본문 바로가기
Spring

FeignClient 정리

by SuldenLion 2025. 5. 21.
반응형

 

ㅇ 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가 유리

- 대용량 처리 또는 파일 업로드 등에서는 성능 이슈 고려 필요

 

 

 

 

반응형

댓글