Spring-Cloud

01. OpenFeign 1

  • -

이번 포스트에서는 Spring Cloud에서 사용되는 OpenFeign에 대해 살펴보자.

 

OpenFeign

 

OpenFeign이란?

Feign은 Netflex에서 개발한 Http Client 라이브러리이다. 나중에 Netflex가 더 이상 유지보수 하지 않고 커뮤니티에서 이어받아 OpenFeign으로 변경되었다.

Feign은 선언적 웹서비스 클라이언트로 이를 이용하면 웹 서비스 클라이언트 작성이 매우 쉬워진다. Feign을 사용하려면 인터페이스를 생성하고 @FeignClient 애너테이션을 추가하면 된다. 다음 코드는 한눈에 봐도 어떤 의도로 작성되었는지 쉽게 파악할 수 있다.

// ❌ 기존 RestTemplate 방식
RestTemplate restTemplate = new RestTemplate();
String url = "https://jsonplaceholder.typicode.com/posts/1";
Post post = restTemplate.getForObject(url, Post.class);

// ✅ OpenFeign 방식
@FeignClient(name = "post-client", url = "https://jsonplaceholder.typicode.com")
interface PostClient {
    @GetMapping("/posts/{id}")
    Post getPost(@PathVariable Long id);
}

// 사용: postClient.getPost(1L);

 

기본 설정

OpenFeign을 사용하기 위해서는 다음의 의존성이 필요하다. 추가로 Spring Web, Lombok, DevTools 도 설정해주자.

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

 

@EnableFeignClient

OpenFeign의 시작은 @Configuration 클래스에 @EnableFeignClient를 추가하는 것으로 시작한다. @EnableFeignClient는 Spring Cloud OpenFeign을 사용하는 외부 서비스와 통신할 때 사용할 Feign Client 인터페이스(@FeignClient 가 선언된)를 찾아내고 활성화 하는 역할을 수행한다. 주요 역할은 다음과 같다.

  • 컴포넌트 스캔 (Component Scanning): 애플리케이션 내에서 @FeignClient 어노테이션이 붙은 인터페이스 스캔
  • 프록시 객체 생성: 찾아낸 인터페이스를 바탕으로 실제 HTTP 요청을 보낼 수 있는 구현체(런타임 프록시 객체)를 자동으로 생성
  • 빈 등록: 생성된 프록시 객체를 스프링 컨테이너에 빈(Bean)으로 등록
@SpringBootApplication
@EnableFeignClients
public class OpenfeignApplication {

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

 

간단한 요청 처리

 

@FeignClient

OpenFeign을 사용하기 위해서는 @FeignClient를 interface에 선언해서 HTTP Client를 생성한다. @FeignClient는 Type에 선언할 수 있으며 상속 된다.

@Target(ElementType.TYPE)
@Inherited
public @interface FeignClient {}

 

다음은 주요 속성들이다.

 

속성 설명 예시
name 클라이언트 이름 (필수) name = "post-client"
url 고정 URL url = "https://jsonplaceholder.typicode.com"
configuration 커스텀 설정 클래스 configuration = FeignConfig.class
fallback 실패시 대체 구현체 fallback = PostFallback.class

 

다음은 간단한 사용 예이다.

@FeignClient(name = "post-client", url = "https://jsonplaceholder.typicode.com")
public interface PostClient {...}

 

다양한 파라미터 전달 방법

OpenFeign은 기존의 Spring MVC가 가지는 어노테이션을 이용해서 다양한 방법으로 파라미터를 전달할 수 있다. 그냥 똑같다.

- @PathVariable

@GetMapping("/posts/{id}")
Post getPost(@PathVariable Long id);
// 호출: /posts/1

- @RequestParam

@GetMapping("/posts")
List<Post> getPostsByUser(@RequestParam Long userId);
// 호출: /posts?userId=1

- @RequestBody

@PostMapping("/posts")
Post createPost(@RequestBody Post post);

- @RequestHeader

@GetMapping("/posts/{id}")
Post getPost(@PathVariable Long id, 
             @RequestHeader("Authorization") String token);

- @SpringQueryMap - 여러 파라미터를 DTO 형태로 전달

@GetMapping("/posts")
List<Post> searchPosts(@SpringQueryMap SearchParams params);

// SearchParams 클래스
class SearchParams {
    private Long userId;
    private String title;
    // getter, setter
}
// 호출: /posts?userId=1&title=example

 

설정 커스터마이징

 

JavaConfig

다음은 JavaConfig 기반으로 기본 설정을 재정의 하는 코드이다. 대부분 빈 추가 형태로 재정의 한다.

@Configuration
public class FeignConfig {
    
    // 타임아웃 설정
    @Bean
    public Request.Options options() {
        return new Request.Options(
            10, TimeUnit.SECONDS,  // connectTimeout
            60, TimeUnit.SECONDS,  // readTimeout
            true                   // 3xx 응답 시 redirect url로 이동할 것인가?
        );
    }
    
    // 로그 레벨 설정 - request, response 시 정보 출력: BASIC, FULL, HEADERS, NONE
    @Bean
    public Logger.Level loggerLevel() {
        return Logger.Level.FULL;
    }
    
    // 인터셉터 (모든 요청에 헤더 추가)
    @Bean
    public RequestInterceptor requestInterceptor() {
        return template -> {
            template.header("X-Custom-Header", "value");
        };
    }
    
    // 에러 처리
    @Bean
    public ErrorDecoder errorDecoder() {
        return (methodKey, response) -> {
            if (response.status() == 404) {
                return new NotFoundException("게시글을 찾을 수 없음");
            }
            return new Exception("에러 발생");
        };
    }
}

Loger의 Level은 다음과 같다.

 

  • NONE: 로깅 안함
  • BASIC: 요청 메서드, URL, 응답 상태만
  • HEADERS: BASIC + 헤더 정보
  • FULL: 모든 정보 (요청/응답 바디 포함)

 

 

application.properties

설정 파일을 통해서도 일부 속성을 재정의할 수 있다.

spring:
  cloud:
    openfeign:
      client:
        config:
          post-client:  # 특정 클라이언트
            connectTimeout: 5000
            readTimeout: 10000
            loggerLevel: BASIC
            
          default:  # 모든 클라이언트
            connectTimeout: 3000
            readTimeout: 5000
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.