Merge pull request 'RestTemplateConfig 수정' (#18) from feat/infer_dev_260107 into develop

Reviewed-on: #18
This commit was merged in pull request #18.
This commit is contained in:
2026-01-30 14:44:05 +09:00
2 changed files with 27 additions and 47 deletions

View File

@@ -7,66 +7,42 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
@RequiredArgsConstructor
@Component @Component
@Log4j2 @Log4j2
@RequiredArgsConstructor
public class ExternalHttpClient { public class ExternalHttpClient {
private final RestTemplate restTemplate; private final RestTemplate restTemplate;
private final com.fasterxml.jackson.databind.ObjectMapper objectMapper;
public <T> ExternalCallResult<T> call( public <T> ExternalCallResult<T> call(
String url, HttpMethod method, Object body, HttpHeaders headers, Class<T> responseType) { String url, HttpMethod method, Object body, HttpHeaders headers, Class<T> responseType) {
HttpEntity<Object> entity = new HttpEntity<>(body, headers); if (headers == null) headers = new HttpHeaders();
headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);
headers.setAccept(java.util.List.of(org.springframework.http.MediaType.APPLICATION_JSON));
// 요청 로그 try {
log.info("[HTTP-REQ] {} {}", method, url); if (body != null) {
if (body != null) { log.info("[HTTP-REQ-BODY-JSON] {}", objectMapper.writeValueAsString(body));
log.debug("[HTTP-REQ-BODY] {}", body); }
} catch (Exception e) {
log.warn("[HTTP-REQ-BODY-JSON] serialize failed: {}", e.getMessage());
} }
HttpEntity<Object> entity = new HttpEntity<>(body, headers);
try { try {
ResponseEntity<T> res = restTemplate.exchange(url, method, entity, responseType); ResponseEntity<T> res = restTemplate.exchange(url, method, entity, responseType);
return new ExternalCallResult<>(res.getStatusCodeValue(), true, res.getBody(), null);
int code = res.getStatusCodeValue(); } catch (HttpStatusCodeException e) {
return new ExternalCallResult<>(
// 응답 로그 e.getStatusCode().value(), false, null, e.getResponseBodyAsString());
log.info("[HTTP-RES] {} {} -> {}", method, url, code);
log.debug("[HTTP-RES-BODY] {}", res.getBody());
return new ExternalCallResult<>(code, code >= 200 && code < 300, res.getBody());
} catch (HttpClientErrorException.NotFound e) {
log.info("[HTTP-RES] {} {} -> 404 (Not Found)", method, url);
log.debug("[HTTP-RES-BODY] {}", e.getResponseBodyAsString());
return new ExternalCallResult<>(404, false, null);
} catch (HttpClientErrorException e) {
// 기타 4xx
log.warn(
"[HTTP-ERR] {} {} -> {} body={}",
method,
url,
e.getStatusCode().value(),
e.getResponseBodyAsString());
throw e;
} catch (HttpServerErrorException e) {
// 5xx
log.error(
"[HTTP-ERR] {} {} -> {} body={}",
method,
url,
e.getStatusCode().value(),
e.getResponseBodyAsString());
throw e;
} }
} }
public record ExternalCallResult<T>(int statusCode, boolean success, T body) {} public record ExternalCallResult<T>(int statusCode, boolean success, T body, String errBody) {}
} }

View File

@@ -4,6 +4,7 @@ import lombok.extern.log4j.Log4j2;
import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
@@ -13,10 +14,13 @@ public class RestTemplateConfig {
@Bean @Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) { public RestTemplate restTemplate(RestTemplateBuilder builder) {
SimpleClientHttpRequestFactory f = new SimpleClientHttpRequestFactory(); SimpleClientHttpRequestFactory baseFactory = new SimpleClientHttpRequestFactory();
f.setConnectTimeout(2000); baseFactory.setConnectTimeout(2000);
f.setReadTimeout(3000); baseFactory.setReadTimeout(3000);
return builder.requestFactory(() -> f).additionalInterceptors(new RetryInterceptor()).build(); return builder
.requestFactory(() -> new BufferingClientHttpRequestFactory(baseFactory))
.additionalInterceptors(new RetryInterceptor())
.build();
} }
} }