kwondroid의 개발 세계

(JAVA) Naver API로 가져온 JSON을 GSON으로 Parse하기 본문

개발

(JAVA) Naver API로 가져온 JSON을 GSON으로 Parse하기

kwondroid 권오철 2018. 7. 23. 04:10

네이버 API를 통해 서버에서 넘어온 Json을 파싱하는 법을 알아보겠다.


GSON을 이용한다.


먼저 프로젝트에 GSON을 Import하자. (설명은 여기)


그 다음 애플리케이션 등록을 하자 (등록은 여기)


자세한 등록 방법은 설명하지 않겠다.




등록을 마치면 클라이언트 키와 비밀번호를 발급받는다.


그 후 코드를 작성하자.

public class ShopInformDTO {
public String lastBuildDate;
public int total;
public int start;
public int display;
public Item[] items;

class Item {
public String title;
public String link;
public String category;
public String description;
public String telephone;
public String address;
public String roadAddress;
public String mapx;
public String mapy;
}
}


public class Main {

public static void main(String[] args) {

int cnt = 1; // 출력 갯수

String clientId = "안알랴줌";
String clientSecret = "안알랴줌";

String temp_json;
String json = "";
String search_word;

ShopInformDTO inform;

BufferedReader br;

Scanner scan = new Scanner(System.in); // for 입력

URLConnection urlConn;
URL url;

try {
search_word = URLEncoder.encode(scan.nextLine(), "UTF-8"); // 검색어
url = new URL("https://openapi.naver.com/v1/search/local.json?query=" + search_word + "&display=" + 100); //API 기본정보의 요청 url을 복사해오고 필수인 query를 적어줍니당!
urlConn = url.openConnection(); //openConnection 해당 요청에 대해서 쓸 수 있는 connection 객체

urlConn.setRequestProperty("X-Naver-Client-ID", clientId);
urlConn.setRequestProperty("X-Naver-Client-Secret", clientSecret); // do not setting,

br = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));

while ((temp_json = br.readLine()) != null) {
json += temp_json;
}
json = json.trim();


} catch (Exception e) {
System.out.println("ERROR");

e.printStackTrace();
}
inform = new Gson().fromJson(json, ShopInformDTO.class);
}

}


코드에 대한 설명은 하지 않겠다. 긴 코드도 아니고, 만약 이해가 안된다면 해매야한다. 그게 우리가 할 일 이니까.


쿼리문은 설명이 필요할 것 같다. 그래서 문서 링크를 첨부한다.

https://developers.naver.com/docs/search/blog/


이것만 보면 별거 아닌 코드처럼 보인다.

사실 그렇다. 별거 아닌 코드다. 내가 며칠 해맸던 이유는 json 파싱 결과를 DTO에 넣는것을 어떻게 해야 하는건지 몰랐기 때문이다.


출력되는 json의 구조는 이러하다.


{
"lastBuildDate": "Mon, 16 Jul 2018 01:28:44 +0900",
"total": 2,
"start": 1,
"display": 2,
"items": [{
    "title": "<b>설빙</b> 경기광명철산점",
    "link": "http://sulbing.com/",
    "category": "카페,디저트>빙수",
    "description": "디저트 카페, 빙수, 토스트, 커피, 스무디, 녹차라떼, 오미자차 등 판매.",
    "telephone": "02-2611-1478",
    "address": "경기도 광명시 철산동 410",
    "roadAddress": "경기도 광명시 오리로856번길 8-1",
    "mapx": "300065",
    "mapy": "542034"
}, {
    "title": "<b>설빙</b> 하안점",
    "link": "",
    "category": "카페,디저트>빙수",
    "description": "경기도 광명시 하안동 위치, 디저트카페, 빙수 전문점.",
    "telephone": "02-899-0503",
    "address": "경기도 광명시 하안동 34-3",
    "roadAddress": "경기도 광명시 하안로 309 세인빌딩",
    "mapx": "301042",
    "mapy": "540690"
}]
}

items안에 array 형식으로 값이 존재한다.

gson 사용법을 구글링 해봤을때 이런 형식을 파싱하는 법은 보이지 않았다. (어딘가에 있었겠지...)


단순히 array값을 어떻게 파싱을 해야할지 감이 잡히지 않았었다.


그래서 스택오버플로우에 직접 물어본 결과는 저 위의 DTO를 만들고 items 배열을 만들어 파싱을 해야한다.


https://stackoverflow.com/questions/51350347/how-to-parse-jsonitems


고찰

힙이 터질것 같다고요?

네이버 api 서비스는 한번 call을 하면 최대 100개의 item을 request합니다. 100개의 DTO로 힙이 터질 일은 없다고 본다.

Total값만큼 가져오면 어떡하냐고요?

테스트도중 total이 900개 정도 정보를 가져오는 결과도 본 적 있다. 그리고 total은 더욱 많아질 수 있다. 사실 이정도 되는 개수의 배열을 만든다면 그때는 성능 문제가 아니라 진짜 힙이 터지는걸 걱정해야 할 수 있다. (엄청 심각하게 걱정할 필요는 없을것같다.
고로 NDK, C의 도움을 빌리는것도 좋을것이다. 성능도 성능이지만 메모리를 직접 컨트롤을 해야 메모리가 펑펑 터지는 상황을 면할 수 있을것이니말이다. 쉽지는 않을것이다. 아무리 ndk라고 하더라도 데이터가 물리적으로(?) 엄청나게 많고 모바일 기기라는 특성때문이다. 게임, 임베디드 프로그래머 수준으로 c++을 갈아보는거로...

DTO(구조체)의 데이터를 최소화하여 파싱과정에서 필요 없는 데이터는 걸러주어 메모리 부담을 최소화해주자.

그리고 RecyclerView처럼 성능에 중점을 둔 뷰를 사용하자.

Json을 불러오는데 시간이 얼마나 걸리나요?

정말 의외로 시간이 걸리지 않는다. 안드로이드 환경에서 테스트 한 결과 준수한 속도가 나온다. Gson자체 파싱 속도도 빨라 큰 고민은 안해도 될 듯 하다. (vu 2)

String 을 += 할 시 성능이 안좋아질 것 같다구요?

맞긴 맞다. + 연산을 할 시 객체를 재 생성하기때문에 성능이 낮아지는것이다. 하지만 언제부터인가 자바 컴파일러가 String의 + 연산을 자동으로 최적화해준다.

An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate String object. To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.


그러니까 고민하지 말자. 

(안드로이드의 경우에 어떤지 잘 모르겠다... 우리의 액시노스를 믿자... ㅠ 폰 cpu는 스냅드레곤 씹어먹잖아... 으헹헹... ㅠ)

기타.

AsyncTask나 Multy Threading을 사용하자. 나는 귀찮아서 안드로이드의 쓰레드 정책을 무시하는 코드를 쓰고 메인쓰레드에서 대충실행을 했는데 어지간하면 구글이 추천하는 방법을 쓰자. (os)제조사가 막아 놓은걸 뚫어서 실행을 하는게 안정적일리가 만무하다. 그냥 더 귀찮더라도 AsyncTask나 Multy Threading을 쓰자. 컹...


Comments