본문 바로가기
개발/Spring Cloud

[Spring Cloud] 마이크로서비스간 통신 (RestTemplate vs FeignClient)

by baau 2023. 6. 22.

마이크로서비스 간 통신

  • 모놀리식 애플리케이션은 단순하게 메서드를 호출함으로 써, 요청에 대해 응답을 처리할 수 있었다.
  • 하지만, 분산 시스템에서 각각의 독립적인 Micro Service가 서로 통신하는 작업이 필요하다.
  • 마이크로서비스 간 통신은 주로 HTTP기반 Restful API를 사용하여 이루어진다.

https://www.nginx.com/blog/building-microservices-inter-process-communication/

 

RestTemplate vs FeignClient

RestTemplate

  • Spring Framework에서 제공하는 HTTP 클라이언트
  • 다른 서비스로의 HTTP 요청을 수행하고 응답을 받아올 수 있다.

 

장단점

  • 장점
    • 다양한 HTTP 메서드를 지원하고, 요청을 다양한 방식으로 커스터마이즈 할 수 있다.
    • 오랜 기간 동안 사용되어 왔기 때문에, 많은 개발자들에게 익숙하다.
    • 많은 커스터마이즈를 제공해 복잡한 통신 시나리오를 다룰 수 있다.
  • 단점
    • 작성할 코드가 많다.
    • 동기식 방식으로 동작한다.
    • 가독성과 유지보수성을 해칠 가능성이 있다.

 

사용방법

1) RestTemplate 빈 등록

@SpringBootApplication
public class XXXServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(XXXServiceApplication.class, args);
	}
	
	@Bean
	@LoadBalanced
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}
}
  • RestTemplate를 빈 등록해서, 실제 RestTemplate를 사용하는 클래스에서 주입을 받아 사용한다.
  • @LoadBalanced 어노테이션을 통해, Micro Service와 통신 시 IP 주소 체계가 아닌 Mircroservice name으로 요청할 수 있다.
    • http://127.0.0.1:8000/order-service/%s/orders  http://order-service/order-service/%s/orders

 

2) RestTemplate 사용하여 다른 Mirco Service에게 요청

public void example() {

    String requestUrl = String.format("http://user-service/user-service/%s/profile", userId);

    ResponseEntity<ProfileResponse> response = restTemplate.exchange(
            url, // 요청 URL
            HttpMethod.GET, // 요청 메서드
            null, // 요청 본문
            ProfileResponse.class // 응답 타입
    );
}
  • restTemplate.exchange
    • HTTP 메서드, 요청 URL, 요청 본문, 응답 타입 등을 지정할 수 있어 더욱 유연한 요청을 처리할 수 있다.

 

FeignClient

  • Restful API 호출을 추상화한 Spring Cloud Netflix 라이브러리
  • HTTP API 클라이언트를 단순화하는 것을 목표로 하고, 실제 인터페이스와 어노테이션을 적용하는 간단한 방법으로 사용 가능하다.
  • 모놀로식 애플리케이션에서 메서드를 호출하는 것과 겉보기에 비슷하게 보일 수 있다.

 

장단점

  • 장점
    • 간단하고 선언적인 방식으로 구현 가능하다.
    • @FeignClient 어노테이션과 인터페이스를 사용하여 클라이언트를 정의하고, 메서드를 호출하는 방식으로 통신할 수 있다.
    • 내장된 로드 밸런싱 기능과 서비스 디스커버리를 활용할 수 있다.
    • 요청 및 응답에 대한 로깅, 오류 처리, 보안 등을 쉽게 구현할 수 있다.
  • 단점
    • 상대적으로 새로운 기술이므로, RestTemplate에 비해 사용자들이 덜 익숙할 수 있다.
    • 자동 설정과 기본 설정이 일부 한정적일 수 있으며, 일부 특정한 사용 사례에는 제약이 있을 수 있다.

 

사용방법

1) 의존성 주입과 @EnableFeignClients 추가

implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
@SpringBootApplication
@EnableFeignClients
public class XXXServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(XXXServiceApplication.class, args);
	}
}
  • @EnableFeignClients
    • FeignClient를 사용하기 위해서는 필수적으로 적용해야 한다.
    • 하위 클래스에서 @FeignClient를 찾아 구현체를 생성하는 역할을 한다.

 

 

2) interface 생성 (user-service와 통신하기 위한 클라이언트 인터페이스 UserServiceClient)

@FeignClient(name="user-service")
public interface UserServiceClient {
	
    @GetMappling("/user-service/{userId}/profile")
    ProfileResponse getProfile(@PathVariable String userId);
}
  • @FeignClient(name="user-service")
    • user-service라는 이름의 Mirco Serivce와 통신할 수 있는 Feign 클라이언트를 나타낸다.
    • name 값을 통해 서비스 디스커버리에서 해당 마이크로서비스를 식별하는 데 사용한다.
  • @GetMappling("/user-service/{userId/profile")
    • user-service라는 Mirco Service의 엔드포인트 ("/user-service/{userId/profile")로 GET 요청을 보내는 역할

FeignClient는 런타임 시에 해당 인터페이스의 메서드를 자동으로 구현하여 HTTP 요청을 처리하고 응답을 반환한다.

 

 

3) 서비스 로직에서 클라이언트 객체를 주입받아 사용하기

@Service
@RequiredArgsConstructor
public class XXXSerivce {

    private final UserServiceClient userServiceClient;

    public ResponseProfile getProfile(String userId) {
        
        ...
        ResponseProfile responseProfile = userServiceClient.getProfile(userId);
		
        return responseProfile;
    }
}
  • 실제 다른 클래스의 메서드를 호출하는 것과 비슷하게 MSA 간의 통신을 할 수 있다.

 

- 추후 일정

FeignClient는 이외에도 로깅, 예외처리 등 다양한 기능을 제공한다. FeignClient가 제공하는 기능들에 대해서는 실제 프로젝트에 FeignClient를 도입한 이유에 사용 예시들에 대해서 포스팅하려 한다.