[Spring] RestTemplate

JunWoo An·2023년 11월 29일
0

스파르타코딩클럽

목록 보기
26/46
post-thumbnail

이전 과제에서 같은 서버내에서 다른 API(내부 API)를 호출하여 기능을 구현하였다. 그렇다면 다른서버의 API(외부 API)는 어떻게 호출하여 사용하는걸까?

RestTemplate?

서비스 개발을 진행하다보면 라이브러리 사용만으로는 구현이 힘든 기능들이 무수히 많이 존재한다. 예를 들어 우리의 서비스에서 회원가입을 진행할때 사용자의 주소를 받아야한다면? 주소를 검색할수있는 기능을 구현해야할텐데 이를 직접 구현시 많은시간과 비용이 소요될것이다. 이때 카카오에서 만든 주소 검색 API를 사용한다면 해당기능을 간단하게 구현할수있다.

그렇다면 어떻게 카카오의 주소 검색 API를 어떻게 사용할수있을까?

우리는 클라이언트의 요청을 받아 요청받은 기능을 서버내에 구현한다.이와 같은 과정으로 카카오 또한 우리가 클라이언트가 되어 요청받은 기능(API)을 수행하는 서버의 역할을 수행한다. 그럼 우리(서버)가 클라이언트가 되는 방법을 알아보자.

Spring에서는 서버에서 다른서버로 간편하게 요청할수 있도록 RestTemplate기능을 제공하고있다.
우선 RestTemplate기능을 사용하기위해 의존성을 주입 받아야한다.

private final RestTemplate restTemplate;

// RestTemplateBuilder의 build()를 사용하여 RestTemplate을 생성합니다.
public RestTemplateService(RestTemplateBuilder builder) {
    this.restTemplate = builder.build();
}

그리고 서버입장의 서버에서 request는 HtttpservletRequest가 해당 요청 URL을 처리해주지만 클라이언트입장의 서버에서는 해당 URL을 직접 만들어야한다.

public ItemDto getCallObject(String query) {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7070")
            .path("/api/server/get-call-obj")
            .queryParam("query", query)
            .encode()
            .build()
            .toUri();

    ResponseEntity<ItemDto> responseEntity = restTemplate.getForEntity(uri, ItemDto.class);

    return responseEntity.getBody();
}

GET 요청의 RestTemplate 예시이다. ResponseEntity에 응답받을 Dto클래스형태로 반환받기위해 restTemplate.getForEntity(요청URL, 전달받은 데이터와 매핑하여 인스턴스화할 클래스타입)을 사용하였다.

우리는 서버의 역할을 수행할 서버와 클라이언트의 역할을 수행할 서버를 동시에 실행시켜야하기 때문에 두개의 port를 다르게 설정하여야한다.(서버입장의 서버 : 8080, 클라이언트입장의 서버 : 7070)

public ItemDto postCall(String query) {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7070")
            .path("/api/server/post-call/{query}")
            .encode()
            .build()
            .expand(query)
            .toUri();

    User user = new User("Robbie", "1234");

    ResponseEntity<ItemDto> responseEntity = restTemplate.postForEntity(uri, user, ItemDto.class);

    return responseEntity.getBody();
}

다음으로는 POST요청 RestTemplate이다. UriComponentsBuilderexpand을 사용하여 {query}안의 값을 동적으로 처리하였다. restTemplate.postForEntity(요청받을uri, HTTP Body에 넣어줄 데이터, 전달 받은 데이터와 매핑하여 인스턴스화할 클래스의 타입)을 사용하였다.

만약 Header에 정보(토큰 등)를 추가하고싶다면?

public List<ItemDto> exchangeCall(String token) {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("http://localhost:7070")
            .path("/api/server/exchange-call")
            .encode()
            .build()
            .toUri();

    User user = new User("Robbie", "1234");

    RequestEntity<User> requestEntity = RequestEntity
            .post(uri)
            .header("X-Authorization", token)
            .body(user);

    ResponseEntity<String> responseEntity = restTemplate.exchange(requestEntity, String.class);

    return fromJSONtoItems(responseEntity.getBody());
}

exchange 메서드의 첫번째 파라미터에 RequestEntity 객체를 만들어 전달해주면 uri, header, body의 정보를 한번에 전달할 수 있다.

이와같이 Spring의 RestTemplate을 사용한다면 무수히 많은 오픈API를 사용하여 더욱 효율적이게 서버를 설계 구현할수있다.

profile
도전하는 사람

0개의 댓글