딸기말차

[Java web] 11. File Up/Download, JQuery, Ajax, Json 본문

Bootcamp/Java web

[Java web] 11. File Up/Download, JQuery, Ajax, Json

딸기말차 2023. 8. 1. 02:08

엔코아 플레이데이터(Encore Playdata) Backend 2기 백엔드 개발 부트캠프 (playdata.io)

 

백엔드 개발 부트캠프

백엔드 기초부터 배포까지! 매력있는 백엔드 개발자 포트폴리오를 완성하여 취업하세요.

playdata.io


1. File Upload

1. multipart/form-data

web에는 전송 속도, 1회 당 전송 크기가 존재한다.

web에서 데이터를 송수신 할 때, 단위가 byte가 아니라 bit 단위이기(1Gb) 때문에 1GB짜리를 보내면 이를 한번에 보낼 수가 없다. 또한, 데이터를 전송 시 손실도 발생할 수 있다.
때문에 이를 쪼개서 보내야하고 해당 기능을 가진 multipart를 사용한다.

 

2. FileUpload Servlet

파일 업로드를 위한 servlet으로, 해당 servlet의 동작 과정은 다음과 같다.

 

1) File 객체 생성
파일을 저장할 디렉터리 경로를 저장한다.
2) DiskFileItemFactory 객체 생성
File 객체에 담아둔 경로와 업로드 시킬 파일의 크기를 정해 저장한다.
3) ServletFileUpload 객체 생성
DiskFileItemFactory 객체를 파라미터로, 경로와 파일 크기를 저장한다.
4) upload.parseRequest(request)

ServletFileUpload의 메서드를 통해 request 객체로 들어온 데이터를 전부 List에 저장한다.
5) FileItem fileItem = (FileItem) items.get(i)

List에 저장 된 데이터를 for문을 통해 FileItem 형태로 하나씩 추출한다.
6) fileItem.isFormField()
해당 메서드를 통해 추출한 데이터가 text면 console에 출력한다.
7)  if (fileItem.getSize() > 0)

추출한 데이터가 text가 아니면, 업로드한 파일의 크기를 확인한다.
8) 파일 크기가 0보다 크면, 가장 마지막에 존재하는 \\ 또는 / 의 index를 찾는다.
이는 OS마다 디렉터리 경로를 표현하는 방법이 다르기 때문이다.
9) fileItem.getName().substring(idx + 1)

경로가 설정 되었으면, 업로드 할 파일명을 추출하기 위해 subString 을 사용한다.
이때 주의할 점은, \\ 또는 / 를 찾은 index에 + 1을 해줘야 파일명이 시작된다는 점이다.
10) File uploadFile = new File(currentDirPath + "\\" + fileName)

File 객체에 저장할 디렉터리 경로 + "\\" + 파일명 을 저장해 최종 경로를 정해준다.
11) fileItem.write(uploadFile)

FileItem 객체의 write 메서드를 통해 최종 경로에 파일을 업로드한다.

private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("utf-8");
    String encoding = "utf-8";

    /* 업로드 사전 준비 */
    File currentDirPath = new File("C:\\file_repo");
    DiskFileItemFactory factory = new DiskFileItemFactory(); // 이 factory 내부에 파일 경로 설정, 크기 설정 메서드가 있다.
    factory.setRepository(currentDirPath); // 파일을 저장할 디렉터리 설정
    factory.setSizeThreshold(1024 * 1024); // 업로드 시킬 파일의 크기 설정, bit 단위이다.
    ServletFileUpload upload = new ServletFileUpload(factory); // 실질적으로 파일을 업로드 시켜주는 역할

    /* 업로드 시작 */
    try {
        List items = upload.parseRequest(request); // request 객체로 들어온 모든 데이터를 List 형태로
        for (int i = 0; i < items.size(); i++) {
            FileItem fileItem = (FileItem) items.get(i); // 파일 아이템 형태로 저장해야 isFormField()를 사용할 수 있다.

            if (fileItem.isFormField()) // isFormField는 파일과 입력한 값을 구별할 수 있다.
                System.out.println(fileItem.getFieldName() + "=" + fileItem.getString(encoding));
            else {
                /* input type="file" */
                System.out.println("파라미터명:" + fileItem.getFieldName()); // file1
                System.out.println("파일명:" + fileItem.getName()); // 선택한 이미지 파일 
                System.out.println("파일크기:" + fileItem.getSize() + "bytes"); // 선택한 이미지 크기

                if (fileItem.getSize() > 0) { // 업로드 파일 크기 확인
                    int idx = fileItem.getName().lastIndexOf("\\");
                    if (idx == -1) // "\\" 가 없으면 "/" 를 찾아야한다. (os마다 틀리기 때문)
                        idx = fileItem.getName().lastIndexOf("/");

                    String fileName = fileItem.getName().substring(idx + 1); // 찾은 index + 1 부분부터 끝까지 자름 -> 파일명 추출
                    File uploadFile = new File(currentDirPath + "\\" + fileName);
                    fileItem.write(uploadFile); // 설정 완료한 경로에 파일 업로드
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

 

파일 업로드를 할 때, form 태그에 반드시 encType=multipart/form-data 을 설정해주는 것을 잊으면 안된다.

<form action="${contextPath}/upload.do" method="post" enctype="multipart/form-data">
    파일1: <input type="file" name="file1"><br> 
    파일2: <input type="file" name="file2"> <br> 
    파라미터1: <input type="text" name="param1"> <br> 
    파라미터2: <input type="text" name="param2"> <br> 
    파라미터3: <input type="text" name="param3"> <br> 
    <input type="submit" value="업로드">
</form>

2.  File Download

1. File Download 구현?

파일 다운로드 기능은 Java IO를 이용해 구현할 수 있다. 이 때 response 객체를 통해 OutputStream을 얻고, 배열 형태의 버퍼를 생성한다. 왜냐하면 JSP의 버퍼 사이즈가 기본 8KB이기 때문에, 파일을 한번에 전송할 수 없기 때문이다.

이 후 while문을 통해 파일을 8KB씩 분할해 버퍼에 저장하고, OutputStream의 write()를 통해 브라우저로 출력하게 된다.

 

2. FileDownload Servlet

파일 다운로드를 위한 servlet으로, 해당 servlet의 동작 과정은 다음과 같다.

 

1) String fileName = (String) request.getParameter("fileName")
request 객체를 통해 받아온 파일의 이름을 String 형태로 파싱해 저장한다. 이때 파일이름.확장자 형태로 저장된다.
2) response.setHeader("Cache-Control", "no-cache"); 
    response.addHeader("Content-disposition", "attachment; fileName=" + fileName);

실제 다운로드가 가능하게 response 객체를 통해 HttpRequestMessage의 Header 부분을 설정한다.
3) String downFile = "C:\\file_repo\\" + fileName
파일이 저장되어있는 장소의 경로를 저장한다.
4) File file = new File(downFile);

File 객체를 생성하고, 파일이 저장되어 있는 장소의 경로를 저장한다. 
5) FileInputStream in = new FileInputStream(file)

File을 스트림 방식으로 읽기 위한 객체를 생성하고, File 객체를 저장해둔다.
6) OutputStream out = response.getOutputStream()
가져온 파일을 브라우저에 출력하기위해, OutputStream을 생성한다.
7)  byte[] buffer = new byte[1024 * 8];

파일은 Byte 형태로 변환되어 이동하기 때문에 Byte 배열을 선언하고, 8KB씩 읽기 위한 초기화를 한다.
8) int count = in.read(buffer)
Byte 단위로 파일을 읽는 read() 를 통해 배열을 하나씩 읽어온다.
9) if (count == -1)

파일을 읽다가 실패하면 -1이 return되어 count에 저장된다. 이를 이용해 파일을 끝까지 읽었을 시, 반복문을 정지한다.
10) out.write(buffer, 0, count)

브라우저에 출력, 이때 파라미터는 출력대상, startIndex, 개수 이다.

private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("utf-8");
    response.setContentType("text/html; charset=utf-8");

    String fileName = (String) request.getParameter("fileName"); // 파일명.확장자
    response.setHeader("Cache-Control", "no-cache"); 
    response.addHeader("Content-disposition", "attachment; fileName=" + fileName);

    String downFile = "C:\\file_repo\\" + fileName; // 어디에 업로드 되어있는 파일인지
    File file = new File(downFile);
    FileInputStream in = new FileInputStream(file); // 파일을 스트림 방식으로 읽기 위한 객체 생성
    OutputStream out = response.getOutputStream(); // 브라우저로 출력하기 위한 OutputStream

    byte[] buffer = new byte[1024 * 8]; // 8KB 씩 읽기 위한 byte 배열
    while (true) {
        int count = in.read(buffer); // byte 단위로 읽는 read(), read() 내에 byte배열을 넣게 되면 읽은 byte값을 하나 씩 배열에 채운다.
        if (count == -1) // 8KB 씩 읽다가, 읽은 내용이 없으면 -1 을 반환
            break;
        out.write(buffer, 0, count); // 브라우저에 출력, write(출력대상, startIndex, 개수)
    }
    in.close();
    out.close();
}

 

실제 파일을 다운로드 할 땐 <a> 태그를 사용할 수 있다. <a> 태그의 href 속성에 파일의 이름을 파라미터로 넣어, 해당 파일을 탐색 후 저장소에 존재한다면, 다운로드 할 수 있게 되는 것이다. 

파일 내려받기 :
<a href="${contextPath}/download.do?fileName=${file1}">파일 1 내려받기</a> <br>
<a href="${contextPath}/download.do?fileName=${file2}">파일 2 내려받기</a> <br>

3. JQuery

1. JQuery ?

웹 페이지는 브라우저 상에서 DOM (Document Object Model)이라는 표준 형식으로 Parsing 되어 표현된다.

따라서 클라이언트의 조작에 맞춰 동적으로 변화하는 대화형 웹(Interactive Web)을 구현하기 위해서는 Dom 조작이 필수적이라 볼 수 있다.

JQuery는 이 DOM 조작을 간편하게 다룰 수 있고, 이벤트 설정과 Ajax까지 사용할 수 있다. 

하지만 단점 또한 존재하는데, 브라우저 상에서 DOM 조작이 발생할 때마다 새로운 연산을 하는 것과 마찬가지기 때문에 클라이언트의 조작이 빈번해 질 수록 브라우저의 성능이 낮아진다.


2. 특징 및 사용방법

* 특징
1. CSS 선택자를 사용해 각 HTML 태그에 접근해서 작업하므로 읽기 쉬운 형태로 표현할 수 있다.
2. 메서드 체인 방식으로 수행하므로 여러개의 동작이 한줄로 나열되어, 코드가 불필요하게 반복되는 것을 피할 수 있다.
3. 풍부한 플러그인을 제공하므로 이미 개발 된 많은 플러그인을 쉽게 이용할 수 있다.
4. 크로스 브라우징을 제공하므로 브라우저 종류에 상관 없이 동일한 기능을 수행할 수 있다.

* 사용방법
1. www.jquery.com 에서 라이브러리 다운
2. 네트워크로 CDN 호스트를 설정해서 사용

 

3. JQuery 실습

HTML 의 id에 접근 시에는 #을, class에 접근 시에는 . 을 사용한다.

 

1) HTML 태그 내 id 접근

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript"> 
	// 페이지가 로딩 될 때
	$(document).ready(function() {
    		// unique 라는 id에 접근, 내부 내용을 경고창으로 띄워준다.
    		alert($("#unique").html());
	});
</script>

<div id="unique">
    <p>제이쿼리는 아주 쉽습니다!!!</p>
</div>

2) JS 메서드를 통해 HTML 태그 내 id에 접근해 태그 내에 데이터 삽입

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
    // input 태그의 button을 통해 JS 메서드 실행
    function addHtml() {
    	// HTML 태그 내 article 이란 ID에 접근, 내부 <p></p> 태그 사이에 데이터 삽입
    	$("#article").html('안녕하세요'+'<br>'); 
    }
</script>

<div>
    <p id="article"></p>
</div>
<input type="button" value="추가하기" onClick="addHtml()" />

3) JS 메서드를 통해 HTML 태그 내 class에 접근해 태그 내에 데이터 삽입

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
    // input 태그의 button을 통해 JS 메서드 실행
    function addImage() {
        // HTML 태그 내 class에 접근, <div></div> 사이에 이미지 데이터 삽입
        $(".class1").html("<img src='../image/duke.png'>");
        // 화면에 삽입한 이미지를 띄우기 전 경고창 송출
        alert($(".class1").html());
    }
</script>

<div class="class1"></div>
<input type="button" value="이미지 추가하기" onClick="addImage()" />

4) JS 메서드를 통해 HTML 태그, id, class에 접근해 태그 내 데이터 삽입

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript"> 
    // input 태그의 button을 통해 JS 메서드 실행
    function addImage() {
      	// 태그의 class가 없다면 태그 자체로도 jquery를 사용할 수 있다.
        $("div").html("<img src='../image/duke.png'>");
        // <div> 태그 내 id에 접근, <div></div> 사이에 데이터 삽입
        $("#id1").html("<img src='../image/duke2.png
        // <div> 태그 내 class에 접근, <div></div> 사이에 데이터 삽입
        $(".c1").html("<img src='../image/image1.jpg'>");
    }
</script>

<div></div>
<div id="id1"></div>
<div class="c1"></div>
<input type="button" value="이미지 추가하기" onClick="addImage()" />

5) JS 메서드를 통해 입력 값을 저장 후 다른 input 태그의 value로 사용

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
    // input 태그의 button을 통해 JS 메서드 실행
    function fn_process() {
        // id가 t_input인 input 태그에 접근, 입력 값을 value1라는 변수에 저장
        var value1 = $("#t_input").val();
        // id가 t_output인 input 태그에 접근, 해당 태그의 value를 저장한 value1로 설정
        $("#t_output").val(value);
    }
</script>

<input type="text" id="t_input" />
<input type="button" value="입력하기" onClick="fn_process()" />
<div>
    결과:<input type="text" id="t_output" disabled />
</div>

6) 초기 입력한 비밀번호와 두번째로 입력한 비밀번호를 비교

<style type="text/css">
	// HTML 내 silver 라는 class에 접근, 색상 설정
	.silver{ background-color: silver; }
</style>

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
    // 페이지가 로딩될 때 -> $(document).ready(function() {}) 과 동일
    $(function() {
        // type이 password 인 태그에 스타일 추가
        $(':password').addClass('silver');
        
        // id가 txtPassword인 태그에 접근
        $('#txtPassword').keyup(function() {
            // id가 labelError인 태그에 접근, 기존에 있던 text를 '' 로 변환 (클리어 기능)
            $('#lableError').text(''); 
        })
        
        // id가 txtPassWordConfirm 인 태그에 접근
        $('#txtPasswordConfirm').keyup(function() {
            // id가 txtPassword인 태그의 값과 id가 txtPasswordConfirm인 태그의 값이 다르다면
            if ($("#txtPassword").val() != $("#txtPasswordConfirm").val()) {
                // id가 labelError인 태그에 접근, 기존에 있던 text를 '' 로 변환 (클리어 기능)
                $('#lableError').text('');
                // id가 labelError인 태그에 접근, <div></div> 사이에 "<b>암호가 틀립니다.</b>"를 html로 삽입
                $("#labelError").html("<b>암호가 틀립니다.</b>");
            }
            // id가 txtPassword인 태그의 값과 id가 txtPasswordConfirm인 태그의 값이 같다면
            else {
                // id가 labelError인 태그에 접근, 기존에 있던 text를 '' 로 변환 (클리어 기능)
                $('#lableError').text(''); 
                // id가 labelError인 태그에 접근, <div></div> 사이에 "<b>암호가 틀립니다.</b>"를 text로 삽입
                $("#labelError").text("<b>암호가 맞습니다.</b>");
            }
        })
    });
</script>

<table style="border: 1px solid skyblue;">
    <tr>
        <td>암호 : </td>
        <td><input type="password" id="txtPassword" size="20"></td>
    </tr>
    <tr>
        <td>암호확인 : </td>
        <td><input type="password" id="txtPasswordConfirm" size="20"></td>
    </tr>
</table>
<div id="labelError">암호를 입력하시오.</div>

4.  Ajax

1. Ajax ?

Ajax는 Asynchronous JavaScript (비동기 자바스크립트) + XML의 의미로 자바스크립트를 사용한 비동기 통신이다.

즉, 클라이언트 측에서의 작업과는 상관 없이 비동기적으로 서버와 작업을 수행할 때 사용하는 기능이다.

* 장점
1. 페이지 이동 없이 데이터 처리가 가능하며, 서버의 처리를 기다리지 않고 비동기 요청이 가능하다
2. 클라이언트와 서버 간의 XML이나 JSON 데이터를 주고받을 수 있다.
3. 웹 페이지 전체를 다시 로딩하지 않고도, 웹 페이지의 일부분만을 갱신할 수 있다.
4. 웹 페이지가 로드 된 후에 서버로 데이터 요청을 보내거나, 받을 수 있다.

* 단점
1. 클라이언트가 서버에 데이터를 요청하는 클라이언트 풀링 방식을 사용하므로, 서버 푸시 방식의 실시간 서비스는 만들 수 없다.
2. 바이너리 데이터를 보내거나 받을 수 없다.
3. Ajax 스크립트가 포함된 서버가 아닌 다른 서버로 Ajax 요청을 보낼 수는 없다.
4. 클라이언트의 PC로 Ajax 요청을 보낼 수는 없다.

 

2. 기본 구조

$.ajax({
    /* 기본 설정 */
    type: "get or post", // 전송 방식
    async: false or true,  // 싱크 여부
    url: "http://localhost:9000/day5_html_jquery/ajaxTest1", // 전송할 경로
    
    /* 클라이언트(jsp) -> 서버(servlet)으로 데이터 전송 설정 */
    dataType: "text", // 전송 데이터 타입
    data: { param:"Hello, jquery" }, // 전송 데이터

    /* 서버 -> 클라이언트로 전송한 데이터 처리 */
    success: { // 성공했을 때 해야할 일들
    },
    error: function(arg1, arg2) { // 오류가 발생했을 때 해야할 일들, 반드시 function
    	alert("에러가 발생했습니다.");
    },
    complete: function(arg1, arg2) { // 작업 완료가 되었을 때 해야할 일들, 반드시 function
    	alert("작업을 완료 했습니다.");
    }
});

5.  Ajax 실습_1) 서버 & 클라이언트 간 데이터 전송

1. ajax1.html

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
    // type이 button인 input 태그의 이벤트가 발생한다면
    function fn_process() {
        $.ajax({
            /* 기본설정 */
            type: "get", // 전송 방식 : get
            async: false, // 동기식으로 설정 : 서버의 응답을 기다렸다가 다음 로직을 실행
            url: "http://localhost:9000/day5_html_jquery/ajaxTest1", // 전송 경로
            
            /* 클라이언트 -> 서버로 데이터 전송 */
            dataType: "text", // 전송 데이터 타입
            data: {param:"Hello, jquery"}, // 서버로 전송할 데이터
            
            /* 서버 -> 클라이언트로 전송한 데이터 처리 */
            success: function(data, textStatus) { // 서버에서 넘어온 데이터를 data에 저장
            	$('#message').append(data); // 태그의 id가 message인 태그를 찾아, data를 추가
            },
            error: function(data, textStatus) {
            	alert("에러가 발생했습니다.");
            },
            complete: function(data, textStatus) {
            	alert("작업을 완료 했습니다.");
            }
        });	
    }		
</script>

<input type="button" value="전송하기" onClick="fn_process()" />
<div id="message"></div>

 

2. AjaxTest1 Servlet

해당 서블릿의 동작 구조는 다음과 같다.

 

1) Ajax를 통해 JSP에서 넘어온 데이터(param)를 request 객체를 통해 저장, 출력한다.

2) PrintWriter의 writer.print() 를 사용해 JSP로 "안녕하세요! 서버입니다." 문자열을 전송한다.

private void doHandler(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("utf-8");
    response.setContentType("text/html; charset=utf-8");
    String param = (String)request.getParameter("param");
    System.out.println("param = " + param);
    PrintWriter writer = response.getWriter();
    writer.print("안녕하세요! 서버입니다.");
}

6.  Ajax 실습_2) 아이디 중복 체크

1. ajax3.html

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
    function fn_process() {
        var _id=$("#t_id").val(); // id가 t_id인 태그에 접근해 value를 _id에 저장

        if(_id == '') { // 만약 _id가 공백이라면 (id를 입력하지 않고 버튼을 누를 시)
            alert("ID를 입력하세요"); // 경고창 출력
            return;
        }  
        $.ajax({
            /* 기본 설정 */
            type: "post", // 전송방식 : post
            async: true, // 비동기식으로 설정 : 서버의 응답을 기다리지 않고 다음 로직을 실행
            url: "http://localhost:9000/day5_html_jquery/mem",

            /* 클라이언트 -> 서버로 데이터 전송 */
            dataType: "text",
            data: {id : _id},

            /* 서버 -> 클라이언트로 전송한 데이터 처리 */
            success:function (data,textStatus) {
                alert(data); // 서버에서 넘어온 데이터 확인

		// data가 usable 이라면
                if(data=='usable') { 
                    $('#message').text("사용할 수 있는 ID입니다."); // id가 message인 태그에 접근해, text를 입력
                    $('#btnDuplicate').prop("disabled", true); // id가 btnDuplicate인 태그에 접근해, property 추가
                }
                else{
                    $('#message').text("사용할 수 없는 ID입니다.");
                }
            },
            error:function(data,textStatus){
            	alert("에러가 발생했습니다.");
            },
            complete:function(data,textStatus){
            	alert("작업을 완료 했습니다.");
            }
        }); 
    }		
</script>

<input type="text" id="t_id" />
<input type="button" id="btnDuplicate" value="ID 중복체크하기" onClick="fn_process()" />
<div id="message"></div>

 

2. MemberServlet

해당 서블릿의 동작 구조는 다음과 같다.

 

1) Ajax를 통해 JSP에서 넘어온 데이터(id)를 request 객체를 통해 저장, 출력한다.

2) MemberDAO의 overlappedID()를 통해, 넘어온 id와 DB 내 id를 대조한다.

3) 대조 결과 해당 id가 사용 가능하다면 JSP로 "not_usable"을, 불가능하다면 "usable"을 전송한다.

private void doHandler(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("utf-8");
    response.setContentType("text/html; charset=utf-8");
    PrintWriter writer = response.getWriter();

    String id = (String) request.getParameter("id");
    System.out.println("id = " + id);
    MemberDAO memberDAO = new MemberDAO();
    boolean overlappedID = memberDAO.overlappedID(id);

    if (overlappedID == true) {
        writer.print("not_usable");
    } else {
        writer.print("usable");
    }
}

7.  JSON (JavaScript Object Notation)

1. JSON ?

JSON은 사람이 읽을 수 있는 텍스트를 사용해 데이터를 저장, 전송하기 위한 자바스크립트 객체이다. 

JSON은 자바스크립트에서 파생되긴 하지만 독립적인 데이터 형식이고, 서로 다른 언어끼리 데이터를 주고받을 경우 사용 가능하다. 또한, 형식이 덜 필요하기 때문에 XML을 대체해 사용할 수 있다.

1. 자바스크립트에서 JSON 객체 생성
- var 변수명 = { key : value }
2. 자바에서 JSON 객체 생성
- JSONObject json = new JSONObject();
3. 자바에서 다수의 JSON 객체 동시 저장
- JSONArray jsonArr = new JSONArray();
4. 자바에서 JSON 객체를 Javascript 으로 전달
- JSONObject.toJSONString();

 

2. JSON 실습

다수의 JSON 데이터를 ajax를 통해 받아 화면에 출력하는 실습을 진행하였다.

 

1) json7.jsp

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
    // 페이지가 로딩 될 때
    $(function() {
        $("#checkJson").click( // id가 checkJson인 태그를 찾아, click 시 동작 부여
            function() {
                $.ajax({
                /* 기본 설정 */
                type : "post", // 전송 타입 : post
                async : false, // 동기식으로 설정 : 서버의 응답을 기다렸다가 다음 로직을 실행
                url : "${contextPath}/json3", // 전송 경로

                /* 서버 -> 클라이언트로 전송 된 데이터 처리 */
                success : function(data, textStatus) { 
                    var jsonInfo = JSON.parse(data); // 넘어온 데이터를 JSON 형태로 파싱해 저장
                    var memberInfo = "회원 정보<br>"; // 태그 내에 추가할 데이터 선언
                    memberInfo += "=======<br>";
                    
                    // for문을 통해 key값이 members인 JSON 객체의 데이터 추출
                    for (var i in jsonInfo.members) { 
                        memberInfo += "이름: " + jsonInfo.members[i].name + "<br>";
                        memberInfo += "나이: " + jsonInfo.members[i].age + "<br>";
                        memberInfo += "성별: " + jsonInfo.members[i].gender + "<br>";
                        memberInfo += "별명: " + jsonInfo.members[i].nickname + "<br><br><br>";
                    }

                    var booksInfo = "<br><br><br>도서 정보<br>";
                    booksInfo += "===========<br>";
                    
                    // for문을 통해 key값이 books인 JSON 객체의 데이터 추출
                    for (var i in jsonInfo.books) { 
                        booksInfo += "제목: " + jsonInfo.books[i].title + "<br>";
                        booksInfo += "저자: " + jsonInfo.books[i].writer + "<br>";
                        booksInfo += "가격: " + jsonInfo.books[i].price + "원 <br>";
                        booksInfo += "장르: " + jsonInfo.books[i].genre + "<br>";
                        imageURL = jsonInfo.books[i].image;
                        booksInfo += "<img src=" + imageURL+ "/>" + "<br><br><br>";
                	}
                // id가 output인 태그에 저장한 memberInfo, booksInfo를 <div></div> 내에 추가
                $("#output").html(memberInfo + "<br>" + booksInfo);
                },
                error : function(data, textStatus) {
                	alert("에러가 발생했습니다.");
                }
            }); 
        });
    });
</script>

<a id="checkJson" style="cursor: pointer">데이터 수신하기</a>
<div id="output"></div>

 

2) JsonServlet3

해당 서블릿의 동작 구조는 다음과 같다.

 

1) PrintWriter writer = response.getWriter()

JSP에 데이터를 전송하기 위한 PrintWriter 객체를 생성한다.

2) JSONObject memberInfo = new JSONObject() & JSONObject bookInfo = new JSONObject()

JSON 데이터를 저장하기 위한 JSONObject 객체를 생성한다. (memberInfo, bookInfo)

3) JSONArray membersArray = new JSONArray() & JSONArray bookArray = new JSONArray()

여러 JSON 데이터를 저장하기 위한 JSONArray 객체를 생성한다. 

4) JSONObject totalObject = new JSONObject()

JSONArray를 다시 JSONObject에 담기위한 객체를 생성한다.

왜냐하면 서버에서 클라이언트로 데이터를 전송하기 위해서는 toJSONString()를 실행해야하는데, 이 메서드는 JSONObject에만 존재하고 JSONArray에는 존재하지 않기 때문이다.

5) membersArray.add(memberInfo) & bookArray.add(bookInfo)

JSONObject에 담은 데이터를 JSONArray 객체에 저장한다.

6) totaObject.put("members", membersArray) & totaObject.put("books", bookArray)

최종적으로 toJSONString() 을 실행하기 위한 객체에 두 JSONArray를 key, value 형식으로 집어 넣는다.

7) String jsonInfo = totaObject.toJSONString()

JSP로 넘겨주기 위해 JSON 객체를 String으로 변환한다.

8) writer.print(jsonInfo)

JSP로 저장한 데이터를 넘겨준다.

private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html; charset=utf-8");
        PrintWriter writer = response.getWriter();

        JSONObject memberInfo = new JSONObject();
        JSONArray membersArray = new JSONArray();
        JSONObject totaObject = new JSONObject();
        memberInfo.put("name", "박지성");
        memberInfo.put("age", "25");
        memberInfo.put("gender", "남자");
        memberInfo.put("nickname", "날센돌이");
        membersArray.add(memberInfo);

        memberInfo = new JSONObject();
        memberInfo.put("name", "김연아");
        memberInfo.put("age", "21");
        memberInfo.put("gender", "여자");
        memberInfo.put("nickname", "칼치");
        membersArray.add(memberInfo);
        totaObject.put("members", membersArray);

        JSONArray bookArray = new JSONArray();
        JSONObject bookInfo = new JSONObject();
        bookInfo.put("title", "초보자를 위한 자바 프로그래밍");
        bookInfo.put("writer", "이병승");
        bookInfo.put("price", "30000");
        bookInfo.put("genre", "IT");
        bookInfo.put("image", "http://localhost:9000/day5_html_jquery/image/image1.jpg");
        bookArray.add(bookInfo);

        bookInfo = new JSONObject();
        bookInfo.put("title", "모두의 파이썬");
        bookInfo.put("writer", "이승찬");
        bookInfo.put("price", "12000");
        bookInfo.put("genre", "IT");
        bookInfo.put("image", "http://localhost:9000/day5_html_jquery/image/image2.jpg");
        bookArray.add(bookInfo);

        totaObject.put("books", bookArray);

        String jsonInfo = totaObject.toJSONString();
        System.out.print(jsonInfo);
        writer.print(jsonInfo);
}

8.  23일차 후기

디테일한 기능인 파일 업/다운로드와 JSON 형식의 데이터를 클라이언트-서버 간 주고 받기 위한 Ajax, Ajax를 사용하기 위한 JQuery 수업을 진행하였다.

 

웹 브라우저는 통일 되어있는 환경이 아니라 어떻게 개발하느냐에 따라 서로 다른 언어를 쓰고, 표현방식 또한 달라진다.

때문에 브라우저 간 통일 된 데이터 양식이 필요했고, JSON 형식의 데이터를 사용하게 되었다.

 

이 JSON 데이터를 주고받을 때 Ajax 통신을 많이 사용한다. 비록 Ajax는 어떤 환경에서 사용하느냐에 따라 양식이 조금씩 달라지긴 하지만, 해당 개념은 반드시 알아둬야 프론트와 백엔드 간 통신을 원활히 진행할 수 있다.

 

파일 업/다운로드 또한 어떤 라이브러리를 가져다 사용함에 따라 조금씩 다른 방식을 띈다. 하지만 "\\" 또는 "/" 의 index를 찾고, 파일명을 추출하는 부분은 어떤 라이브러리를 사용하던 공통 된 부분이기 때문에 꼭 알아둘 필요가 있다.