궤도

[Spring] RestTemplate를 이용해서 OpenAPI(카카오) 호출해보기 본문

💻 현생/📋 스터디

[Spring] RestTemplate를 이용해서 OpenAPI(카카오) 호출해보기

영이오 2021. 7. 15. 17:57

https://developers.kakao.com/docs/latest/ko/daum-search/dev-guide#search-book

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

이걸 써보려고 한다.

 

일단 시작전에 postman으로 api를 실행해보겠다.

Auth에서 저렇게 설정하고 send 해보면

 

잘 나온다. 이제 이걸 적용하는게 문제다.

 

이런저런 구글링을 하니까 RestTemplate라는걸 사용하면 스프링에서 Rest Api를 호출할 수 있나보다.

https://spring.io/guides/gs/consuming-rest/

 

Consuming a RESTful Web Service

this guide is designed to get you productive as quickly as possible and using the latest Spring project releases and techniques as recommended by the Spring team

spring.io

뭔소리여

 

https://hyeonyeee.tistory.com/34

 

RestTemplate 를 이용하여 API Get 하기

1. RestTemplate이란? Spring 3.0부터 지원하며 스프링에서 http 통신에 유용하게 쓸수 있도록 제공해주는 템플릿이다. 즉, API 통신해서 가져 올수 있도록 도와준다. 2. 예시코드 @GetMapping("/test") public Re..

hyeonyeee.tistory.com

https://recordsoflife.tistory.com/360

 

RestTemplate 사용방법(예제)

Java 에코 시스템에서 몇 년간의 경험이 있고 그 경험을 커뮤니티와 공유하고 (물론 작업에 대한 대가를받는 데) 관심이 있다면 "Write for Us"페이지를 참조하십시오 . 건배, Eugen 1. 개요 이 튜토리얼

recordsoflife.tistory.com

이런 저런 블로그를 찾아봤고...

 

package jpa.myunjuk.common;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.Map;

@RestController
public class KakaoApi {

    private final String url = "https://dapi.kakao.com/v3/search/book";
    private final String key = "rest api key";

    @GetMapping("/kakao")
    public Map callApi(@RequestParam String query){
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Authorization", "KakaoAK "+key);
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url).queryParam("query", query);
        HttpEntity<String> entity = new HttpEntity<>(httpHeaders);

        return restTemplate.exchange(builder.toUriString(), HttpMethod.GET, entity, Map.class).getBody();
    }
}

여기까지 했다. 설명은 이따가 하기로 하고...

 

잘 나오긴 하는데 한글이 깨진다.

 

 

악 됐다!

 

https://cultist-tp.tistory.com/entry/Spring-RestTemplate-%EA%B0%9D%EC%B2%B4-%EC%82%AC%EC%9A%A9%EC%8B%9C-url%EC%97%90-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%EC%A0%84%EB%8B%AC-%EB%B0%A9%EB%B2%95

 

Spring RestTemplate 객체 사용시, url에 파라미터 전달 방법

참조 : http://stackoverflow.com/questions/15774475/how-to-send-a-getforobject-request-with-parameters-spring-mvc RestTemplate 객체를 사용하여 url 주소를 호출과 동시에 파라미터를 전달 해줄 경우 Uri..

cultist-tp.tistory.com

여기 보고 해결했다.

 

package jpa.myunjuk.common;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@RestController
public class KakaoApi {

    @Value("${kakao.key}")
    private String key;
    private String url = "https://dapi.kakao.com/v3/search/book";

    @GetMapping("/kakao")
    public Map callApi(@RequestParam String query) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Authorization", "KakaoAK " + key); //Authorization 설정
        HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders); //엔티티로 만들기
        URI targetUrl = UriComponentsBuilder
                .fromUriString(url) //기본 url
                .queryParam("query", query) //인자
                .build()
                .encode(StandardCharsets.UTF_8) //인코딩
                .toUri();

        //GetForObject는 헤더를 정의할 수 없음
        ResponseEntity<Map> result = restTemplate.exchange(targetUrl, HttpMethod.GET, httpEntity, Map.class);
        return result.getBody(); //내용 반환
    }
}

에러 핸들링을 안해서 코드가 짧다. 해야지...해야 하는데...

아무튼 대충 설명하면

 

    @Value("${kakao.key}")
    private String key;
    private String url = "https://dapi.kakao.com/v3/search/book";

일단 검색해본 결과 괜찮다곤 했는데, 키를 노출하는게 영 찝찝해서 application.yml에 api key를 보관했다.

 

application.yml

kakao:
  key: key 내용

이런식으로 하고 저렇게 value 어노테이션으로 호출하면 된다.

 

    @GetMapping("/kakao")
    public Map callApi(@RequestParam String query) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Authorization", "KakaoAK " + key); //Authorization 설정
        HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders); //엔티티로 만들기
        URI targetUrl = UriComponentsBuilder
                .fromUriString(url) //기본 url
                .queryParam("query", query) //인자
                .build()
                .encode(StandardCharsets.UTF_8) //인코딩
                .toUri();

        //GetForObject는 헤더를 정의할 수 없음
        ResponseEntity<Map> result = restTemplate.exchange(targetUrl, HttpMethod.GET, httpEntity, Map.class);
        return result.getBody(); //내용 반환
    }

그리고 여긴 실제로 구현할 땐 Service로 바꾸겠지만 일단 테스트라 API로 만들어서 바로 호출했다.

 

        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders httpHeaders = new HttpHeaders();

RestTemplate는 기본이고, HttpHeaders는 Authorization 때문에 추가했다.

 

 

        httpHeaders.set("Authorization", "KakaoAK " + key); //Authorization 설정
        HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders); //엔티티로 만들기

저기 써있는데로 헤더에 인증 정보를 입력하고, 엔티티로 만들어 준다. post 호출일 때는 엔티티에 body도 넘긴다고 한 것 같다.

 

        URI targetUrl = UriComponentsBuilder
                .fromUriString(url) //기본 url
                .queryParam("query", query) //인자
                .build()
                .encode(StandardCharsets.UTF_8) //인코딩
                .toUri();

그리고 요청을 보낼 uri를 만든다. 개발가이드 보면 인자는 query로 넘겨야 한다. 그래서 그렇게 넘긴 것이다.

UTF-8로 인코딩하면 한글이 깨지지 않는다.

 

        //GetForObject는 헤더를 정의할 수 없음
        ResponseEntity<Map> result = restTemplate.exchange(targetUrl, HttpMethod.GET, httpEntity, Map.class);
        return result.getBody(); //내용 반환

마지막으로 exchange 메소드를 이용해서 호출하면 된다. 

getHeader()를 하면 헤더 정보가 나오고 getBody()를 하면 내용이 반환되는가보다.

 

인텔리제이피셜 넘겨야하는 인자는 위와 같다.

 

아무튼 잘 나온다!

 

하지만 여기서 끝난게 아니고 이 결과를 담을 Dto도 만들어야 하고 뭐 암튼 이것저것 할 것들이 많다.

Comments