Open API를 활용해 숙박 상품 데이터를 수집하기로 하여 다음과 같이 RestTemplate을 사용해 REST API를 호출했습니다.
// ~~ 생략 ~~
private String makeBaseSearchUrl() {
String STAY_SEARCH_URI = "/searchStay1";
return BASE_URL
+ STAY_SEARCH_URI
+ "?serviceKey="
+ SERVICE_KEY
+ DEFAULT_QUERY_PARAMS;
}
// ~~생략~~
private JSONObject getAccommodation(int pageSize, int pageNum) throws JSONException {
URI uri = UriComponentsBuilder.fromHttpUrl(makeBaseSearchUrl())
.queryParam("pageNo", pageNum)
.queryParam("numOfRows", pageSize)
.build().toUri();
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET,
httpEntity, String.class);
log.info("숙박 정보 조회");
return new JSONObject(response.getBody())
.getJSONObject("response")
.getJSONObject("body");
}
// ~~ 생략 ~~
그런데 결과를 보니, 아래처럼 SERVICE_KEY_IS_NOT_REGISTERED_ERROR
라는 응답이 오고 있었습니다.
분명 활용 신청을 통해 발급받은 서비스 키를 사용했는데도 등록되지 않은 서비스 키라는 응답만 돌아왔습니다.
혹시, 인코딩 문제가 아닐까 의심하기 시작했고, 위 코드의 SERVICE_KEY
를 인코딩된 서비스키로도 넣어보고, 인코딩되지 않은 서비스키로도 넣어봤습니다.
하지만, 같은 응답이 돌아올 뿐이었습니다.
원인은 의심한대로 인코딩 문제였습니다.
private JSONObject getAccommodation(int pageSize, int pageNum) throws JSONException {
URI uri = UriComponentsBuilder.fromHttpUrl(makeBaseSearchUrl())
.queryParam("pageNo", pageNum)
.queryParam("numOfRows", pageSize)
.build().toUri();
// ~~ 생략 ~~
위 코드에서 사용한 UriComponentBuilder
는 공백
과 +
를 인코딩해주지 않는다고 합니다. 이 때문에 디코딩된 서비스 키를 UriComponentBuilder를 통해 인코딩한 경우 올바르게 인코딩된 서비스키가 보내지지 않은 것이었습니다.
인코딩된 서비스키를 사용하는 경우 이중 인코딩이 일어납니다. 이 또한 올바르게 인코딩된 서비스키가 보내지지 않습니다.
// ~~ 생략 ~~
private String makeBaseSearchUrl() {
String STAY_SEARCH_URI = "/searchStay1";
return BASE_URL
+ STAY_SEARCH_URI
+ "?serviceKey="
+ URLEncoder.encode(SERVICE_KEY, StandardCharsets.UTF_8)
+ DEFAULT_QUERY_PARAMS;
}
URLEncoder.encode()를 사용하여 따로 인코딩해줍시다.
private JSONObject getAccommodation(int pageSize, int pageNum) throws JSONException {
URI uri = UriComponentsBuilder.fromHttpUrl(makeBaseSearchUrl())
.queryParam("pageNo", pageNum)
.queryParam("numOfRows", pageSize)
.build(true).toUri();
// ~~ 생략 ~~
이중 인코딩을 막기 위해 UriComponentBuilder의 build() 호출 시 true값을 옵션으로 부여합니다.
Open API를 사용할 때 서비스 키와 함께 요청 URI 인코딩에 유의해야 한다는 것을 느낄 수 있었고, UriComponentBuilder의 인코딩 특징에 대해 알 수 있어 유익했습니다.