ajax - json 이용하기, 부제 : String자료형 ↔ Json자료형 (2022.10.21)
1. 서론
이전 게시물에서 간단하게 ajax통신에 대해서 알아보았다.
XMLHttpRequest 객체로 인하여 페이지 전환(새로고침)이 일어나지 않고도
데이터와 데이터의 교환이 가능했고, @ResponseBody에 의하여 body안에 데이터에
return값의 문자열을 넣어준 후 출력할 수 있었다.(ex1.jsp)
XMLHttpRequest 객체에 의해 send를 사용할 수 있고, body태그에 데이터를
send에 넣어 Controller클래스에 @RequestBody로 인하여 데이터를 저장할 수 있고
저장된 데이터는 return값의 문자열로 들어가 출력이 되었다(ex2.jsp)
두 예제가 이해가 되었다면 이번에는 Json을 사용하여 다수의 데이터를 보내고 출력하고 하는
전혀 잡기술 같지 않은 잡기술에 대해 알아보도록 하자..;
2. 본론
2-1. json??
그런데 json은 무엇인가?
진~~~~~~~~~짜 간단하게 얘기하자면 ajax 통신을 사용하기 위해 만들어진 배열 이라고 말할 수 있을 거 같다.
보통 HashMap 방식처럼 객체(Object)를 이름/값 쌍으로 가지고 가는데 얘 태생은 문자열(String)데이터 이다.
여기서 부턴 지극히 개인적인 생각입니다. 피드백은 적극 환영합니다.
어차피 json이란 얘도 javascript에서 파생되어 나온 얘라 text/html로 처리해도 된다.
왜?
어차피 String데이터니까
근데 실질적인 json확장자 파일에 코드를 불러오려면 이 String데이터도 json으로 변환시켜줄 필요가 있다.
왜? 냐고 물어보면...예를 들어보자
진짜 극단적으로 생각해보면??
미국가서 한국말 쓰면 미국인들이 알아먹을까? 거꾸로 미국인이 한국와서 영어 쓰면 우리는 알아먹을까?
그런 거다..
=========================개인적인 생각 절취선=========================
사용자가 json에 있는 자료를 요청했을 때, 이것을 String 데이터로 변환하여 사용자가 보기 편하게 웹페이지에 출력할 방법이 필요한 것이다.
이때 사용하는 라이브러리가 'jackson DataBind' 이다.
pom.xml
1 2 3 4 5 6 | <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.4.2</version> </dependency> | cs |
pom에 위 코드를 붙여넣기 하고 Maven Depnedencies를 확인해 보자.
제대로 추가된게 확인 되면 alt+F5를 눌러 저장하도록 하자.
이러면 이제 String 데이터를 Json데이터로 변환하거나 Json데이터를 String 데이터로 변환 하는게 가능해진다.
2-2. 사용해보자.
우선 해당 코드부터 확인하고 흐름을 파악해보도록 하자.
ex3.jsp
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ex3</title> <script type="text/javascript"> var req function send() { req = new XMLHttpRequest(); req.onreadystatechange = changeText req.open('post', "ex3") /* value값을 가져갈거라 .value를 작성 */ var i=document.getElementById('id').value var p=document.getElementById('pw').value /* 문자열은 ''이나 ""로 설정되어야 하는데 밑에있는건 그냥 json형식만 갖춘 자료임 */ var reqData = {id:i, pw:p} /* json형 자료형을 String으로 형변환을 시켜준다. */ reqData = JSON.stringify(reqData) /* response에 넣게 되면 클라이언트(웹)에 알려주는 거고 request에 넣게 되면 서버에 알려주는거*/ /* 내가 보내려는 건 json의 문자열이니 json으로 처리해줘 */ req.setRequestHeader('Content-Type', "application/json; charset=UTF-8") req.send(reqData) } function changeText() { if(req.readyState == 4 && req.status == 200){ var printId = document.getElementById("printId") var printPw = document.getElementById("printPw") /* JSON.parse(req.responseText) << 문자열의 자료형을 json의 자료형으로 변환 */ var resData = JSON.parse(req.responseText) /* resData.id를 하면 id의 키값을 가져올 수 있음. */ /* resData.pw를 하면 pw의 키값을 가져올 수 있음. */ printId.innerHTML = resData.id printPw.innerHTML = resData.pw } } </script> </head> <body> <input type="text" id="id" placeholder="아이디" /><br> <input type="password" id="pw" placeholder="비밀번호"><br> 응답 아이디 : <span id="printId"></span><br> 응답 비밀번호 : <span id="printPw"></span><br> <button type="button" onclick="send()">데이터 가져오기</button> </body> </html> | cs |
AjaxController.java
컨트롤러 자바클래스는 계속 한 곳에 갱신중이니 코드를 붙여넣고 임포트가 필요한 곳은 해주면 되겠다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // ex3 Mapping 시작==================================================== @GetMapping("ex3") public String ex3Get() { return "ajax/ex3"; } //응답에 리턴값을 담아서 전달하겠다 라는 어노테이션어 @ResponseBody @PostMapping(value="ex3", produces = "application/json; charset=UTF-8") // 서버에서는 아까 임포트한 jackson databind가 처리해준다. public HashMap<String, String> ex3Post( @RequestBody HashMap<String, String> map) { System.out.println("아이디 : " + map.get("id")); System.out.println("비밀번호 : " + map.get("pw")); map.put("id", "아이디"); map.put("pw", "비밀번호"); return map; } // ex3 Mapping 도착==================================================== | cs |
ex3의 전체적인 흐름은 이렇다고 생각된다.
그래서 결과를 확인해보면??
각각 아이디와 비밀번호 입력해보고?
데이터 가져오기를 클릭하면?
콘솔에서 해당 입력값이 정상적으로 나오는 것을 볼 수 있고
HashMap에 각각의 value 값도 바꿔봤는데 페이지에 정상적으로 나오는 것을 확인할 수 있었다.
여담이지만 map.put으로 아이디와 value값을 초기화하여 새로운 값을 집어넣었기 때문에 위와 같은 결과가 나오지만
put대신 map.get을 반환값으로 보냈다면 웹페이지엔 ex2번과 같은 결과가 나왔을거라 생각한다.
자..........이제 본격적으로 json의 자료를 받아보자.
json은 java파일도 아니고 jsp파일도 아니므로 resources폴더에 들어간다.
해당 파일의 경로는 다음과 같다.
해당 json파일의 코드는 다음과 같다.
ex5.json
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 32 33 34 35 36 37 38 39 40 41 42 43 44 | { "cd" : [ { "title" : "Empire Burlesque", "artist" : "Bob Dylan", "price" : "10.90" }, { "title" : "Hide your heart", "artist" : "Bonnie Tyler", "price" : "9.90" }, { "title" : "Greatest Hits", "artist" : "Dolly Parton", "price" : "9.90" }, { "title" : "Still got the blues", "artist" : "Bob Dylan", "price" : "10.20" }, { "title" : "Eros", "artist" : "Eros Ramazzotti", "price" : "9.90" }, { "title" : "One night only", "artist" : "Bee Gees", "price" : "10.90" }, { "title" : "Sylvias Mother", "artist" : "Dr.Hook", "price" : "8.10" }, { "title" : "Maggie May", "artist" : "Rod Stewart", "price" : "8.50" }, { "title" : "Empire Burlesque", "artist" : "Bob Dylan", "price" : "10.90" }, { "title" : "Hide your heart", "artist" : "Bonnie Tyler", "price" : "9.90" }, { "title" : "Greatest Hits", "artist" : "Dolly Parton", "price" : "9.90" }, { "title" : "Still got the blues", "artist" : "Bob Dylan", "price" : "10.20" }, { "title" : "Eros", "artist" : "Eros Ramazzotti", "price" : "9.90" }, { "title" : "One night only", "artist" : "Bee Gees", "price" : "10.90" }, { "title" : "Sylvias Mother", "artist" : "Dr.Hook", "price" : "8.10" }, { "title" : "Maggie May", "artist" : "Rod Stewart", "price" : "8.50" }, { "title" : "Empire Burlesque", "artist" : "Bob Dylan", "price" : "10.90" }, { "title" : "Hide your heart", "artist" : "Bonnie Tyler", "price" : "9.90" }, { "title" : "Greatest Hits", "artist" : "Dolly Parton", "price" : "9.90" }, { "title" : "Still got the blues", "artist" : "Bob Dylan", "price" : "10.20" }, { "title" : "Eros", "artist" : "Eros Ramazzotti", "price" : "9.90" }, { "title" : "One night only", "artist" : "Bee Gees", "price" : "10.90" }, { "title" : "Sylvias Mother", "artist" : "Dr.Hook", "price" : "8.10" }, { "title" : "Maggie May", "artist" : "Rod Stewart", "price" : "8.50" }, { "title" : "Empire Burlesque", "artist" : "Bob Dylan", "price" : "10.90" }, { "title" : "Hide your heart", "artist" : "Bonnie Tyler", "price" : "9.90" }, { "title" : "Greatest Hits", "artist" : "Dolly Parton", "price" : "9.90" }, { "title" : "Still got the blues", "artist" : "Bob Dylan", "price" : "10.20" }, { "title" : "Eros", "artist" : "Eros Ramazzotti", "price" : "9.90" }, { "title" : "One night only", "artist" : "Bee Gees", "price" : "10.90" }, { "title" : "Sylvias Mother", "artist" : "Dr.Hook", "price" : "8.10" }, { "title" : "Maggie May", "artist" : "Rod Stewart", "price" : "8.50" }, { "title" : "Empire Burlesque", "artist" : "Bob Dylan", "price" : "10.90" }, { "title" : "Hide your heart", "artist" : "Bonnie Tyler", "price" : "9.90" }, { "title" : "Greatest Hits", "artist" : "Dolly Parton", "price" : "9.90" }, { "title" : "Still got the blues", "artist" : "Bob Dylan", "price" : "10.20" }, { "title" : "Eros", "artist" : "Eros Ramazzotti", "price" : "9.90" }, { "title" : "One night only", "artist" : "Bee Gees", "price" : "10.90" }, { "title" : "Sylvias Mother", "artist" : "Dr.Hook", "price" : "8.10" }, { "title" : "Maggie May", "artist" : "Rod Stewart", "price" : "8.50" } ] } | cs |
먼저 개발자 도구에 json파일에 있는 데이터를 불러오도록 해볼까?
먼저 부분적인 코드부터 확인해보자
ex4.jsp 中 console에 값 나타내기
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 32 33 34 35 36 37 38 39 40 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ex4</title> <script type="text/javascript"> var req function send() { req = new XMLHttpRequest(); req.onreadystatechange = changeText req.open('post', "ex4") req.send(null) } function changeText() { if(req.readyState == 4 && req.status == 200){ var tbody = document.getElementById("tbody") tbody.innerHTML = "아직은 데이터가 없음." console.log(JSON.parse(req.responseText)) } } </script> </head> <body> <button type="button" onclick="send()">실행</button> <table border="1"> <thead> <tr> <th>title</th> <th>artist</th> <th>price</th> </tr> </thead> <tbody id="tbody"> </tbody> </table> </body> </html> | cs |
AjaxController.java의 ex4 코드
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 32 33 34 | // ex4 Mapping 시작==================================================== @GetMapping("ex4") public String ex4Get() { return "ajax/ex4"; } @ResponseBody @PostMapping(value="ex4", produces = "application/json; charset=UTF-8") public String ex4Post() throws FileNotFoundException, IOException { ClassPathResource resource = new ClassPathResource("ex5.json"); // 원래는 File 객체를 생성하면 c드라이브부터 찾아 들어가야 하나(전체경로) // ClassPathResource덕분에 src/main/resources 하위부터 읽어올 수 있다 FileReader reader = new FileReader(resource.getFile()); BufferedReader buffer = new BufferedReader(reader); String data = ""; while(true) { // 한줄 씩 읽어와줘 (BufferedReader(buffer).readLine) String tmp = buffer.readLine(); if(tmp == null) break; data += tmp; } System.out.println(data); return data; } // ex4 Mapping 도착==================================================== | cs |
ex1,2,3을 대충 이해했다면 이번 예제는 쉽게 이해할 수 있으리라 필자는 생각한다.
일단 java의 ex4 코드 중에 몇 가지 객체를 좀 설명하자면....
throws FileNotFoundException, IOException
예외처리를 위한 Exception코드이다. 보통 DAO할 때 많이 쓰던 try-catch문을 사용하기 귀찮아서 사용했다.
ClassPathResource
이 객체는 본래 File객체를 생성할 경우 C드라이브부터 파일이 있는 경로를 직접 찾아주어야 한다.
하지만 이 객체를 사용함으로서 src/main/resources 하위를 자동적으로 읽어와 주기 때문에 사용한다.
FileReader
파일을 비동기적으로 읽어들이는 데에 사용한다.
BufferedReader
이 객체는 필자가 오직 자바로 회원관리와 같은 프로젝트를 만들 때 사용했던 Scanner와 비슷하다.
보통 Scanner로 객체를 생성하면 입력이 이루어졌을 때, 띄어쓰기와, 개행(줄바꿈)을 경계로 인식한다.
BufferedReader는 오직 개행(줄바꿈)만 인식이 되며 입력받은 데이터는 String으로 고정된다.
새로울만한 객체들도 몇가지 소개를 했고, 필자가 생각하는 전체적인 흐름은 이렇다.
그러면 결과를 보도록 하자.
실행 버튼을 누르기 전엔 아무 데이터도 나오지 않는다.
실행 버튼을 누르며 '아직은 데이터가 없음.' 이라는 문구가 웹페이지에 출력되었고?
console창에 json의 자료가 출력되는 것을 볼 수 있고?
0~39 총 40개의 데이터가 정상적으로 출력되는 것을 볼 수 있다.
이제 이 데이터들을 웹페이지에 출력해볼 생각이다.
ex4.jsp 中 웹페이지에 json 자료들 출력하기
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ex4</title> <script type="text/javascript"> var req function send() { req = new XMLHttpRequest(); req.onreadystatechange = changeText req.open('post', "ex4") req.send(null) } function changeText() { if(req.readyState == 4 && req.status == 200){ var tbody = document.getElementById("tbody") var resData = JSON.parse(req.responseText) var printData = '' //cd를 지정하면 resData.cd만 지정하면 값을 얻어낼 수 있고(40), //resData.cd.length라 하면 값의 길이(0~39)를 얻어낼수 있다. for(i = 0; i < resData.cd.length; i++){ printData += "<tr><td>"+resData.cd[i].title+"</td>" printData += "<td>"+resData.cd[i].artist+"</td>" printData += "<td>"+resData.cd[i].price+"</td></tr>" } tbody.innerHTML = printData } } </script> </head> <body> <button type="button" onclick="send()">실행</button> <table border="1"> <thead> <tr> <th>title</th> <th>artist</th> <th>price</th> </tr> </thead> <tbody id="tbody"> </tbody> </table> </body> </html> | cs |
전체적인 흐름은 console창에 출력하는 것과 같다.
다른게 있다면 반환값이 String 이니까 그것을 Json으로 형변환으로 추가적으로 변수(resData)에 저장시켜주었고,
printData라는 변수 하나를 만들어 초기화 시켜주고, resData가 갖고 있는 ex5.json파일의 cd변수의 길이만큼 for문을 돌려 printData라는 변수가 테이블 형식으로 웹페이지에 저장되게끔 설정했다.
결과를 보도록 하자.
이게 40개의 데이터인지는 모르겠으나 필자는 40개라 굳게 믿고 잘 출력되었다고 말하겠다(무책임)
3. 결론
놀라운건 이게 끝이 아니다. 이제 전체 리스트를 뽑아올 수 있으면
검색을 해서 해당 데이터만 볼 수 있게끔 해보고자 한다.
솔직히..................................머리 아파서 죽을 거 같다..
새로운 친구를 사귀었는데 그 친구가 '인싸' 라서 나도 그 친구의 친구를 자연스럽게 사귀고 있는 느낌?
아직 새 친구도 어떤애인지 천천히 알아가고 있었는데, 그 친구는 그걸 아는건지...
자신의 친구를 대뜸 나에게 소개해줘서 알아가야 할 사람이 하나 더 늘은 느낌.....
스프링을 하니 AJAX통신이 따로오고 더불어 JSON까지 딸려온다고
아.ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
살려줘ㅓㅓㅓㅓㅓㅓㅓㅓㅓㅓㅓㅓㅓㅓㅓㅓㅓㅓ....