1. 개요

이 예제에서는 Spring Boot 앱용 선언적 REST 클라이언트인 Spring Cloud OpenFeign 에 대해 설명합니다.

Feign 은 Feign 어노테이션 및 JAX-RS 어노테이션을 포함하는 플러그 가능한 어노테이션 지원을 통해 웹 서비스 클라이언트 작성을 더 쉽게 만듭니다.

또한 Spring CloudSpring MVC 어노테이션 및 Spring Web에서 사용되는 것과 동일한 HttpMessageConverters 사용에 대한 지원을 추가합니다.

Feign을 사용할 때 좋은 점 중 하나는 인터페이스 정의 외에 서비스를 호출하기 위한 코드를 작성할 필요가 없다는 것입니다.

2. 의존성

먼저 Spring Boot 웹 프로젝트를 생성 하고 pom.xml 파일 에 spring-cloud-starter-openfeign 의존성을 추가하는 것으로 시작합니다.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

또한 spring-cloud-dependencies 를 추가해야 합니다 .

 <dependencyManagement>
     <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Maven Central 에서 최신 버전의 spring-cloud-starter-openfeignspring-cloud-dependencies 를 찾을 수 있습니다.

3. 의뢰인 척하기

다음으로 @EnableFeignClients 를 기본 클래스에 추가해야 합니다.

@SpringBootApplication
@EnableFeignClients
public class ExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}

이 어노테이션을 사용하여 Feign 클라이언트임을 선언하는 인터페이스에 대한 구성 요소 스캔을 활성화합니다.

그런 다음 @FeignClient 어노테이션 을 사용하여 Feign 클라이언트를 선언합니다 .

@FeignClient(value = "jplaceholder", url = "https://jsonplaceholder.typicode.com/")
public interface JSONPlaceHolderClient {

    @RequestMapping(method = RequestMethod.GET, value = "/posts")
    List<Post> getPosts();

    @RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json")
    Post getPostById(@PathVariable("postId") Long postId);
}

이 예제에서는 클라이언트가 JSONPlaceholder API 에서 읽도록 구성했습니다 .

@FeignClient 어노테이션에 전달 된 인수 는 필수이며 랜덤의 클라이언트 이름이며 url 인수를 사용하여 API 기본 URL을 지정합니다.

또한 이 인터페이스는 Feign 클라이언트이므로 Spring Web 어노테이션을 사용하여 도달하려는 API를 선언할 수 있습니다.

4. 구성

이제 각 Feign 클라이언트가 사용자 지정 가능한 구성 요소 집합으로 구성되어 있음을 이해하는 것이 매우 중요합니다.

Spring Cloud 는 다음 섹션에서 설명하는 대로 사용자 정의할 수 있는 FeignClientsConfiguration 클래스를 사용하여 명명된 각 클라이언트에 대한 요청 시 새 기본 세트를 생성합니다.

위의 클래스에는 다음 빈이 포함됩니다.

  • 디코더 – 응답 을 디코딩하는 데 사용되는 SpringDecoder 를 래핑 하는 ResponseEntityDecoder
  • 인코더 – SpringEncoder 는 RequestBody  를 인코딩하는 데 사용됩니다 .
  • 로거 – Slf4jLogger 는 Feign에서 사용하는 기본 로거입니다.
  • 계약 – 어노테이션 처리를 제공하는 SpringMvcContract
  • Feign-Builder – HystrixFeign.Builder 는 구성 요소를 구성하는 데 사용됩니다.
  • 클라이언트 – LoadBalancerFeignClient 또는 기본 Feign 클라이언트

4.1. 커스텀 빈 구성

이러한 bean 중 하나 이상을 사용자 지정하려는 경우 Configuration 클래스 를 생성하여 재정의 한 다음 FeignClient 어노테이션에 추가할 수 있습니다.

@FeignClient(value = "jplaceholder",
  url = "https://jsonplaceholder.typicode.com/",
  configuration = MyClientConfiguration.class)
public class MyClientConfiguration {

    @Bean
    public OkHttpClient client() {
        return new OkHttpClient();
    }
}

이 예제에서는 HTTP/2를 지원하기 위해 기본 클라이언트 대신 OkHttpClient를 사용하도록 Feign 에 지시합니다.

Feign은 일부 서버에서 기대하는 Content-Length 와 같은 요청과 함께 더 많은 헤더를 보내는 ApacheHttpClient 를 포함하여 다양한 사용 사례에 대해 여러 클라이언트를 지원합니다 .

이러한 클라이언트를 사용하려면 pom.xml 파일 에 필요한 의존성을 추가하는 것을 잊지 마십시오 .

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
</dependency>

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

Maven Central 에서 최신 버전의 feign-okhttpfeign -httpclient를 찾을 수 있습니다.

4.2. 속성을 사용한 구성

Configuration 클래스를 사용하는 대신 다음 application.yaml 예제 와 같이 응용 프로그램 속성을 사용하여 Feign 클라이언트를 구성할 수 있습니다 .

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: basic

이 구성을 사용 하여 애플리케이션에서 선언된 각 클라이언트에 대해 제한 시간을 5초로 설정하고 로거 수준을 기본 으로 설정합니다.

마지막으로 모든 @FeignClient 개체 를 구성하기 위해 기본 클라이언트 이름으로 구성을 만들거나 구성에 대한 가짜 클라이언트 이름을 선언할 수 있습니다.

feign:
  client:
    config:
      jplaceholder:

구성 빈과 구성 속성 이 모두 있는 경우 구성 속성은 구성 빈 값을 재정의합니다.

5. 인터셉터

인터셉터 추가는 Feign에서 제공하는 또 다른 유용한 기능입니다.

인터셉터는 모든 HTTP 요청/응답에 대해 인증에서 로깅에 이르기까지 다양한 암시적 작업을 수행할 수 있습니다.

이 섹션에서는 자체 인터셉터를 구현하고 기본 제공되는 Spring Cloud OpenFeign에서 제공하는 인터셉터를 사용합니다. 둘 다 각 요청에 기본 인증 헤더를 추가합니다.

5.1. RequestInterceptor 구현

사용자 지정 요청 인터셉터를 구현해 보겠습니다.

@Bean
public RequestInterceptor requestInterceptor() {
  return requestTemplate -> {
      requestTemplate.header("user", username);
      requestTemplate.header("password", password);
      requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
  };
}

또한 요청 체인에 인터셉터를 추가하려면 이 빈을 Configuration 클래스에 추가하거나 이전에 본 것처럼 속성 파일에서 선언하기만 하면 됩니다.

feign:
  client:
    config:
      default:
        requestInterceptors:
          com.baeldung.cloud.openfeign.JSONPlaceHolderInterceptor

5.2. BasicAuthRequestInterceptor 사용

또는 Spring Cloud OpenFeign이 제공하는 BasicAuthRequestInterceptor 클래스를 사용할 수 있습니다.

@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
    return new BasicAuthRequestInterceptor("username", "password");
}

그렇게 간단합니다. 이제 모든 요청에는 기본 인증 헤더가 포함됩니다.

6. 히스트릭스 지원

Feign은 Hystrix 를 지원하므로 활성화한 경우 대체 패턴을 구현할 수 있습니다.

폴백 패턴을 사용하면 원격 서비스 호출이 실패할 때 예외를 생성하는 대신 서비스 소비자가 대체 코드 경로를 실행하여 다른 수단을 통해 작업을 수행하려고 시도합니다.

목표를 달성하려면 속성 파일에 feign.hystrix.enabled=true 를 추가하여 Hystrix를 활성화해야 합니다.

이를 통해 서비스가 실패할 때 호출되는 폴백 메서드를 구현할 수 있습니다.

@Component
public class JSONPlaceHolderFallback implements JSONPlaceHolderClient {

    @Override
    public List<Post> getPosts() {
        return Collections.emptyList();
    }

    @Override
    public Post getPostById(Long postId) {
        return null;
    }
}

대체 메서드가 제공되었음을 Feign에 알리려면 @FeignClient 어노테이션 에서 대체 클래스를 설정해야 합니다 .

@FeignClient(value = "jplaceholder",
  url = "https://jsonplaceholder.typicode.com/",
  fallback = JSONPlaceHolderFallback.class)
public interface JSONPlaceHolderClient {
    // APIs
}

7. 로깅

각 Feign 클라이언트에 대해 기본적으로 로거가 생성됩니다.

로깅을 활성화하려면 클라이언트 인터페이스의 패키지 이름을 사용하여 application.propertie 파일 에서 로깅을 선언해야 합니다 .

logging.level.com.baeldung.cloud.openfeign.client: DEBUG

또는 패키지의 특정 클라이언트에 대해서만 로깅을 활성화하려는 경우 전체 클래스 이름을 사용할 수 있습니다.

logging.level.com.baeldung.cloud.openfeign.client.JSONPlaceHolderClient: DEBUG

Feign 로깅은 DEBUG 수준에만 응답합니다.

클라이언트별로 구성할 수 있는 Logger.Level 은 로깅할 양을 나타냅니다.

public class ClientConfiguration {
    
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }
}

선택할 수 있는 네 가지 로깅 수준이 있습니다.

  • NONE – 로깅 없음, 기본값
  • BASIC – 요청 방법, URL 및 응답 상태만 기록
  • HEADERS - 요청 및 응답 헤더와 함께 기본 정보를 기록합니다.
  • FULL – 요청 및 응답 모두에 대한 본문, 헤더 및 메타데이터를 기록합니다.

8. 오류 처리

Feign의 기본 오류 처리기인 ErrorDecoder.default 는 항상 FeignException 을 발생시킵니다 .

이제 이 동작이 항상 가장 유용한 것은 아닙니다. 따라서 던져진 예외를 사용자 정의하기 위해 CustomErrorDecoder 를 사용할 수 있습니다 .

public class CustomErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String methodKey, Response response) {

        switch (response.status()){
            case 400:
                return new BadRequestException();
            case 404:
                return new NotFoundException();
            default:
                return new Exception("Generic error");
        }
    }
}

그런 다음 이전에 수행한 것처럼 Configuration 클래스 에 빈을 추가하여 기본 ErrorDecoder 를 대체해야 합니다.

public class ClientConfiguration {

    @Bean
    public ErrorDecoder errorDecoder() {
        return new CustomErrorDecoder();
    }
}

9. 결론

이 기사에서는 Spring Cloud OpenFeign과 간단한 샘플 애플리케이션에서의 구현에 대해 논의했습니다.

또한 HystrixErrorDecoder 를 사용하여 클라이언트를 구성하고 요청에 인터셉터를 추가하고 오류를 처리하는 방법도 살펴 보았습니다 .

늘 그렇듯이 이 예제에 나오는 모든 코드 샘플은 GitHub 에서 사용할 수 있습니다 .

Cloud footer banner