처음에 앱을 만들고 Rest API 를 사용하려고 방법을 찾고 공부해봤을 때 어려운 점이 많았어서 내가 배운 것을 정리할 겸 이 글을 보고 Rest API 를 조금 더 쉽게 사용할 수 있도록 이 글을 적어 보려고 한다.
일단 첫 글에는 네이버 지도 API 인 Maps에서 Rest API 를 사용하는 법에 대해 예를 들어 적어보려고 한다.
1) Directions 5 API
https://guide.ncloud-docs.com/docs/maps-direction5-api
Directions 5 API
guide.ncloud-docs.com
Directions 5는 네이버에서 지원하는 Rest API 중 하나로 출발지 목적지 및 경유지(선택 사항 최대 5개)의 정보를 보내면 응답으로 경로 데이터배열을 받는다.
1-1)사용법
Rest API의 사용법에서 가장 중요한 것은 요청 파라미터와 헤더를 Interface로 구현하고 응답바디를 Class로 구현 하는 것이다.
Directions 5 공식문서에 보면
이런 식으로 요청 파라미터, 요청헤더, 요청 바디가 있다.
요청 파라미터와 헤더를 살펴보자
보통 헤더는 해당 사이트의 Rest API를 사용하는 경우라면 비슷하거나 같은 경우가 많은 것 같다. 그래서 우리가 중요하게봐야하는 항목은 파라미터 부분이다. 파라미터에 이름들을 전부 공식문서의 이름들과 똑같이 해주어야 한다. 오타나 다르게 하면 작동하지 않는다.. 또한 필수 여부에 Y라고 되어있는 파라미터는 필수적으로 넣어줘야하고 부가적으로 더 얻고 싶은 정보가 있다면 넣어주면 된다. 또한 Rest API는 전부 String 형태로 서버에 요청을 보내기 때문에 파라미터의 자료형은 String으로 맞춰주면 된다.
public interface RouteFind_nomid {
@GET("v1/driving")
Call<RoutePath> getData(@retrofit2.http.Header("X-NCP-APIGW-API-KEY-ID")String ClientID,
@Header("X-NCP-APIGW-API-KEY") String Secret,
@Query("start") String start, @Query("goal") String goal)
;
}
이건 내가 만든 Driving5의 요청 Interface이다. 여기서 Call은 Rest API를 호출할때 사용되는 명으로 나중에 다루기로 한다. 또한 RoutePath는 응답바디를 구성하는 Class 명이다. 그리고 getData라는 메소드를 만들어서 이를 통해 서버에 요청을 보낼 수 있다.
@Get 부분은 서버에 정보를 요청하는 부분인데 @GET("API URL에서 끝에 들어가는부분 ")이다
예를 들어
https://naveropenapi.apigw.ntruss.com/map-direction/v1/driving
에서에서는 끝부분에 해당하는 v1/dirving 이다
●헤더부분은 @Header ("헤더명") 자료형 변수명 으로 구현
● 파라미터 부분은 @Query("파라미터명") 자료형 변수명 으로 구현
■요청바디
요청바디 또한 공식문서를 보면
요청바디는 Class로 구현하는데 필수여부로 돼있는 부분은 필수적으로 다 구현해주어야한다. 또한 이름도 응답바디의 속성명과 똑같이 해주어야 한다. 그리고 변수별로 get메서드를 적어주어야 한다. 타입을 보면 이해하기 어려울 수 있는데 이때는 응답 예시를 보는게 쉬울 수 있다. 예시 응답 또한 공식문서에 첨부되어 있다.
String처럼 자료형이 정해져있는 경우엔 그대로 쓰면 되지만 route 같이 자료형이 이해하기 어려운 경우엔 응답 예시를 보면 route 안에 trafast가 있다. 이 trafast는 위의 요청 파라미터에서 무엇을 요청했는지에 따라 달라지는데 기본값은 traoptimal 이다. 그리고 trafast안에는 summary path 가 있다. 이러한 것을 Class로 구현하려면 Class를 여러개로 만들어야한다.
public class RoutePath {
@SerializedName("code")
@Expose
private int code;
@SerializedName("messge")
@Expose
private String messge;
@SerializedName("currentDateTime")
@Expose
private String currentDateTime;
@SerializedName("route")
@Expose
private Route route;
public int getCode() {
return code;
}
public Route getRoute() {
return route;
}
public String getCurrentDateTime() {
return currentDateTime;
}
public String getMessge() {
return messge;
}
}
class Route{
@SerializedName("traoptimal")
@Expose
private List<Traoptimal> traoptimal;
public List<Traoptimal> getTraoptimal() {
return traoptimal;
}
}
class Traoptimal{
@SerializedName("summary")
@Expose
private Summary summary;
@SerializedName("path")
@Expose
private List<List<Double>> path;
public Summary getSummary() {
return summary;
}
public List<List<Double>> getPath() {
return path;
}
}
class Summary{
@SerializedName("start")
@Expose
private Start start;
@SerializedName("goal")
@Expose
private Goal goal;
@SerializedName("distance")
@Expose
private int distance;
public Goal getGoal() {
return goal;
}
이게 예시 응답과 공식문서를 참고하여 만든 Class이다. 보면 Route라는 Class를 만들어서 자료형 처럼 사용하고 있고 그 밑에 여러 Class 및 기본 자료형을 두어서 필수 여부에 Y가 돼있는 것을 다 만들어 주고 Get 메서드까지 달아 주었다.
이렇게 Interface와 Class를 만들어 주었다면 이제 실제로 Retrofit을 통해 호출해 보자
■Retrofit
Retrofit은 Rest API를 사용할 때 쓰는 것으로 사용방법은
1) 의존성 추가
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.squareup.retrofit2:converter-gson:2.6.4'
gradle에 의존성을 추가해주고
2) 인터넷 권한 설정
<uses-permission android:name="android.permission.INTERNET" />
Manifests에 권한 설정을 추가해주면 된다.
이제 실제로 호출하는 코드를 보자.
Retrofit retrofit0 = new Retrofit.Builder()
.baseUrl("https://naveropenapi.apigw.ntruss.com/map-direction/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
RouteFind_nomid routeFind0 = retrofit0.create(RouteFind_nomid.class);
Call<RoutePath> call0 = routeFind0.getData(NavaApIKey,secret,start_lng+","+start_lot,end_lng+","+end_lot); //네이버 길찾기 rest api 시작 출발점 찍으면 됨
call0.enqueue(new Callback<RoutePath>() {
@Override
public void onResponse(Call<RoutePath> call, Response<RoutePath> response) {
if(response.isSuccessful()) {
RoutePath routePath=response.body();
List<List<Double>> path=routePath.getRoute().getTraoptimal().get(0).getPath();
PathOverlay line_path=new PathOverlay(); //길 선 표시할 path 배열
for(int i=0;i<path.size();i++) {
list.add(new LatLng(path.get(i).get(1), path.get(i).get(0)));
}
markers[0]=new Marker();
markers[0].setPosition(new LatLng(start_lot,start_lng));
markers[0].setCaptionText("출발지");
markers[0].setMap(naverMap);
markers[1]=new Marker();
markers[1].setPosition(new LatLng(end_lot,end_lng));
markers[1].setCaptionText("목적지");
markers[1].setMap(naverMap);
line_path.setCoords(list);
line_path.setMap(naverMap);
}
}
@Override
public void onFailure(Call<RoutePath> call, Throwable t) {
Log.d(TAG,"실패");
}
});
이 코드는 Rest API를 통해 서버에 출발 지 목적지 위경도를 주어서 거기까지의 경로를 선으로 그리고 출발지 목적지에 마커를 찍는 코드이다.
사용할 때 Retrofit 을 선언해주고 .baseUrl 부분에 서버에 요청을 보낼 baseUrl
즉 v1/driving 앞에 부분을 넣어주고 RouteFind_nomid 클래스를 선언해준 Retrofit의 .create 메서드 안에 넣어준다.
그리고 Call 을 선언해서 앞에 선언한 Retrofit이 Interface의 getData의 값을 받게된다.
getData안에 헤더값과 요청하고자 하는 값을 넣어주면 선언 해준 call0로 enque를 보내서 response를 통해 결과값
즉 응답값을 받게 된다.
RoutePath 우리가 선언해준 Class에 response.body() 즉 응답바디를 넣으면 우리가 선언해둔 값들을 사용할 수 있게 되는 것이다.
결과는 이렇게 잘 나온 것을 볼 수 있다.