Programming/JDBC

[JDBC] Ajax: 응답 데이터 형식 (Text, XML, JSON)

Isaac S. Lee 2023. 10. 25. 16:14
 

[JDBC] Ajax (Asynchronous JavaScript and XML)

🍁Ajax Ajax는 비동기 방식으로 자바스크립트를 사용해서 서버와 데이터를 통신하는 기술을 의미하며, XML 형식으로 데이터를 주고받는다. 화면 깜박임 없이 데이터를 주고받을 수 있는 기술이다.

isaac-christian.tistory.com

Ajax에 대해서는 위 글을 참고한다.

타입에 따라서 돌려받을 데이터 형식(Text, XML, JSON)을 결정하여 각각의 작업 과정을 확인해 보도록 하자.

 

🍁Text


단일 데이터

Ex04.java

package com.test.ajax.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/ex04.do")
public class Ex04 extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		RequestDispatcher dispatcher = req.getRequestDispatcher("/WEB-INF/views/ex04.jsp");
		dispatcher.forward(req, resp);
	}

}

 

Ex04Data.java

private void m1(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

	// 텍스트 반환(단일값)
	AjaxDAO dao = new AjaxDAO();
	int count = dao.getMemoCount();

	resp.setContentType("text/plain"); // MIME 타입
	resp.setCharacterEncoding("UTF-8");

	PrintWriter writer = resp.getWriter();
	writer.print(count);
	writer.close();

}

 

ex04.jsp

$('#btn1').click(function(){
    $.ajax({
        type: 'GET',
        url: '/ajax/ex04data.do',
        data: 'type=1',
        dataType: 'text', //돌려받을 데이터 형식

        success: function(result) {
            $('#result1').text(result);
        },
        error: function(a,b,c) {
            console.log(a,b,c);
        }
    });
});

 

MIME 타입

resp.setContentType("text/plain");

MIME 타입은 돌려받는 브라우저 또는 ajax 객체에게 돌려받는 데이터가 이런 형식이 데이터라는 것을 알려주는 표시이다. 그래서 위 코드순수 텍스트 데이터라는 것을 알려주는 것을 의미한다.

 

한글 깨짐 방지

resp.setCharacterEncoding("UTF-8");

UTF-8로 한글이 출력될 수 있도록 한다.

 

다중 데이터

AjaxDAO.java

public ArrayList<MemoDTO> listMemo() {
	
	try {
		
		String sql = "select * from tblMemo";
		stat = conn.createStatement();
		rs = stat.executeQuery(sql);
		
		ArrayList<MemoDTO> list = new ArrayList<MemoDTO>();
		
		//ResultSet > 복사 > ArrayList(MemoDTO)
		while (rs.next()) {
			
			MemoDTO dto = new MemoDTO();
			dto.setSeq(rs.getString("seq"));
			dto.setSeq(rs.getString("name"));
			dto.setSeq(rs.getString("pw"));
			dto.setSeq(rs.getString("memo"));
			dto.setSeq(rs.getString("regdate"));
			
			list.add(dto);
		}
		
		return list;
		
	} catch (Exception e) {
		System.out.println("AjaxDAO.listMemo()");
		e.printStackTrace();
	}
	
	return null;
}

 

Ex04Data.java

private void m2(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    AjaxDAO dao = new AjaxDAO();
    ArrayList<MemoDTO> list = dao.listMemo();

    // CSV
    StringBuilder csv = new StringBuilder();
    for (MemoDTO dto : list) {
        csv.append(String.format("%s,%s,%s,%s,%s\r\n", dto.getSeq(), dto.getName(), dto.getPw(),
                dto.getMemo().replace("\r\n", "\n"), dto.getRegdate()));
    }

    resp.setContentType("text/plain");
    resp.setCharacterEncoding("UTF-8");

    PrintWriter writer = resp.getWriter();
    writer.print(csv.toString());
    writer.close();
}

 

ex04.jsp

$('#btn1').click(function(){
    $.ajax({
        type: 'GET',
        url: '/ajax/ex04data.do',
        //data: 'type=1',
        data: 'type=2',
        dataType: 'text', //돌려받을 데이터 형식(text, xml, json)

        success: function(result) {
            //$('#result1').text(result);

            const list = result.split('\r\n');

            list.forEach(memo => {
                //alert(memo);

                const item = memo.split(',');

                $('#result1').append('<div>' + item[0] + '</div>');
                $('#result1').append('<div>' + item[1] + '</div>');
                $('#result1').append('<div>' + item[2] + '</div>');
                $('#result1').append('<br>);
            });
        },
        error: function(a,b,c) {
            console.log(a,b,c);
        }
    });
});

다량의 텍스트를 순수 텍스트로 표현하는 가장 무난한 방법은 CSV이다.

하지만 다량의 값은 XML이나 JSON으로 처리하는 게 더 좋기 때문에 위 방법은 잘 사용하지 않는다.

 

🍁XML (Extensible Markup Language)


다중 데이터 1

Ex04.java

package com.test.ajax.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/ex04.do")
public class Ex04 extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		// Ex04.java

		RequestDispatcher dispatcher = req.getRequestDispatcher("/WEB-INF/views/ex04.jsp");
		dispatcher.forward(req, resp);
	}

}

 

Ex04Data.java

$('#btn2').click(function() {
    $.ajax({
        type: 'GET',
        url: '/ajax/ex04data.do',
        data: 'type=3',
        dataType: 'xml',
        success: function(result) {
            $('#result2').append('<div>번호: ' + $(result).find('seq').text() + '</div>');
            $('#result2').append('<div>이름: ' + $(result).find('name').text() + '</div>');
            $('#result2').append('<div>암호: ' + $(result).find('pw').text() + '</div>');
            $('#result2').append('<div>메모: ' + $(result).find('memo').text() + '</div>');
            $('#result2').append('<div>날짜: ' + $(result).find('regdate').text() + '</div>');
        },
        error: function(a, b, c) {
            console.log(a, b, c);
        }
    });
});

 

ex04.jsp

private void m3(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    AjaxDAO dao = new AjaxDAO();

    MemoDTO dto = dao.get(1);

    // MemoDTO > (XML 형식) > ajax

    // resp.setContentType("text/html");
    // resp.setContentType("application/zip");
    // resp.setContentType("text/plane");
    resp.setCharacterEncoding("UTF-8");
    resp.setContentType("text/xml");

    PrintWriter writer = resp.getWriter();

    writer.print("<?xml version='1.0' encoding='UTF-8'?>");
    writer.print("<memo>");
    writer.printf("<seq>%s</seq>", dto.getSeq());
    writer.printf("<name>%s</name>", dto.getName());
    writer.printf("<pw>%s</pw>", dto.getPw());
    writer.printf("<memo>%s</memo>", dto.getMemo());
    writer.printf("<regdate>%s</regdate>", dto.getRegdate());
    writer.print("</memo>");

    writer.close();
}

이는 서블릿이 HTML 문서를 만드는 것과 같은 상황이다.

대신 서블릿이 아니라 XML로 xml은 컬럼 이름으로 태그를 만들어 HTML문서를 만든다.

 

find 메서드

$(result).find('name').text());

xml을 jQuery로 감싸면 find 메서드를 사용할 수 있다.

xml과 javaScript는 같은 형제이기 때문에 태그를 검색할 수 있다.

 

다중 데이터 2

XML로 여러 개의 메모(MemoDTO x 3개)를 반환하도록 해보자.

 

Ex04Data.java

resp.setContentType("text/xml");

브라우저는 ContentType으로 데이터를 믿기 때문에 XML이라는 것을 알려 주어야한다.

 

PrintWriter writer = resp.getWriter();

XML을 동적으로 만드는 작업이기 때문에 Wrtier를 가지고 만든다.

이제 list를 XML 형식의 문자열로 출력 작업을 한다.

 

writer.print("<?xml version='1.0' encoding='UTF-8'?>");

먼저 XML 선언문을 만든다. 그리고 아래에 내가 만들고 싶은 태그 작업을 한다.

메모라는 루트 태그를 만들고, 그 안에 집어 넣어야 할 값들을 하위 태그로 만들어서 그 태그에 해시 데이터를 넣어야 하는데, 이번에는 이 작업을 여러 번 해야 한다. for문으로 루프를 돌려서 메모를 하나 출력하는 작업을 여러 번 할 수 있다.

그런데 그냥 실행하면 오류가 발생한다. 모든 마크업 언어(ML)은 최상위 태그가 유일해야 하는데, 루트 Element가 여러 개 이기 때문이다. 그래서 바깥에 루트가 되어 전체를 감싸는 <list> 태그를 만들어 주어야 한다. 이러면 XML로써 문제가 전혀 없다.

Ex04Data.java 전체 코드

private void m4(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    AjaxDAO dao = new AjaxDAO();
    ArrayList<MemoDTO> list = dao.listMemo();

    resp.setContentType("text/xml");
    resp.setCharacterEncoding("UTF-8");

    PrintWriter writer = resp.getWriter();

    writer.print("<?xml version='1.0' encoding='UTF-8'?>");
    writer.println("<list>");

    for (MemoDTO dto: list) {
        writer.println("<memo>");
        writer.printf("<seq>%s</seq>", dto.getSeq());
        writer.printf("<name>%s</name>", dto.getName());
        writer.printf("<pw>%s</pw>", dto.getPw());
        writer.printf("<memo>%s</memo>", dto.getMemo());
        writer.printf("<regdate>%s</regdate>", dto.getRegdate());
        writer.println("</memo>");
    }

    writer.println("</list>");
    writer.close();
}

 

ex04.jsp

$('#btn2').click(function() {
    $.ajax({
        type: 'GET',
        url: '/ajax/ex04data.do',
        //data: 'type=3',
        data: 'type=4',
        dataType: 'xml',
        success: function(result) 
            //alert($(result).html());

            //each 메서드
            $(result).find('list > memo').each((index, item) => {

                $('#result2').append('<div>' + $(item).find('seq').text() + '</div>');
                $('#result2').append('<div>' + $(item).find('name').text() + '</div>');
                $('#result2').append('<div>' + $(item).find('pw').text() + '</div>');
                $('#result2').append('<div>' + $(item).find('memo').text() + '</div>');
                $('#result2').append('<div>' + $(item).find('regdate').text() + '</div>');

            });
        },
        error: function(a, b, c) {
            console.log(a, b, c);
        }
    });
});

문서상에서 리스트의 자식인 메모 태그만 찾는다.

 

each 메서드

$(result).find('list > memo').each((index, item) => {

each 메서드는 forEach()와 동일하다. (향상된 for문)
자바의 forEach(item, index)와 자바스크립트의 each(index, item)은 반대이다.

 

🍁JSON (JavaScript Object Notation)


🍂JSON이란?

JSON은 객체 표기법이다.

JSON을 더 정확히 말하자면 자바스크립트 문법을 빌려 어떤 객체를 표기하는 표현법이다.

 

JSON의 특징

{
	"키": "값",
	"키": "값",
	"키": "값"
}

앞은 프로퍼티, 뒤는 값으로 작성하는 게 자바스크립트의 객체이다. 이를 본따서 만든 게 JSON이다.

자바스크립트가 아닌 곳에서도 사용할 수 있도록 문법을 고쳐 두었는데, 반드시 키와 값을 큰 따옴표("") 안에 묶어야 한다는 점이다.

즉, 키와 값을 문자열로 표기해야 한다. 단, 숫자 값은 ""를 생략할 수 있다.

이때 쌍따옴표만 사용할 수 있으며, 홑따옴표를 사용하는 게 불가능하다는 점에 주의한다.

그리고 hello: function() {} 이런 식으로 메서드 멤버 추가가 불가능하다. 메서드는 값이 아니기 때문에 추가할 수 없는 것이다.

JSON은 오로지 데이터를 저장하는 역할을 한다는 점에서 자바의 DTO와 동일한 역할을 한다.

 

JSON 객체

{
    "seq": "5"
    "name": "Isaac",
    "pw": "1111",
    "memo": "메모입니다.",
    "regdate": "2023-10-26 09:40:00"
}

위와 같은 형식으로 출력될 수 있도록 JSON 객체를 만들어보도록 하자.

 

다중 데이터

Ex04Data.java

AjaxDAO dao = new AjaxDAO();
MemoDTO dto = dao.get(1);

데이터베이스에서 데이터를 가져오고, 미리 만들어 둔 get 메서드로 메모를 하나 출력한다.

이제 메모를 JSON 객체로 만들어서 돌려주도록 하자.

 

resp.setContentType("application/json"); //MIME
resp.setCharacterEncoding("UTF-8");

이 데이터가 JSON이라는 것을 알려 주어야 한다.
그리고 인코딩 타입을 UTF-8로 지정해준다.

 

PrintWriter writer = resp.getWriter();

writer.println("{");
writer.printf("\"seq\":\"%s\",", dto.getSeq());
writer.printf("\"name\":\"%s\",", dto.getName());
writer.printf("\"pw\":\"%s\",", dto.getPw());
writer.printf("\"memo\":\"%s\",", dto.getMemo());
writer.printf("\"regdate\":\"%s\"", dto.getRegdate());
writer.println("}");

writer.close();

JSON은 이스케이프("\") 때문에 문법이 헷갈리므로 천천히 작업하도록 한다.

 

Ex04Data.java 전체 코드

private void m5(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    AjaxDAO dao = new AjaxDAO();
    MemoDTO dto = dao.get(1);

    resp.setContentType("application/json"); //MIME
    resp.setCharacterEncoding("UTF-8");

    PrintWriter writer = resp.getWriter();

    writer.println("{");
    writer.printf("\"seq\":\"%s\",", dto.getSeq());
    writer.printf("\"name\":\"%s\",", dto.getName());
    writer.printf("\"pw\":\"%s\",", dto.getPw());
    writer.printf("\"memo\":\"%s\",", dto.getMemo());
    writer.printf("\"regdate\":\"%s\"", dto.getRegdate());
    writer.println("}");

    writer.close();
}

 

ex04.jsp

$('#btn3').click(function() {

    $.ajax({
        type: 'GET',
        url: '/ajax/ex04data.do',
        data: 'type=5',
        dataType: 'json',
        success: function(result) {

            //alert(result.seq);

            $('#result3').append('<div>' + result.seq + '</div>');
            $('#result3').append('<div>' + result.name + '</div>');
            $('#result3').append('<div>' + result.pw + '</div>');
            $('#result3').append('<div>' + result.memo + '</div>');
            $('#result3').append('<div>' + result.regdate + '</div>');

        },
        error: function(a, b, c) {
            console.log(a, b, c);
        }
    })
});

JSON은 처음부터 자바스크립트의 데이터를 돌려주기 때문에 데이터를 가공할 필요가 없다.

result 자체가 이미 자바스크립트 객체이기 때문에 더 깔끔하게 출력할 수 있다.

 

자바스크립트 배열을 이용하는 방법

자바스크립트 배열

[
    10
    ,
    20
]

배열 [] 안에 데이터를 넣어서 데이터를 반환할 수 있다.

객체와 객체 사이에 콤마를 넣어준다.

 

마지막 데이터에는 ','를 쓰지 않도록 해야 하는데, 향상된 for문이기 때문에 마지막 번째 데이터인지 구분하기 번거롭다.

 

temp = temp.substring(0, temp.length() - 1);

그래서 콤마 제거 처리를 위해 위 구문을 작성한다.

이제 오류가 발생하지 않는다.

 

Ex04Data.java

private void m6(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    AjaxDAO dao = new AjaxDAO();
    ArrayList<MemoDTO> list = dao.listMemo();

    resp.setContentType("application/json"); //MIME
    resp.setCharacterEncoding("UTF-8");

    PrintWriter writer = resp.getWriter();

    String temp = "";

    temp += "[";

    for (MemoDTO dto : list) {
        temp += "{";
        temp += String.format("\"seq\":\"%s\",", dto.getSeq());
        temp += String.format("\"name\":\"%s\",", dto.getName());
        temp += String.format("\"pw\":\"%s\",", dto.getPw());
        temp += String.format("\"memo\":\"%s\",", dto.getMemo().replace("\r\n", "\\r\\n")); //개행 처리
        temp += String.format("\"regdate\":\"%s\"", dto.getRegdate());
        temp += "}";
        temp += ",";
    }

    temp = temp.substring(0, temp.length() - 1); //콤마 처리

    temp += "]";

    writer.print(temp);

    writer.close();
}

개행 처리와 콤마 처리를 마친 모습이다.

 

ex04.jsp

$('#btn3').click(function() {
			
    $.ajax({
        type: 'GET',
        url: '/ajax/ex04data.do',
        //data: 'type=5',
        data: 'type=6',
        dataType: 'json',
        success: function(result) {

            $(result).each((index, memo) => {
                //alert(memo.seq);

                $('#result3').append('<div>' + memo.seq + '</div>');
                $('#result3').append('<div>' + memo.name + '</div>');
                $('#result3').append('<div>' + memo.pw + '</div>');
                $('#result3').append('<div>' + memo.memo + '</div>');
                $('#result3').append('<div>' + memo.regdate + '</div>');
                $('#result3').append('<hr>');

            });

        },
        error: function(a, b, c) {
            console.log(a, b, c);
        }
    })
});