[java]JSON & XML Data Format

송어·2023년 11월 22일

JSON(JavaScript Object Notation)과 XML(Extensible Markup Language)은 둘 다 구조화된 데이터를 표현하고 전송하기 위한 데이터 형식이다. JSON과 XML은 각각의 장단점이 있으며, 사용 목적과 상황에 따라 적절한 데이터 형식을 사용하는 것이 좋다.
최근 웹 & 모바일 애플리케이션에서는 JSON형식의 데이터 전송이 더 많이 사용되는 추세이다.

JSON(JavaScript Object Notation)

JSON은 경량의 데이터 교환 형식으로, 텍스트 기반의 구조화된 데이터를 표현한다. JSON은 가독성이 좋고, 다양한 프로그래밍 언어와 호환되기 때문에 현재 널리 사용되고 있다.
JSON 데이터 형식의 구조는 다음과 같다.

1. 객체(Object)
JSON 객체는 중괄호{} 로 묶인 키-값 쌍의 집합이다. 키(Key)는 문자열(String)이고, 값(Value)는 JSON 데이터 형식 중 하나가 될 수 있다.
키-값은 콜론(:)으로 구분되며, 여러 개의 키-값 쌍은 쉼표로 구분된다.

{
  "name":"홍길동",
  "age":30,
  "email":"honggildong321@naver.com",
  "isStudent":false,
  "city":"서울",
  "country":"대한민국"
}
  1. 배열(Array)
    JSON 배열은 대괄호[] 로 묶인 값들의 순서 있는 리스트이다. 배열의 요소는 JSON 데이터 형식 중 하나가 될 수 있으며, 여러 개의 요소는 쉼표(,)로 구분된다.
{
    "dog": [
        "웰시코기",
        "포메라니안",
        "푸들",
        {
            "ownerName": "홍길동",
            "phone": "01012345678"
        }
    ]
}

위의 예제에서 "dog"라는 이름의 JSON 배열은 문자열뿐만 아니라 객체도 요소로 가지고 있다.

XML(Extensible Markup Language)

XML은 데이터를 저장하고 전송하기 위한 마크업 언어이다.
XML 데이터는 트리 구조로 이루어져 있으며, 다음과 같은 요소(element), 속성(attribute), 텍스트(text), 주석(comment)등으로 구성된다.

<!-- This is a member element> // comment
<member id="1">
	<name>홍길동</name>
    <age>30</age>
    <email>honggildong321@naver.com</email>
    <address city="서울" country="대한민국" //attribute /> 
    	
</member>

JSON과 XML 모두 구조화된 데이터를 표현하는데 효과적이지만, 가독성과 데이터 크기에서 차이가 있다.
JSON은 간결한 구조로 인해 가독성이 높고 데이터 크기가 작다. 반면에 XML은 태그를 사용해 데이터를 표현하기 때문에 가독성이 상대적으로 낮고 데이터 크기가 크다.

GsonAPI 활용

GsonAPI를 사용해 JSON데이터를 자바에서 활용해보자

public class GsonTest {
    public static void main(String[] args) {
        Member mvo = new Member("홍길동", 30, "fast@gmail.com");

        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        String json = gson.toJson(mvo); // 인스턴스를 Json타입으로 변환

        System.out.println("json = " + json);

        Member member = gson.fromJson(json, Member.class); // Json타입을 인스턴스로 변환

        System.out.println("member = " + member);
    }
}

중첩된 JSON 구조 핸들링

GsonAPI는 JSON 데이터 안에 데이터가 중첩된 구조라도 간편하게 핸들링 할 수 있다.
다음은 JSON으로 변환하려는 데이터의 model 구조이다.

public class Member {
    private String name;
    private int age;
    private String email;
    private Address address;

    public Member() {
    }

    public Member(String name, int age, String email, Address address) {
        this.name = name;
        this.age = age;
        this.email = email;
        this.address = address;
    }
    // 이하 생략
}
public class Address {
    private String city;
    private String country;

    public Address(String city, String country) {
        this.city = city;
        this.country = country;
    }
    // 이하 생략
}

member에서 받는 데이터로 address객체가 포함되어 있다. 이를 데이터로 받게 되면 json 객체의 value값으로 객체가 들어있는 구조가 출력된다.

public class GsonTest {
    public static void main(String[] args) {
        Address address = new Address("서울", "대한민국");
        Member mvo = new Member("홍길동", 30, "fast@gmail.com", address); 

        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        String json = gson.toJson(mvo); // 인스턴스를 Json타입으로 변환

        System.out.println("json = " + json);

        Member member = gson.fromJson(json, Member.class); // Json타입을 인스턴스로 변환

        System.out.println("member = " + member);
    }
}

---------------------------------------------------------------------------------------------------

<result>
json = {
  "name": "홍길동",
  "age": 30,
  "email": "fast@gmail.com",
  "address": {
    "city": "서울",
    "country": "대한민국"
  }
}

member = Member{name='홍길동', age=30, email='fast@gmail.com', address=Address{city='서울', country='대한민국'}}

member 클래스는 데이터로 address 객체를 받았다. 이를 JSON으로 변환하면 address key의 value로 address 객체가 들어가 있는 구조를 볼 수 있다.

JsoupAPI로 크롤링

GsoupAPI는 자바로 만들어진 HTML 파서(Parser)로, HTML 문서에 포함된 데이터를 분석 추출 할 수 있도록 도와주는 JAVA 오픈소스 라이브러리다. jsoup는 HTML을 파싱해 HTML 요소들을 jsoup 요소(Element)객체로 만들어 자바에서 사용할 수 있도록 만들어준다.

이번에 Jsoup에 대해 알게 되면서 나중에 다루어볼 네이버증권 데이터를 크롤링해 보기로 했다.

네이버 주식 페이지 중 코스피 데이터 상위 기준 1~250번까지 뽑아보기로 했다. 페이지당 50개의 종목 데이터가 나열되어 있는데 get방식으로 데이터를 가져와 for문을 사용해 쿼리 파라미터 페이징을 변경하는 방식으로 250P까지 가져와 볼 계획이다.

public class JsoupTest {
    public static void main(String[] args) {
        for(int i = 1; i<=5; i++) {
           String stockList = "https://finance.naver.com/sise/sise_market_sum.naver?&page="+i;

           try {
               Document document = Jsoup.connect(stockList).get();
               String stockThead = getStockThead(document);
               String stockTbody = getStockTbody(document);

               if(i == 1) {
                   System.out.println(stockThead);
                   System.out.println();
               }
               System.out.println(stockTbody);

           }catch(Exception e) {

           }
        }
    }

    public static String getStockThead(Document document) {
        Elements elementThead = document.select("table.type_2 thead tr");
        StringBuilder sb = new StringBuilder();

        for(Element element : elementThead.select("th")) {
            sb.append(element.text());
            sb.append(" "); // 공백
        }
        return sb.toString();
    }

    public static String getStockTbody(Document document) {
        Elements elementTbody = document.select("table.type_2 tbody tr");
        StringBuilder sb = new StringBuilder();

        for(Element element : elementTbody){
            if (element.attr("onmouseover").isEmpty()) {
                continue;
            }
            for(Element td : element.select("td")) {
                String text;
                if(td.select(".center a").attr("href").isEmpty()) {
                text = td.text();
                }else {
                    text = "https://finance.naver.com" + td.select(".center a").attr("href");
                }
                sb.append(text);
                sb.append(" ");
            }
            sb.append(System.getProperty("line.separator"));
        }
        return sb.toString();
    }
}

먼저 전체 코드이다.

for(int i = 1; i<=5; i++) {
           String stockList = "https://finance.naver.com/sise/sise_market_sum.naver?&page="+i;
// 이하 생략

for문을 사용해 쿼리 파라미터의 페이지를 조정하면서 자체 페이징 처리를 했다.

try {
    Document document = Jsoup.connect(stockList).get();
    String stockThead = getStockThead(document);
    String stockTbody = getStockTbody(document);

    if(i == 1) {
       System.out.println(stockThead);
       System.out.println();
    }
    System.out.println(stockTbody);
	
    }catch(Exception e) {

    }
   // 이하 생략
    

get방식을 사용하는 경우 url이 안맞을 때 예외가 터진다고 해서 try-catch문을 사용해 예외처리를 해주었다. 다음으로 크롤링에 사용한 메서드를 분석해보겠다.

public static String getStockThead(Document document) {
        Elements elementThead = document.select("table.type_2 thead tr");
        StringBuilder sb = new StringBuilder();

        for(Element element : elementThead.select("th")) {
            sb.append(element.text());
            sb.append(" "); // 공백
        }
        return sb.toString();
    }

먼저 table의 thead 부분을 따로 가져와 크롤링했다.

이미지에 해당되는 부분을 가져왔는데 Elements elementThead = document.select("table.type_2 thead tr");로 thead의 tr을 Element객체로 만들어 놓은 다음 th를 for문을 사용해 개별 값으로 나누어주었다. 나누어진 값은 StringBuilder를 사용해 길어지는 문자열을 손쉽게 처리했다.

String은 불변객체로서 + 연산으로 String을 더하면 단순히 더해지는 것이 아닌 새로운 String이 생성된다. 즉 메모리 할당과 해제를 동시에 발생시키며 대량의 문자열을 +연산자로 처리할 경우 성능 부하가 생긴다고 한다.
이에 비해 StringBuilder는 String문자열을 더할 때 기존 데이터에 더하는 방식을 사용하기 때문에 속도도 빠르고 상대적으로 부하가 적다고 한다.
대량의 문자 데이터를 관리하는 경우 StringBuilder를 사용하는 것이 좋겠다.

public static String getStockTbody(Document document) {
        Elements elementTbody = document.select("table.type_2 tbody tr");
        StringBuilder sb = new StringBuilder();

        for(Element element : elementTbody){
            if (element.attr("onmouseover").isEmpty()) {
                continue;
            }
            for(Element td : element.select("td")) {
                String text;
                if(td.select(".center a").attr("href").isEmpty()) {
                text = td.text();
                }else {
                    text = "https://finance.naver.com" + td.select(".center a").attr("href");
                }
                sb.append(text);
                sb.append(" ");
            }
            sb.append(System.getProperty("line.separator")); // 줄바꿈
        }
        return sb.toString();
    }
}

다음은 tbody에 있는 코스피 데이터를 가져왔다. 5개의 데이터마다 tr에 공백처리가 되어있어서
onmouseover 속성만 붙어있는 tr태그에만 접근할 수 있도록 조건문을 추가했다.

이후 tr태그 안에 있는 td데이터만 접근해 추출하기 위해 한번더 for문을 사용해 td데이터만 추출했다. 토론실 링크같은 경우 a태그로 구분되어 있어 if문을 사용해 구분해서 추출했다.
sb.append(System.getProperty("line.separator"));로 td태그 데이터 추출이 완료될 때마다 줄바꿈 처리를 했다.

N 종목명 현재가 전일비 등락률 액면가 시가총액 상장주식수 외국인비율 거래량 PER ROE 토론실 

1 삼성전자 72,500 300 -0.41% 100 4,328,092 5,969,783 53.50 7,738,476 15.41 17.07 https://finance.naver.com/item/board.naver?code=005930 
2 LG에너지솔루션 440,500 6,500 -1.45% 500 1,030,770 234,000 4.55 95,135 67.75 5.75 https://finance.naver.com/item/board.naver?code=373220 
3 SK하이닉스 130,200 1,800 -1.36% 5,000 947,859 728,002 52.66 1,416,653 -8.25 3.56 https://finance.naver.com/item/board.naver?code=000660 
4 삼성바이오로직스 721,000 1,000 -0.14% 2,500 513,165 71,174 10.19 19,601 62.15 11.42 https://finance.naver.com/item/board.naver?code=207940 
5 삼성전자우 56,900 600 -1.04% 100 468,223 822,887 72.64 611,540 12.10 N/A https://finance.naver.com/item/board.naver?code=005935 
6 POSCO홀딩스 470,500 3,500 -0.74% 5,000 397,908 84,571 26.66 239,097 32.13 6.11 https://finance.naver.com/item/board.naver?code=005490 
7 현대차 182,800 1,400 -0.76% 5,000 386,680 211,532 32.87 150,358 4.40 9.36 https://finance.naver.com/item/board.naver?code=005380 
8 LG화학 503,000 2,000 +0.40% 5,000 355,079 70,592 43.65 86,207 30.22 6.95 https://finance.naver.com/item/board.naver?code=051910 
9 NAVER 205,500 1,000 +0.49% 100 333,750 162,409 47.35 172,593 39.79 3.29 https://finance.naver.com/item/board.naver?code=035420 
10 기아 82,900 700 -0.84% 5,000 333,295 402,044 38.47 493,388 3.64 14.57 https://finance.naver.com/item/board.naver?code=000270 
11 삼성SDI 468,500 2,500 +0.54% 5,000 322,162 68,765 45.71 143,556 15.60 12.52 https://finance.naver.com/item/board.naver?code=006400 
12 셀트리온 172,500 300 +0.17% 1,000 252,545 146,403 20.39 238,196 46.00 13.35 https://finance.naver.com/item/board.naver?code=068270 
13 포스코퓨처엠 304,500 1,000 +0.33% 500 235,876 77,463 5.72 450,839 291.67 4.87 https://finance.naver.com/item/board.naver?code=003670 
14 카카오 50,300 1,050 +2.13% 100 223,581 444,496 25.95 1,438,546 513.27 13.54 https://finance.naver.com/item/board.naver?code=035720 
15 KB금융 54,500 400 +0.74% 5,000 219,914 403,511 72.54 368,227 4.80 9.17 https://finance.naver.com/item/board.naver?code=105560 
16 삼성물산 118,100 600 -0.51% 100 219,184 185,592 19.14 61,477 9.64 7.16 https://finance.naver.com/item/board.naver?code=028260 
17 현대모비스 229,500 2,000 -0.86% 5,000 214,938 93,655 38.60 39,969 6.34 6.80 https://finance.naver.com/item/board.naver?code=012330 
18 신한지주 37,000 50 +0.14% 5,000 190,737 515,504 60.11 275,038 4.29 9.70 https://finance.naver.com/item/board.naver?code=055550 
19 LG전자 107,700 700 -0.65% 5,000 176,249 163,648 29.31 250,990 47.49 6.61 https://finance.naver.com/item/board.naver?code=066570 
20 SK이노베이션 142,000 200 -0.14% 5,000 142,931 100,656 21.45 136,407 -57.49 8.49 https://finance.naver.com/item/board.naver?code=096770 
21 삼성생명 69,600 100 +0.14% 500 139,200 200,000 16.82 51,875 6.53 5.73 https://finance.naver.com/item/board.naver?code=032830 
22 LG 84,700 1,800 -2.08% 5,000 133,234 157,301 36.31 42,839 12.77 8.48 https://finance.naver.com/item/board.naver?code=003550 
23 카카오뱅크 26,150 150 +0.58% 5,000 124,685 476,807 15.55 1,026,729 38.57 4.68 https://finance.naver.com/item/board.naver?code=323410 
24 하나금융지주 41,800 100 -0.24% 5,000 122,205 292,357 68.78 425,335 3.22 10.06 https://finance.naver.com/item/board.naver?code=086790 
25 KT&G 91,200 0 0.00% 5,000 122,046 133,822 42.45 51,854 17.08 11.00 https://finance.naver.com/item/board.naver?code=033780 
26 SK 163,700 300 -0.18% 200 119,826 73,198 22.82 59,966 -12.96 5.13 https://finance.naver.com/item/board.naver?code=034730 
27 삼성화재 251,500 3,000 +1.21% 500 119,148 47,375 53.38 25,832 7.50 9.70 https://finance.naver.com/item/board.naver?code=000810 
28 메리츠금융지주 55,800 0 0.00% 500 116,186 208,218 16.74 150,423 5.33 30.32 https://finance.naver.com/item/board.naver?code=138040 
29 한국전력 18,080 130 +0.72% 5,000 116,067 641,964 13.80 653,171 -0.57 -46.91 https://finance.naver.com/item/board.naver?code=015760 
30 SK텔레콤 52,000 100 -0.19% 100 113,793 218,833 41.42 231,368 10.07 7.97 https://finance.naver.com/item/board.naver?code=017670 
31 삼성에스디에스 146,500 700 +0.48% 500 113,358 77,378 15.98 39,201 14.25 14.23 https://finance.naver.com/item/board.naver?code=018260 
32 HMM 16,220 130 +0.81% 5,000 111,762 689,039 9.07 525,355 3.74 64.98 https://finance.naver.com/item/board.naver?code=011200 
33 HD현대중공업 122,900 4,500 +3.80% 5,000 109,102 88,773 7.16 102,568 -101.07 -6.47 https://finance.naver.com/item/board.naver?code=329180 
34 고려아연 494,500 500 -0.10% 5,000 103,393 20,909 18.46 14,230 16.53 9.38 https://finance.naver.com/item/board.naver?code=010130 
35 삼성전기 138,100 400 +0.29% 5,000 103,152 74,694 30.89 76,404 17.63 13.76 https://finance.naver.com/item/board.naver?code=009150 
36 포스코인터내셔널 58,200 700 -1.19% 5,000 102,387 175,923 6.20 416,586 14.37 15.79 https://finance.naver.com/item/board.naver?code=047050 
37 크래프톤 209,000 0 0.00% 100 101,078 48,363 32.25 49,078 22.43 10.29 https://finance.naver.com/item/board.naver?code=259960 
38 우리금융지주 12,680 40 -0.31% 5,000 95,347 751,949 37.34 457,907 3.16 11.51 https://finance.naver.com/item/board.naver?code=316140 
39 두산에너빌리티 14,640 50 -0.34% 5,000 93,778 640,561 13.06 1,301,449 -21.88 -11.70 https://finance.naver.com/item/board.naver?code=034020 
40 기업은행 11,710 10 +0.09% 5,000 93,379 797,426 14.02 294,789 3.18 9.85 https://finance.naver.com/item/board.naver?code=024110 
41 KT 33,000 250 -0.75% 5,000 85,094 257,861 42.64 182,380 7.18 7.99 https://finance.naver.com/item/board.naver?code=030200 
42 하이브 199,100 100 -0.05% 500 82,929 41,652 20.60 113,026 107.56 1.87 https://finance.naver.com/item/board.naver?code=352820 
43 대한항공 22,450 150 -0.66% 5,000 82,666 368,221 16.14 363,811 6.15 21.95 https://finance.naver.com/item/board.naver?code=003490 
44 S-Oil 70,200 100 +0.14% 2,500 79,033 112,583 76.89 75,406 8.05 27.20 https://finance.naver.com/item/board.naver?code=010950 
45 아모레퍼시픽 132,200 2,300 -1.71% 500 77,327 58,493 26.92 60,233 58.06 2.81 https://finance.naver.com/item/board.naver?code=090430 
46 HD한국조선해양 103,000 1,900 +1.88% 5,000 72,896 70,773 25.03 133,044 176.37 -2.22 https://finance.naver.com/item/board.naver?code=009540 
47 TIGER CD금리투자KIS(합성) 53,360 10 +0.02% 0 72,606 136,068 0.02 168,933 N/A N/A https://finance.naver.com/item/board.naver?code=357870 
48 삼성중공업 7,970 260 +3.37% 1,000 70,136 880,000 20.03 5,476,906 -34.21 -16.08 https://finance.naver.com/item/board.naver?code=010140 
49 SK바이오팜 89,400 800 +0.90% 500 70,012 78,313 7.62 72,428 -82.85 -36.66 https://finance.naver.com/item/board.naver?code=326030 
50 SK스퀘어 49,400 100 +0.20% 100 68,657 138,981 45.33 134,929 -4.30 1.55 https://finance.naver.com/item/board.naver?code=402340 

51 현대글로비스 178,700 1,000 -0.56% 500 67,012 37,500 48.03 20,591 5.76 18.78 https://finance.naver.com/item/board.naver?code=086280 
52 롯데케미칼 156,400 100 +0.06% 5,000 66,901 42,775 25.14 41,302 -116.98 0.43 https://finance.naver.com/item/board.naver?code=011170 
53 에코프로머티 97,400 900 +0.93% 500 66,453 68,227 0.66 10,552,940 331.29 6.77 https://finance.naver.com/item/board.naver?code=450080 
54 KODEX 200 33,685 40 -0.12% 0 66,393 197,100 4.72 1,874,476 N/A N/A https://finance.naver.com/item/board.naver?code=069500 
55 한화에어로스페이스 121,400 1,400 +1.17% 5,000 61,465 50,630 33.86 166,409 8.75 6.98 https://finance.naver.com/item/board.naver?code=012450 
56 한화오션 28,100 1,350 +5.05% 5,000 60,941 216,873 3.46 1,019,416 -2.75 -117.79 https://finance.naver.com/item/board.naver?code=042660 
57 카카오페이 45,400 550 +1.23% 500 60,895 134,130 40.10 90,101 121.07 3.08 https://finance.naver.com/item/board.naver?code=377300 
58 LG이노텍 256,500 1,500 +0.59% 5,000 60,706 23,667 20.76 41,983 14.51 25.85 https://finance.naver.com/item/board.naver?code=011070 
59 한미반도체 61,800 300 +0.49% 100 60,156 97,339 11.52 862,535 29.84 25.04 https://finance.naver.com/item/board.naver?code=042700 
60 한화솔루션 33,750 550 -1.60% 5,000 58,014 171,893 23.19 418,348 535.71 4.21 https://finance.naver.com/item/board.naver?code=009830 

// 이하생략

추출된 데이터 결과이다.

0개의 댓글