java
CHAPTER 93 / 99
읽기 약 2분
FUNCTION
Feign Client: 서비스 간 통신
핵심 개념
선언적 HTTP 클라이언트·@FeignClient·Resilience4j Circuit Breaker — 서비스 호출 체인.
본문
Feign Client 기본
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication { }
@FeignClient(name = "product-service", path = "/products")
public interface ProductClient {
@GetMapping("/{id}")
ProductDto getProduct(@PathVariable Long id);
@GetMapping
List<ProductDto> getProducts(@RequestParam List<Long> ids);
@PostMapping("/{id}/decrement")
void decrementStock(@PathVariable Long id, @RequestBody StockRequest req);
}
@Service
@RequiredArgsConstructor
public class OrderService {
private final ProductClient productClient;
public Order placeOrder(OrderRequest req) {
ProductDto product = productClient.getProduct(req.productId());
// ... Eureka가 product-service URL 자동 해결
}
}Circuit Breaker (Resilience4j)
resilience4j:
circuitbreaker:
configs:
default:
slidingWindowSize: 10
failureRateThreshold: 50
waitDurationInOpenState: 30s
permittedNumberOfCallsInHalfOpenState: 3
instances:
productService:
baseConfig: default
retry:
configs:
default:
maxAttempts: 3
waitDuration: 1s
instances:
productService:
baseConfig: default
timelimiter:
configs:
default:
timeoutDuration: 3s@Service
@RequiredArgsConstructor
public class OrderService {
private final ProductClient productClient;
@CircuitBreaker(name = "productService", fallbackMethod = "fallbackProduct")
@Retry(name = "productService")
@TimeLimiter(name = "productService")
public CompletableFuture<ProductDto> getProductWithResilience(Long id) {
return CompletableFuture.supplyAsync(() -> productClient.getProduct(id));
}
public CompletableFuture<ProductDto> fallbackProduct(Long id, Throwable t) {
log.warn("Product service down: {}", t.getMessage());
return CompletableFuture.completedFuture(
new ProductDto(id, "Unavailable", BigDecimal.ZERO, 0)
);
}
}인증 헤더 전달
@Component
public class FeignAuthInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
ServletRequestAttributes attrs = (ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
if (attrs != null) {
String token = attrs.getRequest().getHeader("Authorization");
if (token != null) {
template.header("Authorization", token);
}
}
}
}로깅
logging:
level:
com.example.client.ProductClient: DEBUG
# 요청·응답 본문 모두 로깅 (개발만)
feign:
client:
config:
productService:
loggerLevel: FULL에러 디코더 — 의미있는 예외
@Component
public class CustomErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
return switch (response.status()) {
case 404 -> new ProductNotFoundException();
case 500 -> new ProductServiceUnavailableException();
default -> new ErrorDecoder.Default().decode(methodKey, response);
};
}
}다음 챕터
CH.25 "Kafka 기초" — 이벤트 기반 통신.
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 Spring 코드의 Feign Client 부분을 분석해서 Circuit Breaker 정책와 개선 우선순위를 알려줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
Feign Client vs 다른 패턴 비교를 실전 사례 5개로 보여주고 Feign vs WebClient vs gRPC를 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 코드베이스 전체를 분석해서 Feign Client 관련 서비스 호출 누락 보호를 보고해줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 기업의 Feign Client 채택률과 한국 MSA 회복 탄력성 트렌드를 솔직히 알려줘.
⭐ 이것만 기억하세요
Feign Client: 서비스 간 통신은 이 3가지만 확실히 잡으세요
1.Feign은 인터페이스 기반 선언적 HTTP 클라이언트 — RestTemplate보다 간결
2.Circuit Breaker + Retry + TimeLimiter = 마이크로서비스 회복 탄력성 3종
3.다음 챕터 CH.25에서 Kafka — 비동기 이벤트 기반 통신
공유하기
진행도 93 / 99