• Home
  • About
    • YUN MIN JUNG photo

      YUN MIN JUNG

      If you don't know where you are going, just go.

    • Learn More
    • LinkedIn
    • Instagram
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Spring Cloud Feign

18 Jun 2021

Reading time ~3 minutes

Spring Cloud Feign

목차

  1. Feign Client 정의
  2. Feign Client 예제
  3. Feign Client 추가 설정(심화)

개요

대부분 서비스들이 API 호출을 RestTemplate 이용해 호출을 하고 있었다.
나는 오히려 RestTemplate 사용하지 않고 Feign Client를 이용해 API 호출을 하는데 더 익숙했다.
새로운 서비스 개발을 하는데 Feign Client를 이용해 호출을 하려고 하기 때문에 Feign Client에 대해서 다시 공부해보려고 한다.


상세

1. Feign Client 정의

Feign은 넷플릭스에서 개발한 웹 서비스 Client Binder 도구.
어노테이션을 붙이고, interface를 선언하여 쉽고 편하게 사용할 수 있다.

2. Feign Client 예제

  1. spring-cloud-starter-openfeign maven 추가
    <properties>
        <java.version>1.8</java.version>
            <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>

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

    </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>
  1. @EnableFeignClients 추가 : @FeignClient를 찾아 구현체를 생성하는 역할
@SpringBootApplication
@EnableFeignClients
public class ParsingApplication {

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

}
  1. @FeignClient 인터페이스 생성
@FeignClient(value = "open-api", url = "http://openapitraffic.daejeon.go.kr/api/rest/busRouteInfo/")
public interface OpenAPIClient {

    @GetMapping("/getRouteInfoAll")
    public String getRouteInfoAll(@RequestParam String serviceKey, @RequestParam String reqPage);

}

Error Message

Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_281]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[na:1.8.0_281]
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355) ~[na:1.8.0_281]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[na:1.8.0_281]
	... 114 common frames omitted

에러 발생 뭔가 못찾는거 같다.

해결방법 : 구글링 해보니 spring cloud reference에 Spring boot와 Spring cloud version을 맞춰줘야 한다고 한다.

spring boot vs spring cloud version

내가 사용하는 spring boot 버전이 2.4.1이므로 맞는 버전으로 수정

 <spring-cloud.version>2020.0.0</spring-cloud.version>

spring cloud version을 바꿔주니 정상 작동한다.

Test 코드

@SpringBootTest
public class FeignClientTest {

    @Autowired
    OpenAPIClient openAPIClient;

    @Test
    void getMethodFeignClientTest() {
        String serviceKey = "ERvgM5YJuigXEYahj%2FZwKcD13pTrKUYUZOwWRuamCJfozqcMh4xyI9iMPTApsOQTzGcTeRJH7KIHmywWmYxe1g%3D%3D";

        String reqPage = "1";

        String response = openAPIClient.getRouteInfoAll(serviceKey, reqPage);

        Assertions.assertNotNull(response);
    }
}

3. Feign Client 추가 설정(심화)

Http Header 세팅 방법

  1. 우선, 헤더 로그를 확인 하기 위해 feign 로그관련 설정을 yml에 추가
    • feign.client.config.default : 모든 Feign Client에 대해서 적용
      • default 대신 @FeignClient 어노테이션 name 속성값으로 지정 시 해당 Feign만 적용
    • feign.client.config.client-name.loggerLevel
      • NONE : 로그 없음
      • BASIC : 요청 Method, URL, 응답상태코드, 실행시간만 출력
      • HEADERS : 요청/응답 헤더 출력
      • FULL : 요청/응답 헤더, 바디, 메타데이터 모두 출력

※ @FeginClient의 패키지가 로깅레벨 DEBUG로 되어있어야 로그가 출력된다.

feign:
  client:
    config:
      default:
        loggerLevel: FULL
logging:
  level:
    com.server.people.xml.parsing.client.OpenAPIClient: DEBUG
  1. RequestInterceptor 인터페이스를 Override하면 공통적으로 header를 세팅할수 있다.
public class FeignConfiguration implements RequestInterceptor {
    
    @Override
    public void apply(RequestTemplate requestTemplate) {

        requestTemplate.header("Authorization", "123456");

        requestTemplate.header("Accept", "application/xml");
    }
}

※ 주의 : @Configuration 붙이지 않기
@Configuration을 붙이면 Spring Bean으로 등록되어 모든 FeignClient에 대해 설정이 적용된다.
FeignClient마다 설정 값들이 달라질수 있기 때문에, @Configuration 어노테이션을 붙이지 않고,
@FeignClient 속성값 configuration에 생성한 config를 추가하여 원하는 Feign Client만 설정을 적용하도록 한다.

  1. @FeignClient 어노테이션 configuration 설정값에 세팅한 config 추가
@FeignClient(value = "${sample.open-api.name}", url = "${sample.open-api.url}", configuration = FeignConfiguration.class)
public interface OpenAPIClient {

    @GetMapping("/getRouteInfoAll")
    public String getRouteInfoAll(@RequestParam String serviceKey, @RequestParam String reqPage);

}

결과 Feign Log : header에 세팅한 거 확인

2021-06-18 15:26:24.690 DEBUG 34577 --- [           main] c.s.p.xml.parsing.client.OpenAPIClient   : [OpenAPIClient#getRouteInfoAll] ---> GET http://openapitraffic.daejeon.go.kr/api/rest/busRouteInfo/getRouteInfoAll?serviceKey=ERvgM5YJuigXEYahj/ZwKcD13pTrKUYUZOwWRuamCJfozqcMh4xyI9iMPTApsOQTzGcTeRJH7KIHmywWmYxe1g%3D%3D&reqPage=1 HTTP/1.1
2021-06-18 15:26:24.691 DEBUG 34577 --- [           main] c.s.p.xml.parsing.client.OpenAPIClient   : [OpenAPIClient#getRouteInfoAll] Accept: application/xml
2021-06-18 15:26:24.691 DEBUG 34577 --- [           main] c.s.p.xml.parsing.client.OpenAPIClient   : [OpenAPIClient#getRouteInfoAll] Authorization: 123456
2021-06-18 15:26:24.691 DEBUG 34577 --- [           main] c.s.p.xml.parsing.client.OpenAPIClient   : [OpenAPIClient#getRouteInfoAll] ---> END HTTP (0-byte body)
2021-06-18 15:26:24.815 DEBUG 34577 --- [           main] c.s.p.xml.parsing.client.OpenAPIClient   : [OpenAPIClient#getRouteInfoAll] <--- HTTP/1.1 406 Not Acceptable (120ms)
2021-06-18 15:26:24.816 DEBUG 34577 --- [           main] c.s.p.xml.parsing.client.OpenAPIClient   : [OpenAPIClient#getRouteInfoAll] content-length: 0
2021-06-18 15:26:24.816 DEBUG 34577 --- [           main] c.s.p.xml.parsing.client.OpenAPIClient   : [OpenAPIClient#getRouteInfoAll] content-type: text/xml
2021-06-18 15:26:24.816 DEBUG 34577 --- [           main] c.s.p.xml.parsing.client.OpenAPIClient   : [OpenAPIClient#getRouteInfoAll] date: Fri, 18 Jun 2021 06:26:05 GMT
2021-06-18 15:26:24.816 DEBUG 34577 --- [           main] c.s.p.xml.parsing.client.OpenAPIClient   : [OpenAPIClient#getRouteInfoAll] server: Apache-Coyote/1.1
2021-06-18 15:26:24.816 DEBUG 34577 --- [           main] c.s.p.xml.parsing.client.OpenAPIClient   : [OpenAPIClient#getRouteInfoAll] <--- END HTTP (0-byte body)

참고

https://woowabros.github.io/experience/2019/05/29/feign.html
https://woowabros.github.io/experience/2019/12/20/feign2.html
https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html#_feign_logging
https://sabarada.tistory.com/116



feign Share Tweet +1