티스토리 뷰
최근에 있었던 사내 엔지니어링 데이에서 발표를 하였는데, 상당히 편리하지만 많은 분들이 모르시는 OpenFeign을 준비하였습니다. 그리고 발표하면서 준비했던 내용을 블로그 포스팅에서도 적어두었습니다. 아래의 내용은 Spring Cloud OpenFeign 공식 문서를 기반으로 개인적인 경험을 더해 작성한 내용입니다.
1. OpenFeign이란? Open Feign 소개 및 역사
[ OpenFeign이란? ]
Open Feign은 Netflix에 의해 처음 만들어진 Declarative(선언적인) HTTP Client 도구로써, 외부 API 호출을 쉽게할 수 있도록 도와준다. 여기서 “선언적인” 이란 어노테이션 사용을 의미하는데, Open Feign은 인터페이스에 어노테이션들만 붙여주면 구현이 된다. 이러한 방식은 Spring Data JPA와 유사하며, 상당히 편리하게 개발을 할 수 있도록 도와준다.
@FeignClient(name = "ExchangeRateOpenFeign", url = "${exchange.currency.api.uri}")
public interface ExchangeRateOpenFeign {
@GetMapping
ExchangeRateResponse call(
@RequestHeader String apiKey,
@RequestParam Currency source,
@RequestParam Currency currencies);
}
[ OpenFeign의 역사 ]
OpenFeign의 초기 모델인 Feign은 Eureka, Ribbon 등을 포함하는 Netflix OSS 프로젝트의 일부로써 Netflix에 의해 만들고 공개되었다. Netflix OSS가 공개되고 나서 Spring Cloud 진영은 Spring Cloud Netflix라는 프로젝트로 Netflix OSS를 Spring Cloud 생태계로 포함시켰는데, Feign은 단독으로 사용될 수 있도록 별도의 starter로 제공되었다.
이후에 넷플릭스는 내부적으로 feign의 사용 및 개발을 중단하기로 결정하였고, OpenFeign이라는 새로운 이름과 함께 오픈소스 커뮤니티로 넘겨졌다. Spring Cloud는 Open Feign 역시 스프링 클라우드 생태계로 통합하였고, 이 과정에서 기존의 Feign 자체 어노테이션과 JAX-RS 어노테이션만 사용 가능했던 부분을 Spring MVC 어노테이션을 지원하도록 추가했다. 그리고 추가적으로 Spring에서 사용되는 것과 동일한 HttpMessageConverters를 사용하도록 확장하였다. 그 외에도 다른 Spring Cloud 기술인 Eureka, CircuitBreaker, LoadBalancer를 통합하여 load-balanced된 http client를 제공하고자 하였다.
Netflix OSS → Spring Cloud Netflix → Open Feign → Spring Cloud Open Feign
[ OpenFeign의 장점 ]
- 인터페이스와 어노테이션 기반으로 작성할 코드가 줄어들음
- 익숙한 Spring MVC 어노테이션으로 개발이 가능함
- 다른 Spring Cloud 기술들(Eureka, Circuit Breaker, LoadBalancer) 과의 통합이 쉬움
OpenFeign의 가장 큰 장점은 인터페이스와 어노테이션 기반으로 작성할 코드가 줄어든다는 것이다. 아래의 코드는 환율 조회 API를 RestTemplate으로 작성한 것인데, 요즘 같이 API 호출이 잦은 MSA의 시대에서 이런 코드를 반복한다는 것은 번거롭다.
@Component
@RequiredArgsConstructor
class ExchangeRateRestTemplate {
private final RestTemplate restTemplate;
private final ExchangeRateProperties properties;
private static final String API_KEY = "apikey";
public ExchangeRateResponse call(final Currency source, final Currency target) {
return restTemplate.exchange(
createApiUri(source, target),
HttpMethod.GET,
new HttpEntity<>(createHttpHeaders()),
ExchangeRateResponse.class)
.getBody();
}
private String createApiUri(final Currency source, final Currency target) {
return UriComponentsBuilder.fromHttpUrl(properties.getUri())
.queryParam("source", source.name())
.queryParam("currencies", target.name())
.encode()
.toUriString();
}
private HttpHeaders createHttpHeaders() {
final HttpHeaders headers = new HttpHeaders();
headers.add(API_KEY, properties.getKey());
return headers;
}
}
위의 코드를 OpenFeign으로 작성하면 아래의 코드로 끝이다. OpenFeign으로 코드를 작성하면 생산성이 상당히 높아질 것이라는 장점은 직접 쳐보지 않아도 느낄 수 있을 것이다.
@FeignClient(name = "ExchangeRateOpenFeign", url = "${exchange.currency.api.uri}")
public interface ExchangeRateOpenFeign {
@GetMapping
ExchangeRateResponse call(
@RequestHeader String apiKey,
@RequestParam Currency source,
@RequestParam Currency currencies);
}
[ OpenFeign의 단점 및 한계 ]
- 기본 Http Client가 Http2를 지원하지 않음 → Http Client에 대한 추가 설정 필요
- 공식적으로 Reactive 모델을 지원하지 않음 → 비공식 오픈소스 라이브러리로 사용 가능
- 경우에 따라서 애플리케이션이 뜰 대 초기화 에러가 발생할 수 있음 → Object Provider로 대응 필요
- 테스트 도구를 제공하지 않음 → 별도의 설정 파일을 작성하여 대응 필요
다른 부분보다 테스트 도구를 제공하지 않는다는 점은 꽤나 치명적이다. 왜냐하면 어노테이션과 인터페이스 기반으로 프로그래밍하는 만큼 테스트를 통해 코드에 문제가 없는지, API 호출이 정상적으로 되는지 빠르게 확인할 필요가 있기 때문이다. 그래서 테스트 작성을 위한 설정 부분은 이어지는 포스팅에서 보완할 예정이다.
2. OpenFeign 시작하기
[ OpenFeign 시작하기 ]
1. 의존성 추가하기
Open Feign은 Spring Cloud 기반의 기술이므로 Spring Cloud에 대한 의존성이 필요하다. Spring Cloud 문서를 보면 현재의 Spring Boot 버전에 맞는 버전이 명시되어 있는데, 적합한 버전을 확인한다.
그리고 이를 참고하여 Spring Cloud 의존성을 먼저 추가해줘야 한다. 아래의 예시는 SpringBoot 2.7을 기준으로 작성되었다.
ext {
set('springCloudVersion', "2021.0.4")
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
그리고 Open Feign 의존성을 추가해주면 된다.
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
2. OpenFeign 활성화하기
OpenFeign을 활성화하려면 다른 스프링 부트 기능들과 유사하게 @EnableFeignClients 어노테이션을 붙여주면 된다. OpenFeign을 활성화하려면 기본적으로 main 클래스에 붙여주면 된다.
@EnableFeignClients
@SpringBootApplication
public class OpenFeignSampleApplication {
public static void main(String[] args) {
SpringApplication.run(OpenFeignSampleApplication.class, args);
}
}
하지만 Main 클래스에 @Enable 어노테이션을 붙여주는 것은 SpringBoot가 제공하는 테스트에 영향을 줄 수 있다. 그러므로 별도의 Config 파일로 만들어주는 것이 좋다. (이와 관련해서 모르시는 분은 이 포스트를 참고해주세요!)
별도의 파일로 설정할 경우에는 feign 인터페이스들의 위치를 반드시 지정해주어야 하는데, componentScan 처럼 baseBackes로 지정해주거나, clients로 직접 클래스들을 지정해줘도 된다. 일반적으로 아래와 같이 패키지로 지정하면 된다.
@Configuration
@EnableFeignClients("com.mangkyu.openfeign")
class OpenFeignConfig {
}
3. FeignClient 구현하기
API 호출을 수행할 클라이언트는 인터페이스에 @FeignClient 어노테이션을 붙여주면 된다. 그리고 value와 url 설정이 필요한데 url에는 호출할 주소를, value에는 임의의 client의 이름을 적어주면 된다. value는 다른 스프링 클라우드와의 통합 시에 SpringCloud LoadBalancer Client를 만드는 데 사용된다는데 중요하지 않으므로 넘어가도 되지만, 필수값이므로 반드시 입력해주어야 한다. value와 url에는 placeholder가 사용가능하므로 프로퍼티에 작성해둔 값을 사용하면 된다.
@FeignClient(name = "ExchangeRateOpenFeign", url = "${exchange.currency.api.uri}")
public interface ExchangeRateOpenFeign {
@GetMapping
ExchangeRateResponse call(
@RequestHeader String apiKey,
@RequestParam Currency source,
@RequestParam Currency currencies);
}
OpenFeign은 스프링 어노테이션으로 구현이 가능하므로 별도의 학습이 필요없다. 하지만 Open Feign의 기능이 필요해질 수도 있는데, 필요 시에 검색해서 사용하면 된다. 예를 들어 여러 파라미터를 한번에 넘겨주고 싶은 경우에는 @SpringQueryMap 등이 사용 가능하다. 또한 스프링은 아래와 같은 풀네임으로 FeignClient의 빈 이름을 설정하는데, 필요하다면 qualifers로 별칭을 지정할 수 있다.
ex) com.mangkyu.openfeign.app.openfeign.ExchangeRateOpenFeign
만약 동적인 URI로 호출이 필요하다면, 기존에 url에는 아무 값이나 넣고 URI를 파라미터로 사용해 호출해주면 된다.
@FeignClient(name = "ExchangeRateOpenFeign", url = "USE_DYNAMIC_URI")
public interface DynamicUrlOpenFeign {
@GetMapping
ExchangeRateResponse call(
URI uri
@RequestHeader String apiKey,
@RequestParam Currency source,
@RequestParam Currency currencies);
}
OpenFeign을 적용하고 코드로 구현하는 것은 매우 쉽다. 하지만 OpenFeign이 제공하는 기본 설정만으로는 부족한 부분이 있는데, OpenFeign의 추가적인 설정과 관련해서는 다음 포스팅에서 알아보도록 하자.
최근에 있었던 사내 엔지니어링 데이에서 발표를 하였는데, 상당히 편리하지만 많은 분들이 모르시는 OpenFeign을 준비하였습니다. 그리고 발표하면서 준비했던 내용을 블로그 포스팅에서도 적어두었습니다. 아래의 내용은 Spring Cloud OpenFeign 공식 문서를 기반으로 개인적인 경험을 더해 작성한 내용입니다. 혹시 추가적인 피드백있으면 편하게 남겨주세요! 감사합니다:)
관련 포스팅
- OpenFeign이란? OpenFeign 소개 및 사용법
- OpenFeign 타임아웃(Timeout), 재시도(Retry), 로깅(Logging) 등 설정하기
- OpenFeign에 Resilence4J 서킷 브레이커 적용하는 방법과 예시 및 주의사항
'Spring' 카테고리의 다른 글
[Spring] POJO 프로그래밍과 스프링 프레임워크의 탄생 (8) | 2022.11.29 |
---|---|
[Spring] OpenFeign 타임아웃(Timeout), 재시도(Retry), 로깅(Logging) 등 설정하기 (11) | 2022.11.22 |
[Spring] 스프링의 트랜잭션 전파 속성(Transaction propagation) 완벽하게 이해하기 (23) | 2022.08.22 |
[Spring] 멀티쓰레드 환경에서 MDC를 사용해 요청 별로 식별가능한 로그 남기기 (14) | 2022.07.25 |
[Spring] @SpringBootTest 테스트 격리시키기(TestExecutionListener를 활용한 H2 데이터베이스 Truncate 초기화) (9) | 2022.07.18 |