본문 바로가기

Spring

Spring에서 Feign 사용하기

Feign

  • Netflix에서 개발된 http client binder이다.
  • interface, annotation 작성만 하면 되므로 비교적 간단하게 구현할 수 있다. 
  • 동기 방식으로 동작한다.

시작하기

dependency

build.gradle

implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

pom.xml

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

Application.java

@SpringBootApplication
@EnableFeignClients
public class Application extends SpringBootServletInitializer {
    public static void main(String[] args) { SpringApplication.run(Application.class); }
}

위처럼 main 함수가 있는 클래스에 @EnableFeignClients 어노테이션을 붙여준다.

@EnableFeignClients는 지정된 패키지를 돌아다니면서 @FeignClient를 찾아 구현체를 만든다.

패키지는 basePackages 또는 basePackageClasses 를 통해 지정할 수 있다.

혹은 위 예시처럼 root package에 속성 없이 어노테이션을 붙이면 root package를 돌아다니면서 구현체를 만들어준다.

사용하기

@GetMapping

@FeignClient(name = "student", url = "http://~~~.co.kr")
public interface StudentApi {

    @GetMapping(value = "/api/student/list")
    ApiResponse getStudentList() throws Exception;

}

위는 예시이다.

이렇게 인터페이스로 구현하면 구현체는 자동으로 만들어준다.

GET 메소드로 호출하고 싶은 경우 @GetMapping 어노테이션을 사용한다.

호출하는 api의 응답에 맞게 받아오는 객체를 만들어서 받아주었다.

 

@FeignClient(name = "student", url = "http://~~~.co.kr")
public interface StudentApi {

    @GetMapping(value = "/api/student/{studentId}")
    ApiResponse getStudentByStudentId(@PathVariable("studentId") Long studentId) throws Exception;

}

@PathVariable 예시이다.

여기서 주의해야 할 점은 value 값을 넣어주어야 한다는 것이다.

controller를 작성할 때 보통 @PathVariable Long studentId 이런 식으로 하는데,

여기서는 @PathVariable("studentId") Long studentId 이렇게 value를 꼭 넣어주어야 한다.

 

@FeignClient(name = "student", url = "http://~~~.co.kr")
public interface StudentApi {

    @GetMapping(value = "/api/student/{studentId}")
    ApiResponse getStudentByStudentId(@PathVariable("studentId") Long studentId,
                                    @RequestParam("filters") String filters ) throws Exception;

}

@RequestParam 예시이다.

비슷하게 넣어주면 된다.

나는 여기서 헤맸는데, 나의 경우에는 request parameter가 항상 고정적으로 똑같았기 때문에 쿼리 스트링을 GetMapping의 value에 쌩으로;; 넣어주었다.

이렇게 하면 제대로 받아오지 못하기 때문에 파라미터는 다 @RequestParam으로 넘겨주자.

@RequestMapping

@FeignClient(name = "student", url = "http://~~~.co.kr")
public interface StudentApi {

    @RequestMapping(method = RequestMethod.GET, value = "/api/student/{studentId}")
    ApiResponse getStudentByStudentId(@PathVariable("studentId") Long studentId,
                                    @RequestParam("filters") String filters ) throws Exception;

}

위처럼 @RequestMapping에 메소드를 설정해줘서 할 수도 있다.

@PostMapping

@FeignClient(name = "student", url = "http://~~~.co.kr")
public interface StudentApi {

    @PostMapping(value = "/api/student")
    ApiResponse saveStudent(@RequestBody("StudentDto") String StudentDto) throws Exception;

}

Post 요청은 위와 같이 보낼 수 있다.

@RequestBody 어노테이션을 사용하여 요청의 body에 들어갈 것을 넣어주면 된다.

메소드를 작성할 때 파라미터에 아무 어노테이션도 붙이지 않으면 @RequestBody로 인식한다고 한다.

여기도 마찬가지로 value를 채워주긴 했는데, RequestBody는 value를 채우지 않아도 되는 듯.

 

추가적으로 header, configuration, errorDecoder, retry 등을 더 공부하고 적용해보고 싶다.

 

개인적으로 사용해 봤을 때는 RestTemplate이나 WebClient보다 간단하게 사용할 수 있었다.

WebClient가 꼭 필요한 경우가 아니라면 FeignClient를 사용해도 좋을 것 같다.

 

참고

https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html

https://techblog.woowahan.com/2630/
https://www.baeldung.com/spring-boot-feignclient-vs-webclient

https://velog.io/@byeongju/FeignClient

https://velog.io/@minwest/Spring-Cloud-OpenFeign%EC%9C%BC%EB%A1%9C-API-%ED%98%B8%EC%B6%9C%ED%95%B4%EB%B3%B4%EA%B8%B0