최근 인터페이스 사용이 잦아지며, 인터페이스가 아닌 코드를 인터페이스화 하는 작업을 하고 있다.
그러다 가끔 HttpClient와 IHttpClientFactory 처럼, 사용되는 변수와 들어가는 인스턴스의 형식이 다른걸 발견하게 된다.
궁금해서 왜 그런지 찾아보았는데, 결국 들어가는건 같은 형이 되었기 때문에 상관 없었지만, 조금 더 알아보았다.
그리고 차이를 찾았는데, 우리 회사에 있는 코드는 아래와 같다.
현재 사용중인 코드
public class MyService
{
private readonly HttpClient _httpClient;
public MyService(IHttpClientFactory httpClientFactory)
{
_httpClient = httpClientFactory.CreateClient();
}
public async Task<string> GetAsync(string url)
{
var response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
위와 같이 되면 _httpClient에 HttpClient 생성자를 저장하게 된다. 그러므로 HttpClient 생성자는 항상 살아있는 것이다.
하지만 이는 나중에 IHttpClientFactory가 나오게 된 이유에 반하게 된다.
.NET Core 2.1부터 IHttpClientFactory 인터페이스가 도입되었는데, HttpClient에 문제가 있기 때문이다.
HttpClient를 잘못 사용할 경우 리소스 낭비와 성능에 문제가 발생할 수 있는데, 이 인스턴스를 요청마다 생성하고 폐기하는 패턴에서 소켓 고갈 문제가 있을 수 있다고 한다. 왜냐하면 각 인스턴스가 폐기될 때마다 사용하던 소켓이 즉시 해제되지 않고, TIME_WAIT 상태로 남아있기 때문이다. 이러한 문제를 방지하기 위해 HttpClient를 재사용하는 것이 권장되지만, 이 경우에도 DNS 변경을 자동으로 감지하지 못하는 문제가 있을 수 있다.
그래서 IHttpClientFactory가 나오게 되었고, 인스턴스의 생성, 구성, 수명 관리를 담당하게 되었다. IHttpClientFactory가 위의 문제점을 효과적으로 해결할 수 있기 때문이다.
IHttpClientFactory의 장점
- HttpClient 인스턴스 관리: IHttpClientFactory는 내부적으로 HttpClient의 인스턴스 풀을 관리하여 필요할 때마다 인스턴스를 재사용함으로써 성능을 개선하고 소켓 고갈 문제를 방지할 수 있다.
- DNS 변경 감지: IHttpClientFactory를 사용하면 DNS 변경 사항을 자동으로 감지하고, 새 IP 주소로 요청을 보낼 수 있다. 이는 HttpClient를 장기간 재사용할 때 중요하다.
- 중앙 집중식 구성: IHttpClientFactory를 사용하면 모든 HttpClient 인스턴스에 대한 구성을 중앙에서 관리할 수 있다. 이를 통해 로깅, 인증 토큰 추가 등의 공통 로직을 쉽게 적용할 수 있다.
- 명시적 종속성 주입: IHttpClientFactory는 ASP.NET Core의 종속성 주입 시스템과 통합되어 HttpClient 인스턴스를 필요로 하는 클래스에 IHttpClientFactory 를 주입하여 사용할 수 있다.
따라서 위의 사용중인 코드가 아닌 아래의 코드처럼 작성하여야 IHttpClientFactory를 제대로 사용한다고 할 수 있겠다.
앞으로 지향해야 할 코드
private readonly IHttpClientFactory _httpClientFactory;
public MyService(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory; // httpClientFactory 인스턴스를 저장
}
public async Task<HttpResponseMessage> GetAsync(string url)
{
var httpClient = _httpClientFactory.CreateClient(); // 필요할 때마다 HttpClient 인스턴스를 생성
return await httpClient.GetAsync(url);
}
각 메소드에서 필요할 때 마다 HttpClient 인스턴스를 생성하여 사용하는 것이다.
'C#' 카테고리의 다른 글
[C#, Dart] Dart와 C#에서의 변경 불가능한 변수: `final`과 `readonly` 비교 (0) | 2024.07.01 |
---|---|
[C#] 형 변환에 대하여 (for string 그리고 메모리 관점) (0) | 2024.04.17 |
[C#] 명시적 & 묵시적 형변환 (0) | 2023.11.10 |
[C#] JSON 데이터를 beautify(예쁘게 정렬하여 가독성을 높이는 것)하고 indent(들여쓰기)하는 방법 (0) | 2023.07.28 |
[C#] 요소가 null일 때 처리하는 방법 (0) | 2023.07.27 |
댓글