Time does not change us. It just unfolds us.

Web/Front

[Web]Feign Client

소젬 2021. 10. 22. 13:43

이번 프로젝트에서 FeignClient를 이용하여 개발해서 개념을 이해하고자 공부해보았다.

특히 공통 헤더를 추가하기 위해 커스터마이즈한 Configuration을 설정하는 부분에 대해 정리하였다.

 

Feign Client란?

1) Feign Client는 web service 클라이언트를 보다 쉽게 작성할 수 있도록 도와줌.

2) interface를 작성하고 annotation을 붙여주면 세부적인 내용 없이 사용할 수 있기 때문에 코드 복잡도가 낮아짐.

3) Netflix 에서 만들어진 Http client binder

4) spring-cloud-starter-openfeign으로 스프링 라이브러리에서 사용할 수 있음.

 

feign client 라이브러리 넣기

<!-- maven (pom.xml) -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>3.0.3</version>
</dependency>
 
 
<!-- gradle(build.gradle) -->
 
dependencyManagement {
    imports {
        mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Greenwich.RELEASE'
    }
}
 
dependencies {
//...
    // Feign Client
    compile 'org.springframework.cloud:spring-cloud-starter-openfeign'
//...
}

 

Application.java 파일에 annotation 작성

@EnableFeignClients 을 작성하여 Feign Client 사용할 것임을 알려줌

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
 
import java.util.Arrays;
 
@Slf4j
@EnableCaching
@EnableFeignClients
@ServletComponentScan
@SpringBootApplication
@ComponentScan("com.poscoict.posmaster")
public class Application {
 
    public static void main(String[] args) {
        Arrays.stream(args)
              .forEach(log::debug);
 
        SpringApplication.run(Application.class, args);
    }
}

인터페이스로 Client 작성

annotation을 통해 요청할 url을 설정함

import com.poscoict.posmaster.client.config.HeaderConfiguration;
import com.poscoict.posmaster.model.dto.ApiResponse;
import com.poscoict.posmaster.model.dto.shared.SharedDetailResponse;
import com.poscoict.posmaster.model.dto.shared.SharedPageResponse;
import com.poscoict.posmaster.model.dto.shared.SharedRequest;
import com.poscoict.posmaster.model.entity.App;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
 
@FeignClient(name = "shared-api", url = "http://localhost:1323/api/v1", configuration = HeaderConfiguration.class)
public interface SharedClient {
 
    @GetMapping("/pshm/list")
    SharedPageResponse findSharedPageList(@RequestParam("offset") int offset, @RequestParam("limit") int limit);
 
    @DeleteMapping("/pshm/delete")
    ApiResponse deleteShared(@RequestParam("name") String name);
 
    @PutMapping(value = "/pshm/update", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    ApiResponse modifyShared(@RequestParam("name") String name, @RequestParam("size") int size, @RequestParam("sender") String sender, @RequestParam("receiver") String receiver, @RequestParam("filedel") String filedel, @RequestPart(value = SharedRequest.MULTIPART_PARAM) MultipartFile file);
 
    @PostMapping(value = "/pshm/write", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    ApiResponse modifyTagValue(@RequestParam("name") String tagName, @RequestParam("value") int value);
}

기본설정 값 및 Configuration

  • feign 를 하다보면, 기본으로 설정되는 bean 들이 존재.
  • Spring 을 사용하는 환경이라면, org.springframework.cloud.openfeign.FeignClientsConfiguration.class 에서 어떤 Bean 이 만들어지는지 확인 가능.
  • default 설정을 override 하고 싶다면, configuration 에 설정된 값을 넣으면 됨  
  • 미설정 시 기본적으로 제공하는 설정정보로 사용

  • configuration 을 이용해서 설정하기
    • RequestIntercepor는 공통으로 사용하는 header를 추가하기위해 사용할 수 있음 (그 외 참고)
    • RequestInterceptor는 interface이며 apply 메서드를 정의할 수 있음
    • 원하는 feign client 에 configuration 에 만든 class를 설정.
    • API endpoint 마다 사용하기 위해 여러 feign client를 만드는 경우 서로 다른 설정을 해야 함 
package feign;
 
public interface RequestInterceptor {
    void apply(RequestTemplate var1);
}
import com.poscoict.posmaster.model.SessionUser;
import feign.RequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
 
import javax.servlet.http.HttpServletRequest;
 
public class HeaderConfiguration {
 
    @Bean
    public RequestInterceptor requestInterceptor() {
        return template -> {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
             
            if (requestAttributes != null) {
                HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
 
                if (request != null) {
                    if (request.getSession().getAttribute(SessionUser.TOKEN_KEY) != null) {
                        String token = (String) request.getSession().getAttribute(SessionUser.TOKEN_KEY);
                        template.header(HttpHeaders.AUTHORIZATION, "Bearer " + token);
                    }
                }
            }
        };
    }
}
  • 공식 문서에서 제공하는 기본 설정 Bean
    • @ConditionalOnMissingBean : 해당 Bean은 해당 옵션으로 사용하는 별도의 Bean이없을 때 적용되는 Default라는 의미
      ex) Decoder feignDecoder, feignEncoder, feignLoggerFactory, feignContract, HystrixFeignConfiguration
    • @Bean
      @ConditionalOnMissingBean
      public Decoder feignDecoder() {
          return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
      }
    • Configuration 사용 시 주의사항
    • Configuration class를 생성하다보면 습관적으로 @Configuration으로 설정하기 쉽다.
      하지만 @Configuration으로 설정하게되면 되면 Spring bean으로 등록되어 모든 feign client 대상으로 적용이 된다.
      따라서 모든 feign client에 적용되어야하는 설정은 @Configuration으로 적용되게 하고,
      client 별로 적용되어야 하는 설정은 @FeignClient의 configuration attribute에 명시해서 추가해야한다.


      참고로 같은 설정에 대해서는 @FeignClient의 configuration attribute의 설정으로 덮어씌워진다.

 

참고

Fegin Client 알아보기

우아한 feign 적용기

openfeign 설정 시 주의점

Spring Cloud Feign- 기본 설정편

Feign 적용(주의사항)

 

'Web > Front' 카테고리의 다른 글

[JavaScript]IP input mask  (0) 2021.10.28
[Web]Custom Validator  (0) 2021.10.26
[Web]Freemarker문법  (0) 2021.10.26
[JavaScript]JSON 형식의 문자열과 Encode 함수  (0) 2021.10.25