Feign Client는 Spring Cloud에서 제공하는 HTTP 클라이언트 라이브러리로, RESTful API 호출을 더욱 간결하고 선언적으로 처리할 수 있게 도와줍니다. Java 코드로 API 호출을 마치 인터페이스 메서드를 호출하듯 작성할 수 있어 생산성과 가독성이 높아집니다. ✨
Feign Client의 주요 특징 🌟
- 인터페이스 기반: API를 호출할 때 복잡한 코드를 작성할 필요 없이 인터페이스와 어노테이션만으로 구현할 수 있습니다.
- 내장형 로드 밸런싱: Spring Cloud LoadBalancer와 연동하여 클라이언트 부하 분산을 자동으로 처리합니다.
- 확장 가능: 커스터마이징을 통해 로깅, 요청/응답 변환기 등을 손쉽게 추가할 수 있습니다.
- 타사 라이브러리 통합: OkHttp, Apache HttpClient 등 다양한 HTTP 클라이언트를 지원합니다.
예제: Feign Client로 REST API 호출하기 🛠️
1. 의존성 추가하기 📦
먼저, build.gradle 또는 pom.xml에 Feign 의존성을 추가합니다:
Gradle:
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
Maven:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2. Feign Client 인터페이스 정의하기 ✍️
예를 들어, JSONPlaceholder API를 호출한다고 가정해보겠습니다:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "jsonPlaceholderClient", url = "https://jsonplaceholder.typicode.com")
public interface JsonPlaceholderClient {
@GetMapping("/posts/{id}")
Post getPostById(@PathVariable("id") Long id);
@GetMapping("/posts")
List getAllPosts();
}
여기서:
- @FeignClient: Feign Client 인터페이스임을 선언합니다.
- name: 이 클라이언트를 구분짓는 이름입니다.
- url: 호출할 API의 기본 URL입니다.
- @GetMapping: HTTP GET 메서드를 호출할 경로를 지정합니다.
Post 클래스는 API의 응답 구조에 맞게 정의되어야 합니다:
@Data
public class Post {
private Long id;
private Long userId;
private String title;
private String body;
}
3. Feign Client 사용하기 🚀
이제 작성한 Feign Client를 서비스나 컨트롤러에서 사용할 수 있습니다:
import org.springframework.stereotype.Service;
@Service
public class PostService {
private final JsonPlaceholderClient jsonPlaceholderClient;
public PostService(JsonPlaceholderClient jsonPlaceholderClient) {
this.jsonPlaceholderClient = jsonPlaceholderClient;
}
public Post getPostById(Long id) {
return jsonPlaceholderClient.getPostById(id);
}
public List<Post> getAllPosts() {
return jsonPlaceholderClient.getAllPosts();
}
}
컨트롤러에서 호출해봅시다:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PostController {
private final PostService postService;
public PostController(PostService postService) {
this.postService = postService;
}
@GetMapping("/posts/{id}")
public Post getPostById(@PathVariable Long id) {
return postService.getPostById(id);
}
@GetMapping("/posts")
public List<Post> getAllPosts() {
return postService.getAllPosts();
}
}
Feign Client 커스터마이징 🛠️
로깅 추가하기 📝
Feign Client의 요청/응답 로그를 확인하려면 다음 설정을 추가하세요:
- application.yml 설정:
logging:
level:
com.example.JsonPlaceholderClient: DEBUG
- Feign Logger Bean 등록:
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
오류 처리 핸들러 추가하기 ⚠️
Feign Client는 기본적으로 오류 응답을 그대로 던지므로, 이를 사용자 정의 예외로 처리하려면 **ErrorDecoder**를 구현합니다:
import feign.Response;
import feign.codec.ErrorDecoder;
public class CustomErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
switch (response.status()) {
case 400:
return new BadRequestException("잘못된 요청입니다.");
case 404:
return new NotFoundException("리소스를 찾을 수 없습니다.");
default:
return new Exception("알 수 없는 오류가 발생했습니다.");
}
}
}
그리고 Feign Client에 이 오류 디코더를 적용합니다:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
public ErrorDecoder errorDecoder() {
return new CustomErrorDecoder();
}
}
마무리 🎉
Feign Client를 활용하면 복잡한 HTTP 클라이언트 코드를 줄이고, 선언적인 방식으로 API 호출을 간편하게 작성할 수 있습니다. 필요한 경우 로깅, 오류 처리, 커스터마이징 등을 통해 요구사항에 맞게 확장할 수도 있습니다. 🚀
'IT 개발 라이프 > Back_End' 카테고리의 다른 글
자바 Stream 이란? 🚀 (0) | 2024.12.04 |
---|---|
자바에서 동적 바인딩과 정적 바인딩 이해하기 🐾✨ (0) | 2024.12.03 |
필드 주입과 생성자 주입 – 무엇이 더 나은 선택일까? 🌍 (1) | 2024.12.02 |
REST API란 무엇인가? 🌐 (0) | 2024.12.02 |
Filter와 Interceptor 이해하기 ✨ (0) | 2024.11.29 |