티스토리 뷰

반응형

해당 글의 소스코드는 링크 걸어 두었습니다.

 

GitHub - dolgogae/TIL: Today I Learned

Today I Learned. Contribute to dolgogae/TIL development by creating an account on GitHub.

github.com

 

앞선 Get, Post를 통해서 Naver API를 호출해보는 실습을 하자.

 

네이버의 API는 https://developers.naver.com/여기서 확인 할 수 있다.

그 중에서 지역 검색과 이미지 검색을 호출하는 것을 개발해보도록 하자.

 

Document > 검색 > 지역을 들어가면 다음처럼 API spec을 볼 수 있다.

네이버의 경우에는 굉장히 깔끔하고 이쁘게 정리를 해두어 개발하기가 매우 편하다.

 

가장 처음 봐야할 것은 Get방식을 사용한다는 것을 알고 있어야 한다. 

그 다음은 우리가 어떤 uri를 통해서 API를 호출하는 지 확인해야한다. 위에서는 https://openapi.naver.com/v1/search/local.json 이라고 되어 있다.

또한, Json을 이용할 것이기 때문에 출력 포맷을 Json으로 선택했다.

그리고 나서는 우리가 요청(request)할 변수들을 확인하면 된다.

 

그것을 우리는 객체를 통해서 만들어 주면 된다. 

SearchLocalReq.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class SearchLocalReq{
    private String query="";
    private int display=1;
    private int start=1;
    private String sort="random";

    public MultiValueMap<String, String> toMultiValueMap(){
        var map = new LinkedMultiValueMap<String, String>();

        map.add("query", query);
        map.add("display", String.valueOf(display));
        map.add("start", String.valueOf(start));
        map.add("sort", sort);
        return map;
    }
}

 

다음처럼 spec에 맞는 자료형으로 생성해주면 되고, 이후에 uri에 파라미터로 넣기 편하게 하기 위해 

toMultiValueMap을 매서드로 만들어 주었다.

 

 

또 위처럼 응답을 받을 것이라서 이것도 객체로 만들어 주면 된다.

 

SearchLocalRes.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class SearchLocalRes {
    private String lastBuildDate="";
    private int total=1;
    private int start;
    private int display;
    private List<Item> items;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Item {
        private String title;
        private String link;
        private String description;
        private String category;
        private String telephone;
        private String address;
        private String roadAddress;
        private int mapx;
        private int mapy;
    }
}

 

Item의 경우에는 위의 spec에서 볼 수 있듯 여러개의 변수가 묶음으로 있는 변수이기 때문에

다음처럼 inner 객체를 통해서 만들어 주었다.

 

그 다음으로는 앞서 해봤던, Get 방식을 통해서 호출하기만 하면 된다.

 

NaverSearchClient.java

@Component
public class NaverSearchClient {

    @Value("${naver.client.search.id}")
    private String naverClientId;

    @Value("${naver.client.search.secret}")
    private String naverClientSecret;

    @Value("${naver.url.search.local}")
    private String naverLocalSearchUrl;

    @Value("${naver.url.search.image}")
    private String naverImageSearchUrl;

    public static<T> ResponseEntity<T> search(MultiValueMap<String, String> mv,
                                        ParameterizedTypeReference<T> responseType,
                                        String url, String id, String passwd){
        URI uri = UriComponentsBuilder.fromUriString(url)
                .queryParams(mv)
                .build()
                .encode()
                .toUri();

        HttpHeaders header = getHttpHeaders(id, passwd, MediaType.APPLICATION_JSON);

        var httpEntity = new HttpEntity<>(header);

        var responseEntity = new RestTemplate().exchange(
                uri,
                HttpMethod.GET,
                httpEntity,
                responseType
        );
        
        return responseEntity;
    }

    private static HttpHeaders getHttpHeaders(String id, String passwd, MediaType contentType){
        HttpHeaders header = new HttpHeaders();
        header.set("X-Naver-Client-Id", id);
        header.set("X-Naver-Client-Secret", passwd);
        header.setContentType(contentType);
        return header;
    }

    public SearchLocalRes searchLocal(SearchLocalReq searchLocalReq){
        var mv = searchLocalReq.toMultiValueMap();
        var responseType = new ParameterizedTypeReference<SearchLocalRes>(){};
        var responseEntity = search(mv, responseType, naverLocalSearchUrl,  naverClientId, naverClientSecret);

        return responseEntity.getBody();
    }
}

 

위 소스코드에서 조금 더 설명을 하자면

public SearchLocalRes searchLocal(SearchLocalReq searchLocalReq){
    var mv = searchLocalReq.toMultiValueMap();
    var responseType = new ParameterizedTypeReference<SearchLocalRes>(){};
    var responseEntity = search(mv, responseType, naverLocalSearchUrl,  naverClientId, naverClientSecret);

    return responseEntity.getBody();
}

해당 부분에서는 위 사이트에서 확인 할 수 있듯이 검색에는 여러 종류가 있고,

우리는 그중 지역에 대한 것만 하기 때문에 Generic하게 search함수를 만드는 것이 좋아서

호출부를 분리하였다.

 

그리고 responseType의 경우에는 ParameterizedTypeReference<응답 받을 객체>를 통해서 

우리가 만든 객체를 응답 받을 수 있다.

 

다음으로는 직접 통신을 하는 구현부 이다.

 

public static<T> ResponseEntity<T> search(MultiValueMap<String, String> mv,
                                    ParameterizedTypeReference<T> responseType,
                                    String url, String id, String passwd){
    URI uri = UriComponentsBuilder.fromUriString(url)
            .queryParams(mv)		// uri 변수
            .build()
            .encode()
            .toUri();

    HttpHeaders header = getHttpHeaders(id, passwd, MediaType.APPLICATION_JSON);

    var httpEntity = new HttpEntity<>(header);

    var responseEntity = new RestTemplate().exchange(
            uri,
            HttpMethod.GET,			// 통신방식
            httpEntity,				// 헤더 정보
            responseType			// 응답받을 형식
    );

    return responseEntity;
}

 

대부분은 앞선 코드와 비슷하지만 응답의 경우를 넣어주는것이 조금 변경되었다.

우선 HttpHeaders를 통해서 header를 좀더 간단하게 만들어 주었고, HttpEntity를 통해서 감싸주었다.

 

그리고 가장 중요한 RestTemplate의 경우에 다음과 같이 변수를 넣어서 호출을 하면

우리는 응답값을 responseType에 맞게 받을 수 있다.

 

생각보다 상당히 간단하다. 이렇게 다른 Get 호출의 경우에도 어렵지 않게 응답값을 얻을 수 있을 것이다.

728x90
반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함
250x250