프로젝트를 진행하면서 느낀점이나 해결했던 과정을 기록하기 위해 시작한다.
처음 작업은 패키지 정리였는데, 카카오 API 요청을 어디서 할지였다.
일단 repository는 DB와 연관된 처리를 할 때이므로 제외시키고,
service냐 controller냐였는데, 회사 동기의 조언이나 다른 블로그 글들을 보고 service안에 externalAPI라는 패키지를 만들자는 결론을 내렸다.
이렇게 결론을 내리게된 이유는 API 요청 방법이 달라질 수 있고 다른 API들을 사용할 경우 분리해서 관리하기 쉽겠다고 생각을 해서이다.
이런식으로 준비를 하고 카카오 API 요청을 해보자. 요청을 하기 전에 git을 사용하므로 API 키 부터 숨겨야 한다.
일단 나는 카카오 API를 사용할 예정인데 거기서 키워드로 장소 검색하기 라는 API이다.
https://developers.kakao.com/docs/latest/ko/local/dev-guide#search-by-keyword
내 애플리케이션에 들어가보면
이런 API 키가 나오는데 API 사용을 위해서 필수로 사용해야 하고 다른사람이 이 키를 통해서 사용할 수 있으니 숨겨야 한다. 유료 API 호출을 사용할 경우 호출 수 제한등으로 다른 사람들이 사용할 수 있으니 숨겨야 하는 것이다.
이제 스프링으로 가서 resources안에 application-API-KEY.properties 라는 파일을 만든다.
그리고 내 애플리케이션에 적혀있는 REST API key가 123456이라고 한다면
application-API-KEY.properties 파일 안에 kakao_id = 123456이라고 적으면 된다. 즉, kakao_key = 자신의 REST API 키
그 다음 나는 yml을 사용하므로 application.yml에
이렇게 추가해주는데, application.properties를 사용하더라도 그냥 spring.profiles.include=API-KEY 라고 적으면 될듯(?)
파일이름에 API-KEY라는 문자가 들어가는 파일도 관리한다? 라고 생각하면 될듯.
그리고 .gitignore 파일에
src/main/resources/application-API-KEY.properties
를 추가해 준다.
그리고 이런식으로 사용하면 된다. 출력해보면 API 키를 받은 것을 확인할 수 있을것이다.
이제 Kakao API 를 호출해보자.
일단 오늘의 목표는 서울 시청의 100m 이내의 맛집을 검색을 목표로 잡았다.
아까 언급한 https://developers.kakao.com/docs/latest/ko/local/dev-guide#search-by-keyword
API를 사용할 것인데, 정보를 봐보면
나는 JSON으로 받을 것이고, GET 형식으로 요청하면 된다.
그리고 헤더인데 Host는 어차피
https://dapi.kakao.com/v2/local/search/keyword.JSON?
이런식으로 요청할테니 Host는 따로 설정 안해줘도 되고 중요한 것이 Authorization이다.
보면 Authorization 헤더에 KakaoAK (한 칸 띄고) (API 키) 임을 나타낸다.
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setRequestProperty("Authorization", "KakaoAK " + kakao_apikey);
con.setRequestMethod("GET");
이런식으로 할 예정이다. 보면 KakaoAK 하고 한 칸 띄운 것을 볼 수 있다.
이제 파라미터인데 query만 필수이므로 query는 필수적으로 넣어주고, 여기서 나는 category_group_code, x, y, radius만 사용할 예정이다. (category_group_code에서 FD6값은 API 정보에 음식점이라는 정보라고 나와있음)
x와 y는 위도 경도이므로 서울 시청의 위도 경도를 알아야하는데 카카오 api에서 주소 검색하기라는 api를 통해 위도 경도를 알 수 있지만 일단은 구글 지도를 통해서 위도 경도를 알아낸 후 진행했다.(나중에 구현 예정)
서울 시청의 위도, 경도
위도 : 37.5606326
경도 : 126.9433486
코드를 봐보면
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
@Service
public class KakaoAPI {
@Value("${kakao_apikey}")
private String kakao_apikey;
public String getRestaurant() {
try {
// 맛집 단어 UTF-8로 인코딩
String query = URLEncoder.encode("맛집", "UTF-8");
// 파라미터를 사용하여 요청 URL을 구성한다.
String apiURL = "https://dapi.kakao.com/v2/local/search/keyword.JSON?" +
"query=" + query
+ "&category_group_code=" + "FD6"
+ "&x=" + "37.5606326"
+ "&y=" + "126.9433486"
+ "&radius=" + "100";
URL url = new URL(apiURL);
HttpURLConnection con = (HttpURLConnection)url.openConnection();
// 요청 헤더를 setRequestProperty로 지정해준다. 헤더가 더 많을시 더 추가하면 됨.
con.setRequestProperty("Authorization", "KakaoAK " + kakao_apikey);
con.setRequestMethod("GET");
// 응답 코드 확인
int responseCode = con.getResponseCode();
BufferedReader br;
// 정상 응답이 200이므로(http 상태코드)
if(responseCode == 200) { // 정상 호출
br = new BufferedReader(new InputStreamReader(con.getInputStream()));
} else { // 에러 발생
br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
}
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = br.readLine()) != null) {
response.append(inputLine);
}
br.close();
// System.out.println(response.toString());
return response.toString();
} catch (Exception e) {
System.out.println(e);
}
return "";
}
}
설명은 대충 주석에 적었고, service와 controller를 구현한다.
package com.lunchpick.lunchpick.service;
import com.lunchpick.lunchpick.service.externalAPI.KakaoAPI;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class LocationService {
private final KakaoAPI kakaoAPI;
public String getRestaurant() {
return kakaoAPI.getRestaurant();
}
}
package com.lunchpick.lunchpick.controller;
import com.lunchpick.lunchpick.service.LocationService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@RestController
@RequiredArgsConstructor
public class PickController {
private final LocationService locationService;
@RequestMapping(value = "/test", method = RequestMethod.GET)
@ResponseBody
public String getRest(){
return locationService.getRestaurant();
}
}
이렇게 하고 결과를 확인하면
제대로 결과가 나왔다.
private final KakaoAPI kakaoAPI;
여기서 final을 뺐었다. 즉, 의존성 주입이 안된 상태였던 것...
03. kakao API로 주소를 좌표로 변환 후 주위 맛집 찾기 (0) | 2021.12.25 |
---|---|
02. kakao API를 기존 HttpURLConnection에서 RestTemplate로 변경, 받은 데이터 객체화 (2) | 2021.12.19 |