Study Web Development

1월 13일

이전으로

jQuery

6. Ajax(Asynchronous JavaScript and XML)

6-2 jQuery Ajax 메서드

JSON
  1. 새 폴더 ch13-ajax 생성하고 table.sql 생성
CREATE TABLE people(
	id VARCHAR2(10) PRIMARY KEY,
	name VARCHAR2(30) NOT NULL,
	job VARCHAR2(30) NOT NULL,
	address VARCHAR2(60) NOT NULL,
	blood_type VARCHAR2(2) NOT NULL
);

INSERT INTO people VALUES ('test', '실험', '학생', '서울시', 'A'); -- 중복 체크용 초기 데이터
COMMIT;
  1. ch11-jdbc 폴더에서 dbinfo.jspf 복사하여 ch13-ajax 폴더에 붙여넣기하고, 첫 행의 contentType 속성 값을 text/plain으로 변경
  2. 새 JSP 파일 confirmId.jsp 생성
<%@ page language="java" contentType="text/plain; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.ResultSet" %>
<%@ page import="java.sql.SQLException" %>
<%@ include file="dbinfo.jspf" %> <%-- include된 파일과 contentType이 불일치하면 에러 --%>
<%
	// 전송된 데이터 인코딩 처리
	request.setCharacterEncoding("UTF-8");

	// 전송된 데이터 반환
	String id = request.getParameter("id");
	
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	String sql = null;

	try {
		// JDBC 수행 1단계 : 드라이버 로드
		Class.forName(driverName);
		// JDBC 수행 2단계 : Connection 객체 생성
		conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);
		
		// SQL문 작성
		sql = "SELECT id FROM people WHERE id=?";
		
		// JDBC 수행 3단계 : PreparedStatement 객체 생성
		pstmt = conn.prepareStatement(sql);
		// ?에 데이터를 바인딩
		pstmt.setString(1, id);

		// JDBC 수행 4단계 : SQL문을 실행해서 결과 행을 Resultset에 담아 반환
		rs = pstmt.executeQuery();
		
		if(rs.next()) { // ID 중복
%>
{"result":"idDuplicated"} <%-- JSON 데이터 --%>
<%
		}
		else { // ID 중복되지 않음
%>
{"result":"idNotFound"} <%-- JSON 데이터 --%>
<%
		}
	}
	catch(Exception e) {
		e.printStackTrace();
%>
{"result":"failure"} <%-- JSON 데이터 --%>
<%
	}
	finally {
		// 자원 정리
		if(rs!=null) try {rs.close();} catch(SQLException e) {}
		if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
		if(conn!=null) try {conn.close();} catch(SQLException e) {}
	}
%>
  1. 새 HTML 파일 main.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>아이디 중복 체크</title>
<style type="text/css">
	ul {
		padding: 0;
		margin: 0;
		list-style: none;
	}
	ul li {
		padding: 0;
		margin: 0 0 10px 0;
	}
	label {
		width: 100px;
		float: left;
	}
</style>
<script type="text/javascript" src="../js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
	$(function() {
		// 아이디 중복 체크 결과
		var count = 0; // 0: 아이디 중복 체크하지 않았거나 중복, 1: 아이디 중복되지 않음
		
		$('#confirmId').click(function() {
			if($('#id').val().trim()=='') {
				alert('아이디를 입력하세요!');
				$('#id').focus();
				$('#id').val(''); // 공백 제거
				return; // 함수를 빠져나감
			} // end of if
			
			// 서버 프로그램과 통신
			$.ajax({
				url:'confirmId.jsp', // 요청 URL
				type:'post', // 클라이언트의 데이터 전송 방식
				data:{id:$('#id').val()}, // 서버로 전송할 데이터
				dataType:'json', // 서버로부터 전송받는 데이터의 타입
				cache:false, // 캐시를 사용하지 않음
				timeout:30000, // 전송 또는 서버 상황이 좋지 않아 응답이 지연되는 경우, 실패로 간주하는 대기 시간; 밀리초 단위이며 정상적인 경우 통신에 1-2초 정도 소요
				success:function(param) { // JSON 데이터를 정상적으로 전송받았을 때; catch 블럭의 {"result":"failure"}도 success에 해당
					if(param.result=='idDuplicated') {
						count = 0;
						$('#id_signed').text('이미 등록된 아이디').css('color', 'red');
						$('#id').val('').focus();
					}
					else if(param.result=='idNotFound') {
						count = 1;
						$('#id_signed').text('사용 가능한 아이디').css('color', 'black');
					}
					else {
						count = 0;
						alert('아이디 중복 체크시 오류 발생!')
					}
				},
				error:function() { // JSON 데이터가 아닌 에러 페이지 등을 전송받았을 때
					count = 0;
					alert('네트워크 오류 발생!');
				}
			}); // end of ajax
		}); // end of click
		
		$('#insert_form #id').keyup(function() {
			$('#id_signed').text('');
			count = 0;
		}); // end of keyup
		
		$('#insert_form').submit(function() {
			if($('#id').val().trim()=='') {
				alert('아이디를 입력하세요!');
				$('#id').val('').focus();
				return false;
			}
			
			if(count==0) {
				alert('아이디 중복 체크는 필수입니다!');
				$('#confirmId').focus();
				return false;
			}
			else {
				alert('아이디가 중복되지 않습니다.');
				return false;
			}
		}); // end of submit
	});
</script>
</head>
<body>
<div>
	<form id="insert_form" method="post"> <!-- action을 지정하지 않으면 자기 자신을 호출 -->
		<fieldset>
			<legend>회원 가입</legend>
			<ul>
				<li>
					<label for="id">아이디</label>
					<input type="text" name="id" id="id">
					<input type="button" id="confirmId" value="중복 체크">
					<span id="id_signed"></span> <!-- 중복 체크 결과를 표시하기 위한 빈 태그 -->
				</li>
				<li>
					<input type="submit" value="전송">
				</li>
			</ul>
		</fieldset>
	</form>
</div>
</body>
</html>
  1. 새 폴더 ch14-ajax 생성하고 새 JSP 파일 insertPerson.jsp 생성
<%@ page language="java" contentType="text/plain; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.SQLException" %>
<%@ include file="/ch13-ajax/dbinfo.jspf" %> <%-- 첫 /는 컨텍스트 루트를 의미 --%>
<%
	// 전송된 데이터 인코딩 처리
	request.setCharacterEncoding("UTF-8");

	// 전송된 데이터 반환
	String id = request.getParameter("id");
	String name = request.getParameter("name");
	String job = request.getParameter("job");
	String address = request.getParameter("address");
	String blood_type = request.getParameter("blood_type");
	
	Connection conn = null;
	PreparedStatement pstmt = null;
	String sql = null;
	
	try {
		// JDBC 수행 1단계 : 드라이버 로드
		Class.forName(driverName);
		// JDBC 수행 2단계 : Connection 객체 생성
		conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);

		// SQL문 작성
		sql = "INSERT INTO people (id, name, job, address, blood_type) "
			+ "VALUES (?, ?, ?, ?, ?)";

		// JDBC 수행 3단계 : PreparedStatement 객체 생성
		pstmt = conn.prepareStatement(sql);
		// ?에 데이터를 바인딩
		pstmt.setString(1, id);
		pstmt.setString(2, name);
		pstmt.setString(3, job);
		pstmt.setString(4, address);
		pstmt.setString(5, blood_type);
		
		// JDBC 수행 4단계 : SQL문 실행
		pstmt.executeUpdate();
%>
	{"result":"success"}
<%
	}
	catch(Exception e) {
		e.printStackTrace();
%>
	{"result":"failure"}
<%
	}
	finally {
		// 자원 정리
		if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
		if(conn!=null) try {conn.close();} catch(SQLException e) {}
	}
%>
  1. 새 HTML 파일 main.html 생성
    • 개발자 도구의 네트워크 탭에서 .jsp를 클릭하면 JavaScript와 서버가 주고받은 요청 및 응답의 헤더나 서버에서 응답한 JSON 데이터 등을 확인 가능
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 정보</title>
<style type="text/css">
	form {
		width: 500px;
		margin: 10px auto;
	}
	ul {
		padding: 0;
		margin: 0;
		list-style: none;
	}
	ul li {
		padding: 0;
		margin: 0 0 10px 0;
	}
	label {
		width: 150px;
		float: left;
	}
	table {
		border: solid 1px gray;
		width: 500px;
		margin: 0 auto;
		border-collapse: collapse;
	}
	td {
		border: solid 1px gray;
	}
</style>
<script type="text/javascript" src="../js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
	$(function() {		
		// 목록
		function selectData() {
			// <table> 내부 내용 제거(초기화)
			$('#output').empty();
			
			// 서버에 데이터 요청
			$.ajax({
				url:'getPeopleJSON.jsp',
				dataType:'json',
				cache:false,
				timeout:30000,
				success:function(param) {
					$(param).each(function(index, item) { // 배열로 처리
						var output = '';
						output += '<tr>';
						output += '<td>' + item.id + '</td>';
						output += '<td>' + item.name + '</td>';
						output += '<td>' + item.job + '</td>';
						output += '<td>' + item.address + '</td>';
						output += '<td>' + item.blood_type + '</td>';
						output += '</tr>';
						
						// 테이블에 생성한 태그를 추가
						$('#output').append(output);
					}); // end of each
				},
				error:function() {
					alert('네트워크 오류 발생!');
				}
			}) // end of ajax
		} // end of selectData
		
		// 이벤트 연결
		$('#insert_form').submit(function name(event) {
			// 입력 양식의 내용을 요청 매개 변수 문자열로 만듦; GET 방식처럼 파라미터명과 값의 쌍을 연결하고 인코딩 처리
			var input_data = $(this).serialize();
			
			// 서버에 데이터 전송
			$.ajax({
				url:'insertPerson.jsp',
				type:'post',
				data:input_data,
				dataType:'json', // 서버로부터 받을 데이터의 형식
				cache:false,
				timeout:30000, // 응답이 30초 이상 지연되면 에러 처리
				success:function(param) {
					if(param.result=='success') {
						alert('회원 가입 성공');
						// 초기화
						$('#insert_form input[type="text"]').val('');
						
						// 목록 호출
						selectData();
					}
					else {
						alert('회원 가입시 오류 발생!');
					}
				},
				error:function() { // (에러 페이지 등) 형식에 맞지 않는 데이터를 받은 경우
					alert('네트워크 오류 발생!');
				}
			}); // end of ajax
			
			// 기본 이벤트 제거
			event.preventDefault();
		}); // end of submit
		
		// 초기 화면에 데이터를 표시
		selectData();
	});
</script>
</head>
<body>
<div>
	<form id="insert_form" method="post">
		<fieldset>
			<legend>회원 가입</legend>
			<ul>
				<li>
					<label for="id">아이디</label>
					<input type="text" name="id" id="id">
				</li>
				<li>
					<label for="name">이름</label>
					<input type="text" name="name" id="name">
				</li>
				<li>
					<label for="job">직업</label>
					<input type="text" name="job" id="job">
				</li>
				<li>
					<label for="address">주소</label>
					<input type="text" name="address" id="address">
				</li>
				<li>
					<label for="blood_type">혈액형</label>
					<input type="text" name="blood_type" id="blood_type">
				</li>
			</ul>
			<div align="center">
				<input type="submit" value="추가">
			</div>
		</fieldset>
	</form>
</div>
<table id="output"></table>
</body>
</html>
  1. 새 JSP 파일 getPeopleJSON.jsp 생성
<%@ page language="java" contentType="text/plain; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.ResultSet" %>
<%@ page import="java.sql.SQLException" %>
<%@ include file="/ch13-ajax/dbinfo.jspf" %>
<%-- 배열 안에 스크립트릿 사용 --%>
[<% 
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	String sql= null;

	try {
		// JDBC 수행 1단계 : 드라이버 로드
		Class.forName(driverName);
		// JDBC 수행 2단계 : Connection 객체 생성
		conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);

		// SQL문 작성
		sql = "SELECT * FROM people ORDER BY id DESC";
		
		// JDBC 수행 3단계 : PreparedStatement 객체 생성
		pstmt = conn.prepareStatement(sql);
		
		// JDBC 수행 4단계
		rs = pstmt.executeQuery();
		while(rs.next()) {
			String id = rs.getString("id"); 
			String name = rs.getString("name"); 
			String job = rs.getString("job"); 
			String address = rs.getString("address"); 
			String blood_type = rs.getString("blood_type");
			
			if(rs.getRow()>1) { // 첫 번째 행을 제외하고
				out.print(","); // 쉼표 삽입
			}
%>
			{
				"id":"<%= id %>",
				"name":"<%= name %>",
				"job":"<%= job %>",
				"address":"<%= address %>",
				"blood_type":"<%= blood_type %>"
			}
<%			
		} // end of while
	} // end of try
	catch(Exception e) { // 예외 발생시 형식에 맞지 않는 데이터(에러 페이지)가 전송되도록 별도의 JSON 데이터를 만들지 않음
		e.printStackTrace();
	}
	finally {
		// 자원 정리
		if(rs!=null) try {rs.close();} catch(SQLException e) {}
		if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
		if(conn!=null) try {conn.close();} catch(SQLException e) {}
	}
%>]
XML
  1. 새 폴더 ch15-ajax 생성하고 ch11-jdbc 폴더에서 table.sql을 복사하여 ch15-ajax 폴더에 붙여넣기
  2. ch13-ajax 폴더에서 dbinfo.jspf를 복사하여 ch15-ajax 폴더에 붙여넣기하고, 첫 행의 contentType 속성 값을 text/xml으로 변경
  3. 새 JSP 파일 getProductList.jsp 생성
<%@ page language="java" contentType="text/xml; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.PreparedStatement" %>
<%@ page import="java.sql.ResultSet" %>
<%@ page import="java.sql.SQLException" %>
<%@ include file="dbinfo.jspf" %>
<?xml version="1.0" encoding="UTF-8"?>
<product>
<%
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	String sql = null;
	
	try {
		// JDBC 수행 1단계 : 드라이버 로드
		Class.forName(driverName);
		// JDBC 수행 2단계 : Connection 객체 생성
		conn = DriverManager.getConnection(jdbcUrl, dbId, dbPass);
		
		// SQL문 작성
		sql = "SELECT * FROM product ORDER BY num DESC";
		
		// JDBC 수행 3단계 : PreparedStatement 객체 생성
		pstmt = conn.prepareStatement(sql);
		
		// JDBC 수행 4단계 : SQL문을 실행하고 결과 행들을 ResultSet에 담아 반환
		rs = pstmt.executeQuery();
		while(rs.next()) {
%>
	<item>
		<num><%= rs.getInt("num") %></num>
		<name><%= rs.getString("name") %></name>
		<price><%= rs.getInt("price") %></price>
		<stock><%= rs.getInt("stock") %></stock>
		<origin><%= rs.getString("origin") %></origin>
		<reg_date><%= rs.getDate("reg_date") %></reg_date>
	</item>
<%
		}
	}
	catch(Exception e) {
		e.printStackTrace();
	}
	finally {
		// 자원 정리
		if(rs!=null) try {rs.close();} catch(SQLException e) {}
		if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
		if(conn!=null) try {conn.close();} catch(SQLException e) {}
	}
%>
</product>
  1. 새 HTML 파일 main.html 생성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>XML 데이터 처리</title>
<style type="text/css">
	* {
		margin: 0;
		padding: 0;
	}
	#wrap {
		overflow: hidden;
	}
	.item {
		margin: 5px;
		padding: 5px;
		width: 200px;
		height: 150px;
		float: left; /* 반응형처럼 동작함 */
		border-width: 3px;
		border-style: solid;
		border-color: gray;
		border-radius: 10px;
	}
</style>
<script type="text/javascript" src="../js/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
	$(function() {
		function selectData() {			
			$.ajax({
				url:'getProductList.jsp',
				dataType:'xml',
				success:function(param) {
					// 화면 초기화
					$('#wrap').empty();
					$(param).find('item').each(function() {
						var output = '<div class="item">';
						output += '<p>상품 번호 : ' + $(this).find('num').text() + '</p>';
						output += '<p>상품명 : ' + $(this).find('name').text() + '</p>';
						output += '<p>가격 : ' + $(this).find('price').text() + '</p>';
						output += '<p>재고 : ' + $(this).find('stock').text() + '</p>';
						output += '<p>원산지 : ' + $(this).find('origin').text() + '</p>';
						output += '<p>등록일 : ' + $(this).find('reg_date').text() + '</p>';
						output += '</div>';
						
						// 문서 객체 추가
						$('#wrap').append(output);
					}); // end of each
				},
				error:function() {
					alert('네트워크 오류 발생!');
				}
			}); // end of ajax
		} // end of selectData
		
		// 초기 화면 데이터 처리
		selectData();
	});
</script>
</head>
<body>
	<div id="wrap"></div>
</body>
</html>

다음으로