MSA 프로젝트를 진행하면서, 서비스 간 통신이 필요한 상황이 발생했다. 이를 해결하기 위해 HTTP 클라이언트를 찾아본 결과 RestTemplate, FeignClient, WebClient, RestClient 네 가지 방식이 존재했다.
각 방식의 특징과 장단점을 비교한 후, 우리의 요구사항에 가장 적합한 방법을 선택했다.
우리의 경우 MSA에서 서비스 간 호출이 목적이므로, FeignClient를 사용하기로 결정했다.
RestTemplate (Spring 5 이전 사용)
개발이 중단되었으며, RestClient 사용을 권장한다.
RestTemplate은 Spring 5 이전까지 사용되던 동기식 HTTP 클라이언트로,
Spring Boot 3.2 이상에서는 RestClient 사용이 권장된다.
특징
- 동기 방식(Blocking IO)
- 멀티 스레드 환경에서 사용 가능
- API가 직관적이지만 최신 트렌드에는 맞지 않음
예제 코드
@Service
public class RestTemplateService {
private final RestTemplate restTemplate = new RestTemplate();
public String callExternalApi() {
String url = "https://jsonplaceholder.typicode.com/posts/1";
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
return response.getBody();
}
}
설명
- getForEntity()를 사용해 외부 API를 호출하고, 응답을 String으로 반환한다.
- 동기 방식이므로 API 응답이 완료될 때까지 블로킹된다.
FeignClient (Spring Cloud 제공)
개발이 중단되었지만, MSA 환경에서는 여전히 유용하다
FeignClient는 Spring Cloud에서 제공하는 선언적 HTTP 클라이언트로,
인터페이스만 선언하면 구현 없이 API를 호출할 수 있다.
특징
- 인터페이스 기반 선언적 HTTP 클라이언트
- Spring Cloud와 쉽게 통합 (e.g., Eureka, Load Balancer)
- MSA 환경에서 서비스 간 호출을 단순화
사용 추천 상황
- 마이크로서비스 간 REST API 호출이 필요한 경우
- Spring Cloud Eureka, Load Balancer 등과 연동해야 하는 경우
예제 코드
// Eureka를 사용중이라면 Eureka에 등록된 서비스 이름만 적어주면 된다.
@FeignClient(name = "externalService", url = "https://jsonplaceholder.typicode.com")
public interface FeignClientService {
@GetMapping("/posts/{id}")
String getPost(@PathVariable("id") Long id);
}
설명
- name만 지정하면 Eureka를 통해 자동으로 서비스 위치를 찾을 수 있다.
- url을 명시하지 않아도 Eureka가 해당 서비스의 위치(IP 및 포트)를 자동으로 해결한다.
WebClient (Spring WebFlux 제공)
Spring WebFlux에서 제공하는 비동기 HTTP 클라이언트
WebClient는 비동기(reactive) 방식으로 요청을 처리할 수 있는 HTTP 클라이언트이다.
필요할 경우 block()을 사용해 동기 방식으로도 처리할 수 있다.
특징
- 비동기(reactive) 방식으로 요청 처리 가능
- block()을 사용하면 동기 방식 호출도 가능
- WebFlux 기반 프로젝트에서 권장
사용 추천 상황
- 비동기(reactive) 프로그래밍이 필요한 경우
- WebFlux 기반 프로젝트에서 API 호출이 필요한 경우
예제 코드
@Service
public class WebClientService {
private final WebClient webClient;
public WebClientService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
public String getPost(Long id) {
return webClient.get()
.uri("/posts/{id}", id)
.retrieve()
.bodyToMono(String.class)
.block(); // 동기식 처리
}
}
설명
- retrieve()를 사용해 HTTP 응답을 가져온다.
- block()을 사용하면 동기 방식으로도 처리할 수 있다.
RestClient (Spring Boot 3.2 이상)
RestTemplate과 WebClient의 장점을 결합한 최신 HTTP 클라이언트
Spring Boot 3.2에서 새롭게 추가된 RestClient는 RestTemplate과 WebClient의 장점을 결합한 방식으로,
직관적인 API를 제공하면서도 동기 & 비동기 방식을 모두 지원한다.
특징
- RestTemplate과 유사한 직관적인 API 제공
- 동기 & 비동기 방식 모두 지원
- Spring Boot 3.2 이상에서 사용 가능
사용 추천 상황
- 최신 Spring Boot 3.2 이상 프로젝트에서 HTTP 호출이 필요한 경우
예제 코드
@Service
public class RestClientService {
private final RestClient restClient;
public RestClientService(RestClient.Builder restClientBuilder) {
this.restClient = restClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").build();
}
public String getPost(Long id) {
return restClient.get()
.uri("/posts/{id}", id)
.retrieve()
.body(String.class);
}
}
설명
- retrieve()를 사용해 HTTP 응답을 가져온다.
- 동기 방식과 비동기 방식 모두 지원한다.
결론
우리는 마이크로서비스 간 호출을 단순하고 간편하게 처리하기 위해 FeignClient를 사용하기로 결정했다.
FeignClient는 선언적 인터페이스 방식으로 구현 부담이 적으며, Spring Cloud Eureka와 통합이 용이하여 MSA 환경에서 효율적이다.
다만, FeignClient는 개발이 중단되어 유지보수 상태이므로 추후 Spring Cloud LoadBalancer와 RestClient를 활용하는 방식도 고려해볼 계획이다.
'Java , Spring > Spring' 카테고리의 다른 글
[MSA] Orchestration 기반 SAGA 패턴을 활용한 분산 트랜잭션 처리 (1) | 2025.03.02 |
---|---|
[MSA] MSA 환경에서의 분산 트랜잭션 처리(2PC, SAGA) (3) | 2025.02.23 |
[Spring Cloud] Spring Cloud Gateway (그리고 Zuul 와 Netty) (2) | 2025.01.21 |
[Spring] JWT 검증 방법 (대칭키, 비대칭키) (0) | 2025.01.16 |
[Spring] Spring Security 예외를 @ControllerAdvice에서 처리하기 (0) | 2024.12.13 |
댓글