ㅇ FeignClient란?
- Netflix에서 개발한 HTTP 클라이언트로, 인터페이스 기반의 프로그래밍을 통해 외부 REST 서비스와의 통신을 간단하게 처리할 수 있게 해줌
- 마이크로서비스 아키텍처(MSA) 환경에서 서비스 간의 통신을 간편하게 처리할 수 있도록 도와주는 선언적 HTTP 클라이언트
- Java 진영, 특히 Spring Cloud에서 널리 사용되며, REST API 호출을 마치 로컬 메서드 호출처럼 추상화할 수 있도록 해줌
- Spring Cloud는 Feign을 확장하여 @FeignClient 어노테이션을 제공하고, 이를 통해 서비스 간 통신을 추상화 함
ㅇ 사용 이유
기존 방식 (RestTemplate, WebClient) | Feign 방식 |
요청 URL, 파라미터, HttpMethod 직접 지정 | 메서드 호출처럼 선언만 하면 됨 |
반복되는 boilerplate 코드 많아짐 | 코드 간결해짐 |
예외처리, 로깅, 인증 등 직접 처리 | 공통 정책을 설정으로 분리 가능 |
ㅇ 주요 기능
1. 선언적 REST 클라이언트
- Feign은 REST API를 자바 인터페이스로 선언하고, 해당 인터페이스를 구현하지 않아도 HTTP 요청을 자동으로 수행하게 함
@FeignClient(name = "order-service")
public interface OrderClient {
@GetMapping("/orders/{id}")
OrderDto getOrder(@PathVariable("id") Long id);
}
→ RestTemplate처럼 직접 호출 코드를 작성하지 않아도 REST API를 호출 가능
2. 서비스 디스커버리 연동
- Spring Cloud 환경에서 Eureka 같은 서비스 디스커버리와 연동하여, 실제 URL을 하드코딩하지 않고 서비스 이름 기반으로 호출함.
@FeignClient(name = "inventory-service")
→ inventory-service는 Eureka에 등록된 서비스 이름이며, 부하 분산까지 자동 처리 됨
3. RequestInterceptor (공통 헤더 삽입)
- 모든 요청에 대해 헤더나 인증 정보를 자동으로 추가 가능. 공통 로직을 분리하는 데 유용함
@Component
public class AuthRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
String token = SecurityContextHolder.getContext().getAuthentication().getCredentials().toString();
template.header("Authorization", "Bearer " + token);
}
}
4. Fallback (서킷 브레이커 대체 로직)
- 호출 대상 서비스가 다운되었거나 예외가 발생했을 경우를 대비해 예외 처리용 대체 객체를 정의 가능
@FeignClient(name = "user-service", fallback = UserClientFallback.class)
public interface UserClient {
@GetMapping("/users/{id}")
UserDto getUser(@PathVariable Long id);
}
@Component
public class UserClientFallback implements UserClient {
public UserDto getUser(Long id) {
return new UserDto(id, "Unknown User");
}
}
5. 커스텀 ErrorDecoder
- HTTP 에러 응답을 세분화하여, 커스텀 예외를 던질 수 있도록 지원함
@Component
public class CustomErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
if (response.status() == 404) {
return new NotFoundException("해당 리소스를 찾을 수 없습니다");
}
return new RuntimeException("Feign 오류 발생: " + response.status());
}
}
6. 요청/응답 포맷 커스터마이징 (Encoder/Decoder)
- 기본은 JSON 기반이지만, XML, Form-data 등 다른 포맷도 커스터마이징 가능
@Configuration
public class FeignCustomConfig {
@Bean
public Encoder feignEncoder() {
return new FormEncoder(new SpringEncoder(...));
}
@Bean
public Decoder feignDecoder() {
return new SpringDecoder(...);
}
}
==============================================================================
그리고 FeignClient에 명시
@FeignClient(name = "legacy-service", configuration = FeignCustomConfig.class)
7. 설정 기반 타임아웃/로깅 제어
- 각 클라이언트에 대해 개별적으로 타임아웃, 로깅 레벨 등을 설정 가능
[application.yml]
feign:
client:
config:
user-service:
connectTimeout: 3000
readTimeout: 3000
loggerLevel: full
ㅇ 내부 동작 구조 (Spring Cloud OpenFeign 기준)
▷ 호출 흐름
- @FeignClient 인터페이스 정의
- 애플리케이션 실행 시 Spring Cloud가 해당 인터페이스에 대해 동적 프록시(Proxy) 생성
- 메서드 호출 시 → 프록시 객체가 내부적으로 'Feign.Builder'를 사용해 HTTP 요청 생성
- 내부적으로는 Apache HttpClient, OkHttp, 또는 기본 URLConnection을 사용
- JSON 직렬화/역직렬화는 Jackson, Gson 등 Encoder/Decoder가 담당
▷ 구성 요소
- Contract : 메서드와 어노테이션의 매핑 방식 정의 (SpringMvcContract 사용됨)
- Encoder/Decoder : 요청/응답 변환기. 보통 JacksonEncoder, JacksonDecoder
- Client : 실제 HTTP 클라이언트. ApacheHttpClient, OkHttpClient 등
- RequestInterceptor : 공통 헤더나 토큰 추가 시 사용
- ErrorDecoder : 에러 응답을 예외로 변환
- FallbackFactory : 장애 허용 시 대체 로직 제공 (Resilience4j 연계 가능)
ㅇ 유의할 점
- Fallback이 너무 남용되면 문제를 은폐하게 됨
- 비동기 호출이 필요한 경우 Feign보다는 WebClient가 유리
- 대용량 처리 또는 파일 업로드 등에서는 성능 이슈 고려 필요
'Spring' 카테고리의 다른 글
Spring Batch (스프링 배치) 정리 (1) | 2025.06.15 |
---|---|
스프링 & 스프링 Web MVC 주요 개념 (0) | 2024.06.23 |
서블릿 API 필수적 개념 (세션, 쿠키, 필터, 리스너) (0) | 2023.09.17 |
Spring Tiles (스프링 타일즈) (0) | 2023.07.25 |
웹 페이지 파일(이미지) 업로드 & 페이지네이션 (0) | 2023.07.24 |
댓글