들어가면서
카카오 및 애플 로그인을 구현하면서 외부 API 서버에 접근해 데이터를 받아와야 하는 일이
많아졌고, API 주소를 설정파일에 저장한 후 직접 HttpURLConnection 을 생성해서
연결하는 코드가 중복되게 되었다.
또 직접 HttpURLConnection 을 연결해 외부 API 에서 데이터를 받아오면
받아온 JSON 을 직접 파싱해야 하는 불편함도 존재했다.
정리하자면,
- 외부 API 를 간편하게 호출하고 싶어서
- 호출 결과를 직접 파싱하는 과정이 번거로워서
FeignClient 를 사용하게 되었다.
아래 설명에서는 많이 예시를 드는 Github API 를 이용해서 코드를 작성해보았다.
FeinClient
Feign 은 Netflix 에서 개발한 REST Client 이다.
기존에 RestTemplate 을 사용한 API 호출 코드량을 줄이고 간편하게 호출할 수 있게 해준다.
먼저 FeinClient 를 이용하기 위해 필요한 세팅을 정리해보자. (Gradle 기준)
- build.gradle 에 의존성 추가
- FeignClient 인터페이스 생성
- @EnableFeignClients 추가
- FeignClient Config 정보 설정
- Service 에 FeignClient 의존성 주입
- Controller 에 FeignService 의존성 주입
build.gradle 의존성 추가
ext {
set('springCloudVersion', "2021.0.1")
}
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:$springCloudVersion"
}
}
FeignClient 인터페이스 생성
@FeignClient(name = "githubFeignClient", url = "https://api.github.com",
configuration = GithubFeignClientConfig.class)
public interface GithubFeignClient {
@GetMapping("/users/{githubId}")
GithubUserResponse getGithubUser(@PathVariable("githubId") String githubId);
@GetMapping("/search/commits?q=author:{author} committer-date:{committerDate}")
GithubUserResponse getGithubCommits(@PathVariable("author") String author,
@PathVariable("committerDate") String committerDate);
}
어노테이션 안에 들어가는 값들은 다음과 같다.
@FeignClient(name ="feign client 이름 설정" , url="호출할 api url",
configuration = "feignclient 설정정보가 셋팅되어 있는 클래스")
추가로 Github API 를 호출하고 받을 Response 를 Mapping 하는 DTO 를 정의하자.
@Data
@AllArgsConstructor
public class GithubUserResponse {
String login;
Long id;
String node_id;
String avatar_url;
}
@EnableFeignClients 추가
@EnableFeignClients
@Configuration
public class GithubFeignClientConfig {
}
- Application Main 클래스 위에
@EnableFeignClients
를 추가해도 된다.
FeignClient Config 정보 설정
Config 클래스를 생성하고 필요한 설정 정보를 세팅할 수 있다.
- Config 를 따로 생성하지 않아도 아래 Bean 들은 기본적으로 제공된다.
Spring Cloud OpenFeign provides the following beans by default for feign (BeanType beanName: ClassName):
Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder)
Encoder feignEncoder: SpringEncoder
Logger feignLogger: Slf4jLogger
MicrometerCapability micrometerCapability: If feign-micrometer is on the classpath and MeterRegistry is available
CachingCapability cachingCapability: If @EnableCaching annotation is used. Can be disabled via feign.cache.enabled.
Contract feignContract: SpringMvcContract
Feign.Builder feignBuilder: FeignCircuitBreaker.Builder
Client feignClient: If Spring Cloud LoadBalancer is on the classpath, FeignBlockingLoadBalancerClient is used. If none of them is on the classpath, the default feign client is used.
- 아래 Bean 들은 필요할 때 Config 클래스에 만들어주어야 한다.
Logger.Level
Retryer
ErrorDecoder
Request.Options
Collection
SetterFactory
Capability (MicrometerCapability and CachingCapability are provided by default)
예시로, Github API 에서 유저를 조회했을 때 사용자가 없고,
해당 아이디를 가진 Github 유저가 없다
라는 커스텀 에러가 필요한 상황이라고 가정하자.
그럴 땐 에러 생성 후에 Config 에 ErrorDecoder
를 상속받은 GithubFeignError
를 작성하면 된다.
- Config 클래스
@EnableFeignClients
@Configuration
public class GithubFeignClientConfig {
@Bean
public ErrorDecoder errorDecoder() {
return new GithubFeignError();
}
}
- 커스텀 에러 클래스
public class GithubFeignError implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
switch (response.status()) {
case 404:
return new GithubUserNotFoundException(); // 커스텀 Exception
}
return null;
}
}
Service 에 FeignClient 의존성 주입
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class GithubFeignService {
private final GithubFeignClient githubFeignClient;
public GithubUserResponse getGithubUser(String githubId) {
return githubFeignClient.getGithubUser(githubId);
}
}
Controller 에 FeignService 의존성 주입
@RestController
@RequiredArgsConstructor
public class GithubController {
private final GithubFeignService githubFeignService;
@GetMapping("/github/user/{userId}")
public GithubUserResponse getGithubUser(@PathVariable("userId") String userId) {
return githubFeignService.getGithubUser(userId);
}
}
이제 Spring 을 실행시키고 localhost:8080/github/user/{userId} 를 호출하면
Github 유저 정보가 나오는 것을 확인할 수 있다.