728x90
반응형
마이크로서비스 아키텍처에서 서비스 간 통신은 필수입니다.
하지만 RestTemplate 또는 WebClient로 매번 HTTP 요청을 구성하고 응답을 처리하는 것은 번거롭고 중복이 많습니다.
1. OpenFeign 개요
OpenFeign은 인터페이스 기반으로 외부 HTTP API를 간단하고 타입 안전하게 호출할 수 있게 도와주는 선언형(Declarative) HTTP 클라이언트입니다.
연도 | 주요 이벤트 |
2013 | Netflix가 내부 프로젝트로 Feign 개발 시작 |
2015 | Netflix OSS의 일부로 Feign 오픈 소스 공개 |
2016 | Spring Cloud Netflix 프로젝트에서 @FeignClient 으로 통합 |
2019 | OpenFeign이라는 이름으로 독립 프로젝트로 분리됨 Netfliex는 Feigb의 개발에서 손을 떼고 커뮤니티로 이전 |
2020 이후 | Spring Cloud OpenFeign이 주요한 구현체로 유지되며, Spring Boot와 통합 지원 지속 |
주요 특징
- @FeignClient 인터페이스만으로 외부 API 호출 가능
- JSON, Form 등 다양한 HTTP 요청 포맷 지원
- 공통 헤더, 인증 토큰 등을 위한 RequestInterceptor 지원
- Retry, Fallback, ErrorDecoder 등 고급 기능 내장
- Spring Cloud와 완벽 통합 (spring-cloud-starter-openfeign)
2. 기본 구성
2.1. 의존성 추가
<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>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-hc5</artifactId>
</dependency>
</dependencies>
2.2. @EnableFeignClients 설정
@Configuration
@EnableFeignClients(defaultConfiguration = FeignConfig.class)
public class FeignConfig { }
2.3. Feign 인터페이스 정의
@FeignClient(name = "userApi", url = "https://api.example.com")
public interface UserApiClient {
@GetMapping("/users/{id}")
UserResponse getUser(@PathVariable("id") Long id);
@PostMapping(value = "/users", consumes = "application/json")
UserResponse createUser(@RequestBody CreateUserRequest request);
}
@FeignClient는 실제 구현체 없이도 자동으로 프록시가 생성됩니다.
3. 실전 사용 예 : 토큰 인증 붙은 API 호출
3.1. 인터셉터로 헤더 자동 삽입
@Component
public class AuthHeaderInterceptor implements RequestInterceptor {
@Autowired
private TokenProvider tokenProvider;
@Override
public void apply(RequestTemplate template) {
// template.removeHeader("Authorization");
template.header("Authorization", "Bearer " + tokenProvider.getToken());
}
}
3.2. 토큰 만료 대응 : ErrorDecoder 사용
@Component
public class CustomFeignErrorDecoder implements ErrorDecoder {
private final ErrorDecoder defaultDecoder = new Default();
@Override
public Exception decode(String methodKey, Response response) {
String body = getBody(response);
if (body.contains("EXPIRE_TOKEN")) {
return new RetryableException(
response.status(),
"Token invalid or expired. Retrying with refreshed token...",
response.request().httpMethod(), // ← method
(Long) null, // ← retryAfter millis (null 이면 기본 정책 사용)
response.request() // ← 원래 요청 정보
);
}
return defaultDecoder.decode(methodKey, response);
}
private String getBody(Response response) {
try (InputStream is = response.body().asInputStream()) {
return IOUtils.toString(is, StandardCharsets.UTF_8);
} catch (IOException e) {
return "";
}
}
}
4. 고급 기능 요약
기능 | 설명 |
RequestInterceptor | 요청 전 헤더/쿼리 등 전처리 |
ErrorDecoder | 응답 오류 커스터마이징 |
Retryer | 재시도 정책 설정 |
FallbackFactory | 실패 시 fallback 지정 |
Decoder | 응답 JSON → DTO 매핑 (기본은 Jackson 사용) |
5. 테스트 팁
- FeignClient는 일반 인터페이스이므로, 단위 테스트에서는 @MockBean 또는 Stub으로 쉽게 대체 가능
- 통합 테스트에서는 WireMock 또는 MockWebServer 사용 추천
6. 언제 Feign을 써야 하나?
Feign은 API 호출이 많고, 인증/헤더/재시도 로직이 공통화된 프로젝트에 강력한 생산성과 유지보수성을 제공합니다.
하지만, 단순한 단건 호출이나, 복잡한 커넥션 풀 관리가 필요한 경우엔 WebClient도 고려해볼 수 있습니다.
[Reference]
https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/
https://github.com/OpenFeign/feign
728x90
반응형
'spring' 카테고리의 다른 글
[SpringBoot3] MultipartException, FileCountLimitExceededException 발생 이슈 (0) | 2025.06.27 |
---|---|
[SpringBoot3] Resilience4j Java Config 설정 (0) | 2025.05.20 |
[SpringBoot] logback xml을 java configuration으로 변환하기 (0) | 2024.11.04 |
[SpringBoot] Spring Profile과 환경별 resource 설정 (0) | 2024.11.04 |
Spring MVC의 PathPattern (AntPathMatcher, PathPatternParser) (0) | 2024.05.08 |
댓글