Feign Client
🚀 Netflix Feign Client를 활용한 서비스 호출
마이크로서비스 환경에서 서비스 간의 원활한 통신은 필수적입니다.
이번 글에서는 Spring Cloud Netflix Feign Client를 활용하여 Eureka를 통해 마이크로서비스를 호출하는 방법을 알아보겠습니다.
기존의 RestTemplate
방식보다 코드가 간결하고 직관적인 Feign Client를 사용하면 서비스 호출을 쉽게 추상화할 수 있습니다.
Spring Cloud가 자동으로 프록시를 생성해주기 때문에, 개발자는 복잡한 HTTP 요청 코드를 작성할 필요가 없습니다. 😊
🎯 1. Feign Client란?
Netflix Feign Client 는 RESTful API 호출을 간단하게 추상화하는 HTTP 클라이언트 입니다.
Feign을 사용하면 인터페이스만 정의하면 Eureka를 통해 자동으로 REST API를 호출할 수 있습니다.
✅ 기존 방식 vs Feign Client 방식 비교
방식 | 코드 복잡도 | Eureka 연동 | 로드 밸런싱 지원 | 주요 특징 |
---|---|---|---|---|
RestTemplate | 높음 | ✅ 가능 | ✅ 가능 (LoadBalanced) | 직접 URL 생성 및 HTTP 요청 처리 필요 |
Feign Client | 낮음 | ✅ 자동 | ✅ 자동 | 인터페이스만 정의하면 서비스 호출 가능 |
✔ Feign Client는 기존 RestTemplate
보다 코드가 훨씬 간결 🎯
✔ Spring Cloud가 자동으로 Eureka와 연동하여 로드 밸런싱을 수행 🚀
✔ 인터페이스만 정의하면 Spring이 프록시를 생성해 자동으로 API를 호출
🏗 2. Feign Client 활성화
✅ 1️⃣ @EnableFeignClients
추가
Spring Boot 애플리케이션에서 Feign Client를 사용하려면 @EnableFeignClients
애너테이션을 추가해야 합니다.
📌 LicenseServiceApplication.java
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableFeignClients // Feign Client 활성화
public class LicenseServiceApplication {
public static void main(String[] args) {
SpringApplication.run(LicenseServiceApplication.class, args);
}
}
✔ @EnableFeignClients
를 추가하면 Feign Client 기능이 활성화됨
✔ Feign이 Eureka와 자동으로 연동되어 서비스 탐색을 수행
🔍 3. Feign Client를 활용한 서비스 호출
✅ 2️⃣ Feign Client 인터페이스 정의
이제 Feign Client를 사용하여 Organization Service를 호출하는 인터페이스를 정의해 보겠습니다.
📌 OrganizationFeignClient.java
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
@FeignClient("organization-service") // Eureka에서 "organization-service" 호출
public interface OrganizationFeignClient {
@RequestMapping(
method = RequestMethod.GET,
value = "/v1/organization/{organizationId}",
consumes = "application/json"
)
Organization getOrganization(@PathVariable("organizationId") String organizationId);
}
✔ @FeignClient("organization-service")
"organization-service"
는 Eureka에 등록된 서비스 ID- Feign이 Eureka에서 자동으로 해당 서비스의 위치를 찾아 호출
✔ @RequestMapping
을 사용하여 REST API 호출 정의
- 기존 컨트롤러에서 사용하는
@RequestMapping
과 동일한 방식으로 사용 가능 - Feign이 이 인터페이스를 기반으로 프록시를 생성하여 HTTP 요청을 자동으로 처리
⚙️ 4. Feign Client 사용 방법
이제 Feign Client를 서비스 코드에서 주입받아 사용하면 됩니다.
📌 LicenseService.java
@Service
public class LicenseService {
@Autowired
private OrganizationFeignClient organizationFeignClient;
public License getLicense(String licenseId, String organizationId) {
License license = licenseRepository.findByOrganizationIdAndLicenseId(organizationId, licenseId);
if (license == null) {
throw new IllegalArgumentException("해당 라이선스를 찾을 수 없습니다.");
}
// Feign Client를 사용하여 Organization Service 호출
Organization organization = organizationFeignClient.getOrganization(organizationId);
if (organization != null) {
license.setOrganizationName(organization.getName());
license.setContactName(organization.getContactName());
license.setContactEmail(organization.getContactEmail());
license.setContactPhone(organization.getContactPhone());
}
return license;
}
}
✔ Feign Client를 @Autowired
로 주입받아 사용
✔ Feign이 Eureka에서 자동으로 organization-service
의 위치를 찾아 호출
✔ 서비스 호출 코드가 매우 간결
⚠️ 5. Feign Client의 에러 처리 (Error Handling)
🚨 1️⃣ RestTemplate vs Feign Client의 에러 처리 방식
방식 | HTTP 오류 처리 방식 |
---|---|
RestTemplate | ResponseEntity.getStatusCode() 를 통해 직접 처리 |
Feign Client | HTTP 4xx~5xx 응답이 발생하면 FeignException 발생 |
💡 Feign Client는 HTTP 오류 응답을 FeignException
으로 변환하여 예외 처리해야 합니다.
✅ 2️⃣ Feign Client의 커스텀 에러 처리
Feign에서는 커스텀 에러 디코더를 구현하여 예외를 변환할 수 있습니다.
📌 FeignErrorDecoder.java
import feign.Response;
import feign.codec.ErrorDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
public class FeignErrorDecoder implements ErrorDecoder {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public Exception decode(String methodKey, Response response) {
if (response.status() == HttpStatus.NOT_FOUND.value()) {
return new NotFoundException("해당 리소스를 찾을 수 없습니다.");
} else if (response.status() == HttpStatus.BAD_REQUEST.value()) {
return new BadRequestException("잘못된 요청입니다.");
}
return new Exception("Feign Client 호출 중 예기치 않은 오류 발생");
}
}
📌 Feign 에러 디코더 설정
@Configuration
public class FeignConfig {
@Bean
public ErrorDecoder errorDecoder() {
return new FeignErrorDecoder();
}
}
✔ Feign이 HTTP 오류 응답을 FeignException
대신 커스텀 예외로 변환하도록 설정 가능
✔ Feign을 사용할 때 오류 처리를 보다 효과적으로 수행할 수 있음
🎯 6. Feign Client vs RestTemplate vs DiscoveryClient 비교
방식 | Eureka 연동 | 로드 밸런싱 지원 | 코드 복잡도 | 추천 사용 사례 |
---|---|---|---|---|
DiscoveryClient | ✅ | ❌ | 복잡함 | 서비스 목록을 직접 조회할 때 |
RestTemplate (@LoadBalanced) | ✅ | ✅ | 보통 | REST API 호출 시 |
Feign Client | ✅ | ✅ | 가장 간결함 | 간단한 API 호출 시 |
💡 Feign Client가 가장 사용하기 편리하지만, 일부 경우에는 RestTemplate이 필요할 수도 있습니다.
🏆 결론
이번 글에서는 Spring Cloud Netflix Feign Client를 활용하여 마이크로서비스를 호출하는 방법을 살펴봤습니다. 🚀
✅ 핵심 정리
✔ Feign Client를 사용하면 코드가 매우 간결
✔ Eureka와 자동 연동되어 동적으로 서비스 위치를 탐색
✔ Spring이 자동으로 HTTP 요청을 처리하므로 개발자가 직접 요청을 작성할 필요 없음
✔ 커스텀 에러 핸들링을 추가하여 Feign의 예외 처리를 개선 가능