우리는 개발을 하다보면 외부 Api를 호출해야 하는 경우가 종종 있다.
그럴 때 보통 사용하는 기술이 여러가지가 있는데
- URL + HttpURLConnection + OutputStreamWriter + BufferedReader
- RestTemplate + UriComponents + HttpEntity
- ...
하지만 위와 같은 기술을 사용하면 대표적인 클래스 선언만 3,4가지 이상이 되고 그 이외에 설정까지 하면 외부 Api 호출하는데 기본 코드가 10줄 이상이 돼버린다.
아래는 KAKO 주소 검색 API를 호출하는 코드이다.(OpenFeign 사용 X)
KakaoApiService.class
@Service
@RequiredArgsConstructor
public class KakaoApiService {
@Value("${key.kakao.map.rest-api}")
private String apiKey;
private static final String SEARCH_ADDRESS_URI = "https://dapi.kakao.com/v2/local/search/address";
public KakaoAddressResponse searchAddressBack(String address) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "KakaoAK " + apiKey);
UriComponents uri = UriComponentsBuilder.fromUriString(SEARCH_ADDRESS_URI).queryParam("query", address).build();
HttpEntity<Void> httpEntity = new HttpEntity<>(headers);
ResponseEntity<KakaoAddressResponse> response = restTemplate.exchange(uri.toUriString(), HttpMethod.GET, httpEntity, KakaoAddressResponse.class);
if (response.getStatusCode() != HttpStatus.OK) {
throw new ServiceException("", "주소확인 오류");
}
if (response.getBody().getMeta().getTotalCount() == 0) {
throw new ServiceException("", String.format("일치하는 주소가 없습니다. : [%s]", address));
}
return response.getBody();
}
}
위 코드에선 RestTemplate를 사용해서 조금은 코드를 줄인 상태이다.
해당 Api에선 설정해 줘야 하는 값들이 많지 않고 전달하는 parameter 또한 많지 않기 때문에 비교적 간결하다.
하지만 전달할 parameter 많다던가 기초 셋팅 값들이 많아질수록 코드는 10줄 20줄까지도 넘어가게 된다.
심지어 HttpURLConnection을 사용한다면,,,
JSONObject 사용해서 parameter 설정하고 new URL 생성하고 HttpURLConneciton에 method 설정하고 Content-Type 설정하고 OutputStreamWriter로 write 하고 flush하고 new InputStreamReader 하고 BufferedReader로 Response 읽고 Reader 닫고 Connection 끊고 뭐하고 뭐하고,,,
후 생각만 해도 아주 복잡하고 지저분할 거 같다.
이러한 코드를 조금 더 깔끔하고 가독성 있도록 개선하는 방법 중 하나가 OpenFeign을 사용하는 것이다.
자 그럼 OpenFeign을 사용해 보자.
기본 설정
1. build.gradle
openFeign 의존성 추가
// OpenFeign
implementation platform("org.springframework.cloud:spring-cloud-dependencies:2022.0.2")
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
2. Applicaiton.java
@EnableFeignClients Annotation 추가
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
설정 끗
1. FeignClient 생성 및 설정
ㅇ @FeignClient (url = "")으로 호출하는 Api에 공통 Url이 있다면 아래와 같이 url = ""로 설정
ㅇ @GetMapping으로 Api Method Type 설정
ㅇ @GetMapping (value = "")으로 공통 Url 뒤에 사용될 Url 설정
ㅇ @GetMapping (consumes = "") 클라이언트가 서버에게 Request Data Type(본인 -> 카카오)
( produces = "" 카카오 -> 본인 Response Data Type)
ㅇ @RequestHeader로 Header에 설정해 줘야 하는 값 설정
ㅇ @PathVariable로 Url {address}에 값 설정
(Method Type이 Get이기 때문에 @PathVariable로 URL에 mapping, if (Method Type == Post) @RequestBody 사용)
KakaoFeignClient.class
@FeignClient(name = "kakaoMapClient", url = "${url.kakao.map.search}")
public interface KakaoFeignClient {
@GetMapping(value = "/v2/local/search/address?query={address}", consumes = "application/json")
ResponseEntity<KakaoAddressResponse> getKakaoAddressInfo(@RequestHeader(value = "Authorization", required = true) String authorization,
@PathVariable("address") String address);
}
2. KakaoApiService.class
public class KakaoApiService {
private final KakaoFeignClient kakaoFeignClient;
@Value("${key.kakao.map.rest-api}")
private String apiKey;
public KakaoAddressResponse searchAddress(String address) {
String authorization = "KakaoAK " + apiKey;
ResponseEntity<KakaoAddressResponse> response = kakaoFeignClient.getKakaoAddressInfo(authorization, address);
if (response.getStatusCode() != HttpStatus.OK) {
throw new ServiceException("", "주소확인 오류");
}
if (response.getBody().getMeta().getTotalCount() == 0) {
throw new ServiceException("", String.format("일치하는 주소가 없습니다. : [%s]", address));
}
return response.getBody();
}
}
이렇게 OpenFeign을 사용해 봤다.
OpenFeign을 사용함으로써 코드의 간결함은 기본이고 공통적인 properties, 로직 관리에 용이점도 있는 거 같다.
또한 현재 코드는 Api를 호출하고 받아온 response에 응답 코드로 오류 예외 처리를 하고 있는데
@FeignClient (configuration = "") 을 사용하면 Request를 보낼 때 마다 실행해야 하는 Header에 token 설정, Authorization 설정 등과 Response에 응답 코드에 따른 예외 처리 등 공통적인 로직을 담을 수 있다.
@FeignClient 에는 이외에도 많은 옵션들이 존재하니 한 번쯤 읽어보는 것도 좋을 거 같다.
'Web > Spring' 카테고리의 다른 글
[Spring] 파일 업로드/다운로드 (다운로드) (0) | 2024.04.08 |
---|---|
[Spring] 파일 업로드/다운로드 (업로드) (0) | 2024.04.08 |
맨땅에 Spring Batch - 회원 복제 (0) | 2024.01.16 |
맨땅에 Spring Batch - Task 그리고 Chunk (0) | 2024.01.16 |
맨땅에 Spring Batch - Item (0) | 2024.01.16 |