- Netflix에서 개발한 HTTP 클라이언트 라이브러리를 Spring Cloud에서 통합한 선언적 HTTP 클라이언트 라이브러리입니다. - Spring Cloud에서는 OpenFeign을 스프링 MVC 어노테이션을 사용하여 웹 서비스 클라이언트를 쉽게 작성할 수 있도록 통합했습니다. - OpenFeign은 마이크로서비스 아키텍처에서 특히 유용하며, 코드를 더 간결하고 유지보수하기 쉽게 만듭니다.
1. 선언적 REST 클라이언트 - 인터페이스와 어노테이션만으로 HTTP 클라이언트를 구현할 수 있어 코드가 더 간결해집니다.
2. Spring Web 어노테이션 지원 - @GetMapping, @PostMapping 등 개발자에게 친숙한 Spring Web 어노테이션을 그대로 사용할 수 있습니다.
3. 설정의 중앙화 - URL, 인증 정보 등의 설정을 중앙에서 관리할 수 있어 유지보수가 용이합니다.
4. 재사용성 향상 - 정의된 인터페이스를 여러 서비스에서 쉽게 재사용할 수 있습니다.
5. 테스트 용이성 - Mock 객체를 사용한 테스트가 더 쉽고, 인터페이스 기반이라 테스트 코드 작성이 간편합니다.
6. 오류 처리 통합 - ErrorDecoder를 통해 예외 처리를 중앙화하고 일관성 있게 관리할 수 있습니다.
@FeignClient(name = "user-service", url = "<http://api.example.com>")publicinterfaceUserClient {
@GetMapping("/users/{id}")
User getUser(@PathVariable("id") Long id);
@PostMapping("/users")
User createUser(@RequestBody User user);
}
💡 OpenFeign 설정 중앙화 - REST API 통신을 수행할 때, 이와 관련된 설정에 대해서 중앙에서 관리가 가능합니다. - 주요 설정 정보는 타임아웃, 로깅, 인증 및 보안 설정, 재시도 정책, 디코더/인코더 설정, 서킷브레이커 설정에 대해 설정에 대해서 yaml/yml 파일 혹은 Configuration 클래스에서 중앙에서 설정하여 공통적으로 관리할 수 있습니다.
구분
세부 설정
타임아웃 설정 (Timeout)
- connectTimeout: 연결 시도 제한 시간 - readTimeout: 읽기 작업 제한 시간
💡 OpenFeign 설정 중앙화: 타임아웃 설정 - OpenFeign에서 외부 서비스와의 통신 시 발생할 수 있는 API 통신 지연을 제어하는 중요한 설정입니다. 이는 connectTimeout (연결 타임아웃), readTimeout (읽기 타임아웃)으로 나뉩니다. 이에 따르는 타임아웃 예외 처리도 필요합니다.
1. connectTimeout (연결 타임아웃) - 클라이언트가 서버와 연결을 맺는데 허용되는 최대 시간을 지정하며, 네트워크 문제나 서버 응답 지연 시 연결 시도를 제한할 수 있습니다.
2. readTimeout (읽기 타임아웃) - 서버로부터 데이터를 읽는데 허용되는 최대 시간을 의미하며, 서버의 응답이 늦어질 경우 요청을 중단합니다.
- 아래와 같은 OpenFeign에서 전역으로 설정하는 설정 정보를 제공합니다. 1. config.default: 전역으로 설정하는 설정정보를 의미합니다. 2. config.keycloak-auth-client: feignClient 별로 지정을 할 수 있습니다. @FeignClient의 name 속성으로 지정한 값을 참조합니다.
구분
타임아웃 값
의미
connect-timeout
5000ms (5초)
- 클라이언트가 서버와 TCP 연결을 맺는데 허용되는 최대 시간 - 네트워크 연결 수립 과정의 제한 시간 - DNS 조회, TCP handshake 등의 과정 포함
read-timeout
5000ms (5초)
- 서버와 연결된 후 데이터를 주고받는데 허용되는 최대 시간 - 요청을 보낸 후 응답을 받을 때까지의 제한 시간 - 서버의 처리 시간이 긴 경우 고려 필요
spring:cloud:openfeign:client:config:default:connect-timeout:5000# 연결 타임아웃read-timeout:5000# 읽기 타임 아웃keycloak-auth-client:connect-timeout:6000# 연결 타임아웃read-timeout:6000# 읽기 타임아웃
- Java Configuration을 사용하여 OpenFeign의 타임아웃 정책을 설정할 수 있습니다. - @Configuration 어노테이션이 달린 클래스에서 Request.Options를 Bean으로 등록하여 설정합니다. - 전역 설정과 특정 클라이언트별 설정을 모두 구성할 수 있습니다.
설정
설명
connectTimeout
클라이언트가 서버와의 연결을 시도할 때 허용되는 최대 시간을 설정하는 값입니다. 이 시간을 초과하면 연결 시도가 중단됩니다.
readTimeout
서버로부터 데이터를 읽어오는데 허용되는 최대 시간을 설정하는 값입니다. 이 시간을 초과하면 요청이 타임아웃 됩니다.
followRedirects
HTTP 리다이렉션(3xx 응답)을 자동으로 따를지 여부를 결정하는 boolean 값입니다. true로 설정하면 자동 리다이렉션을 수행합니다.
package com.blog.springbootkeycloak.config;
import feign.Request;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
/**
* OpenFeign 타임아웃 정책 설정 환경 파일
*
* @author : jonghoon
* @fileName : FeignClientTimeoutConfig
* @since : 25. 2. 16.
*/@Slf4j@ConfigurationpublicclassFeignClientTimeoutConfig {
/**
* 공통 FeignClient Timeout 정책 설정
*
* @return
*/@Beanpublic Request.Options feignRequestOptions() {
returnnewRequest.Options(
5000, // connectTimeout (5초)
TimeUnit.MILLISECONDS,
5000, // readTimeout (5초)
TimeUnit.MILLISECONDS,
true// followRedirects
);
}
/**
* 특정 FeignClient Timeout 정책 설정
*
* @return
*/@Beanpublic Request.Options customRequestOptions() {
returnnewRequest.Options(
3000, // connectTimeout (3초)
TimeUnit.MILLISECONDS,
3000, // readTimeout (3초)
TimeUnit.MILLISECONDS,
true// followRedirects
);
}
}
💡 Configuration 기반 설정 방법 - Java Configuration을 통해 로깅 설정을 구성할 수 있습니다. - @Configuration 어노테이션이 달린 클래스에서 Logger.Level을 Bean으로 등록하여 설정합니다. - 로깅을 위한 패키지 레벨도 함께 설정해야 합니다.
package com.blog.springbootkeycloak.config.feign;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* OpenFeign 로깅 정책 설정 환경 파일
*
* @author : jonghoon
* @fileName : FeignClientLoggingConfig
* @since : 25. 2. 16.
*/@ConfigurationpublicclassFeignClientLoggingConfig {
/**
* 공통 FeignClient Logging 정책 설정
*
* @return
*/@Bean
Logger.Level customFeignLoggerLevel() {
return Logger.Level.FULL;
}
/**
* 특정 FeignClient Logging 정책 설정
*/@Beanpublic Logger.Level defaultFeignLoggerLevel() {
return Logger.Level.BASIC; // 특정 Feign 클라이언트에 적용될 기본 로깅 레벨
}
}
- OpenFeign를 활용하여 Keycloak 서버로 요청을 하였을 때, 아래와 같이 요청 정보, 응답 정보가 반환이 됩니다. - 응답 상태, 응답 헤더, 응답 값 들이 출력이 잘 됨을 확인하였습니다.이를 통해서 상세한 로그를 통해 API 요청/응답의 전체 과정을 모니터링하고 디버깅할 수 있습니다.
- OpenFeign을 사용하여 외부 API와 통신할 때 보안을 강화하고 인증된 요청을 보내기 위해 사용됩니다. - OpenFeign를 통한 통신을 수행할 때, 모든 Feign Client에 공통으로 인증 헤더를 적용할 수 있습니다. - 예를 들어서 Authorization를 통해서 Bearer 토큰을 전달하거나 커스텀 키 인 x-api-key 형태를 포함하여 전달할 수 있습니다.
- OpenFeign 클라이언트의 인증 및 보안 설정을 yaml 파일에서 중앙 관리할 수 있습니다. - Bearer 토큰, API 키, 커스텀 헤더 등 다양한 인증 정보를 설정할 수 있습니다. - defaultRequestHeaders를 통해 모든 요청에 공통으로 적용될 헤더를 설정할 수 있습니다.또한 클라이언트 별로 각각 인증 정보를 지정할 수 있습니다.
spring:
cloud:
openfeign:
client:
config:
default:
logger-level: full # 전체 모두 기록
defaultRequestHeaders:
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJLbHVfNEVEamQzQnRseUdpaUtabTNFUTF0cXZReDNGOUN0WGxEUXJ0QUpBIn0.eyJleHAiOjE3Mzk1MDI4NjUsImlhdCI6MTczOTQ5OTI2NSwianRpIjoiMTU1MTIyMGMtN2IzMC00MDA4LThlMGUtYWU0ZWZkZjY2OTRlIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo5MDAxL3JlYWxtcy9kZXYtcmVhbG0iLCJhdWQiOlsicmVhbG0tbWFuYWdlbWVudCIsImJyb2tlciIsImFjY291bnQiXSwic3ViIjoiOTcyMDRhYTItMTE2MC00MjQzLTkwM2ItODFiYTJiZTE0ZGUwIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoic3ByaW5nLWJvb3QtYXBwIiwic2lkIjoiMDM1ZDM3YTktYzEyMC00YjA3LWI2ZWItMDVhYjkzYjFlNDhhIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwOi8vbG9jYWxob3N0OjgwODAiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLWRldi1yZWFsbSJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InJlYWxtLW1hbmFnZW1lbnQiOnsicm9sZXMiOlsidmlldy1pZGVudGl0eS1wcm92aWRlcnMiLCJ2aWV3LXJlYWxtIiwibWFuYWdlLWlkZW50aXR5LXByb3ZpZGVycyIsImltcGVyc29uYXRpb24iLCJyZWFsbS1hZG1pbiIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJxdWVyeS1yZWFsbXMiLCJ2aWV3LWF1dGhvcml6YXRpb24iLCJxdWVyeS1jbGllbnRzIiwicXVlcnktdXNlcnMiLCJtYW5hZ2UtZXZlbnRzIiwibWFuYWdlLXJlYWxtIiwidmlldy1ldmVudHMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWF1dGhvcml6YXRpb24iLCJtYW5hZ2UtY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyJdfSwic3ByaW5nLWJvb3QtYXBwIjp7InJvbGVzIjpbInNwcmluZy1ib290LWFwcC1zdWItcm9sZSJdfSwiYnJva2VyIjp7InJvbGVzIjpbInJlYWQtdG9rZW4iXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJ2aWV3LWFwcGxpY2F0aW9ucyIsInZpZXctY29uc2VudCIsInZpZXctZ3JvdXBzIiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJkZWxldGUtYWNjb3VudCIsIm1hbmFnZS1jb25zZW50Iiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoiVXBkYXRlZCBVc2VyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic3ViYWRtaW4iLCJnaXZlbl9uYW1lIjoiVXBkYXRlZCIsImZhbWlseV9uYW1lIjoiVXNlciIsImVtYWlsIjoidXBkYXRlZEBleGFtcGxlLmNvbSJ9.IqfTKGmHqoa6j063e7RwmOmQbU21_joYwB9TIUH8vWaGHBL19IUCLYW25pRYa5OwJbH_ryuZZ08Phb7dTHEA4cvxcSzDxRnxyoAKQovNpEU7oi5CbeBUnNjXxS4exXK104WNIwX8UcpOaPLZJbkS6VS40Xlwpqy0grMtaP-7tPXOOnBVEGHnteWSAP4SEFPMoSWKf0iEWMCs4fqkasnoaTXQ6nrbD-dNhyhcqGN0-dI2eauCCQendj6AWTCQlrcPksAntT2yQ5n81DHmNyGnQH7FhzJlkSnB2VB2cZCN91kq9HhEWDBXZlF6aPBLZBMflf9-M9kHHtXkie0k8ZO_fw
x-api-key: test-api-key
Custom-Header: common-value
keycloak-auth-client:
logger-level: none # 기록하지 않음
defaultRequestHeaders:
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJLbHVfNEVEamQzQnRseUdpaUtabTNFUTF0cXZReDNGOUN0WGxEUXJ0QUpBIn0
x-api-key: custom-api-key
Custom-Header: common-header-value
- OpenFeign를 이용한 요청을 수행할때, header에 대한 설정을 추가하였습니다. - Header에 Authorization를 통한 Bearer 토큰 전송을 하고 추가적으로 커스텀 키에 해당하는 “x-api-key”를 추가하며, Custom-Header를 추가하여서 OpenFeign 전송 시마다 전달을 하도록 구성하였습니다.