sol 개발 블로그 로고
Published on

Spring RestTemplate으로 외부 API 사용 방법

Authors
  • avatar
    Name
    Chan Sol OH
    Twitter

목차

개요

스프링에서 외부 서버와 API 통신하는 방법은 여러 가지가 있다고 한다.

  1. Spring RestTemplate
    • Java Servlet API를 사용하기 때문에 요청 마다 쓰레드를 할당한다.
    • Blocking 처리이므로 응답을 기다릴 때 쓰레드가 대기 상태로 있다.
    • 많은 요청이 몰리면 많은 쓰레드가 쌓일 것이고 메모리 사용량이 초과될 수 있다.
  2. WebClient
    • Spring Reactive framework를 사용하여 비동기 방식으로 처리
    • RestTemplate이 각 이벤트에 쓰레드를 생성한 것과 달리 Reactive framework는 task라는 것을 생성한다.
    • 이벤트 드라이븐 아키텍처를 사용

WebClient은 RestTemplate에 비해 쓰레드를 적게 사용하는 장점이 있다. 하지만 Spring WebFlux 라이브러리의 한 부분이고, 비동기처리를 지원하기 때문에 아직 모르는 부분이 있다. 그래서 이번 실습에서는 비교적 동작 원리가 명확한 RestTemplate을 사용해서 외부 API 호출을 구현해보려고 한다.

RestTemplate의 유용한 메서드들

  • getForEntity()
    • GET 요청을 수행하고 status code와 응답 객체가 포함된 ResponseEntity class의 객체를 리턴한다.
  • getForObject()
    • getForEntity와 비슷하지만 응답 객체만 리턴한다.
  • headForHeaders()
    • HEAR 요청을 보내서 모든 HTTP 헤더 값을 리턴한다.
  • delete()
    • delete http 메서드를 요청한다.
  • put()
    • put http 메서드를 요청한다.
  • postForObject()
    • HTTP POST 메서드를 요청하고, 생성한 entity를 리런탛낟.

요청, 응답에 쓰일 DTO 객체 만들기

공식 DOCS에 적힌 것으로는 아래와 같은 형태로 응답한다고 한다. 이를 Controller에서 응답 받을 수 있도록 DTO를 작성한다.

catImageDTO.json
[{
  "id":"41n",
  "url":"https://cdn2.thecatapi.com/images/41n.jpg",
  "width":2048,"height":1530
}]
catImageDTO.java

@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class CatImage {

    private String id;
    private String url;
    private Long width;
    private Long height;
}

위와 같은 DTO를 List로 받아서 응답 받을 것이다.

RestTemplate을 이용한 Service 만들기

getCatImages.java
@Service
@RequiredArgsConstructor  // 생성작를 통한 DI
public class CatPhotosService implements CatPhoto {

    // 생성작를 통한 DI
    private final RestTemplate restTemplate;

    @Value("${api.cat.host.url}")
    public String hostUrl=null;
    @Value("${api.cat.xkey}")
    public String xkey=null;

    @Override
    public List<CatImage> getCatImages(Long imageNumber) {
        URI uri = UriComponentsBuilder
                .fromUriString(hostUrl)
                .path("/images/search")
                .queryParam("limit",imageNumber)
                .encode()
                .build()
                .toUri();
        HttpHeaders headers = new HttpHeaders();
        headers.set("x-api-key",xkey);
        HttpEntity entity = new HttpEntity(headers);
        ResponseEntity<List<CatImage>> responseEntity = restTemplate.exchange(uri,
                HttpMethod.GET, entity, new ParameterizedTypeReference<List<CatImage>>() {
                });
        System.out.println(responseEntity);
        return responseEntity.getBody();
    }
}

http entity를 이용해서 헤더를 설정하고 application.properties에서 xkey를 받아서 인증 정보를 보냈다. 또한 RestTemplate의 GET요청을 통해 이미지 데이터를 받았다.

Controller로 API 만들기

controller.java
@RestController
@RequiredArgsConstructor
public class imageController {

    private final CatPhotosService catPhotosService;

    @RequestMapping(value = "/api/v1/images", method = RequestMethod.GET)
    public List<CatImage> getImages(@RequestParam Long imageNumber){
        return catPhotosService.getCatImages(imageNumber);
    }
}

앞으로...

다만, 앞으로 비동기처리 방식인 WebFlux를 자주 사용할 것이라는 얘기가 많이 나오고 있다. 비동기 처리의 위험성 (데드락, 레이스 컨디션) 같은 것을 잘만 처리하면 적은 쓰레드를 써서 더 많은 요청을 처리할 수 있고, CPU, 메모리 사용량이 더 적기 때문인 것 같다.

다음에는 WebClient를 이용한 API 요청이나 WebFlux를 이용한 비동기처리도 포스팅하겠다.