23.05.12 : Ajax 기본

이준영·2023년 5월 12일
0
Javascript
	Ecmascript
    
프로그램 언어 = 자바와 비슷
			let / const
            
            함수
            
            객체
            	기본객체
                BOM
                DOM(처리하는 거 중요)   책 05,06,07 챕터



P. 431 http 통신 (웹 서버와 통신 = 자바의 urlconnection과 비슷)
p. 438 ~ 439 (중요) 서버에서 자료 가져오기

🌕 Ajax(Asynchronous JavaScript and XML)

빠르게 동작하는 동적인 웹 페이지를 만들기 위한 개발 기법의 하나
자바스크립트가 사용하는 기술 (문법 아님)


Jsp -> html(web 1.0 방식)이 아니라 Jsp -> data(web 2.0 방식)로 끝난다.
요청을 보내면 url 변화가 없다.(디자인만 바뀜)


Ajax / Dom 에 따라 바뀔 수 있다.



🌕 자료

자료
	jsp
		csv (, 구분자를 가진 데이터)
        		값,값,값 ...
    	xml
        	
    	json

🌙 csv

csv 예

<%@ page language="java" contentType="text/plain; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>  <--평문으로 보여주기 위해 
    text/plain 사용, 공백 제거로 trimDirectiveWhitespaces = true

HTML5 + CSS3 입문,삼국미디어,유비,30000원
Javascript + JQuery 입문,삼국미디어,관우,32000원
Node.js 프로그래밍,삼국미디어,장비,22000HTML5 프로그래밍,삼국미디어,조자룡,30000원

이렇게 만든 csv는 무슨 데이터인지 구별하기가 힘든 감이 좀 있다.
데이터를 조금 구분짓기 위하여 xml이 나옴



🌙 xml

xml문법 기본
1. 시작은 단 하나여야 한다.
2. 시작하면 종료태그 무조건 있어야 함
3. 띄어쓰기 가능 등..

xml 예

<?xml version="1.0" encoding="utf-8" ?>
<books>
	<book>
	<name>HTML5 + CSS3 입문</name>
	<publisher>삼국미디어</publisher>
	<author>유비</author>
	<price>30000원</price>
	</book>


	<book> 
	<name>Node.js 프로그래밍</name>
	<publisher>삼국미디어</publisher>
	<author>장비</author>
	<price>22000원원</price>
	</book>

	<book> 
	<name>Javascript + JQuery 입문</name>
	<publisher>삼국미디어</publisher>
	<author>관우</author>
	<price>32000원</price>
	</book>
</books>


xml은 에러가 나면 html과 다르게 에러 생김(규칙이 있다)



xml.jsp로 만들기

  1. contentType="text/xml" 로 하고 trimDirectiveWhitespaces = true 하기
<%@ page language="java" contentType="text/xml; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
선언부만 바꿔주면 된다. 다른건 동일

🌙 xml db 연동

테이블 생성

 create table books (
seq int not null primary key auto_increment,
name varchar(100),
publisher varchar(20),
author varchar(10),
price int
);

insert문 이용하여 책 정보 넣기

insert into books values (1, 'HTML5 + CSS3 입문', '삼국미디어', '유비', 30000);
insert into books values (2, 'Javascript + JQuery 입문', '삼국미디어', '관우', 32000);
insert into books values (3, 'Node.js 프로그래밍', '삼국미디어', '장비', 22000);
insert into books values (4, 'HTML5 프로그래밍' , '삼국미디어', '조자룡', 32000);
<%@ page language="java" contentType="text/xml; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true" %>
<%@ page import="javax.naming.Context"  %>
<%@ page import="javax.naming.InitialContext"  %>
<%@ page import="javax.naming.NamingException"  %>

<%@ page import="javax.sql.DataSource" %>

<%@ page import="java.sql.Connection"  %>
<%@ page import="java.sql.PreparedStatement"  %>
<%@ page import="java.sql.ResultSet"  %>
<%@ page import="java.sql.SQLException"  %>
<%
	request.setCharacterEncoding("utf-8");

	
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	
	StringBuilder sbHtml = new StringBuilder();

	try { 
		Context initCtx = new InitialContext();
		Context envCtx = (Context)initCtx.lookup("java:comp/env");
		
		DataSource dataSource = (DataSource)envCtx.lookup("jdbc/mariadb1");
		
		conn = dataSource.getConnection();
	
		String sql = "select seq, name, publisher, author, price from books";
	
		pstmt = conn.prepareStatement(sql);
	
		rs = pstmt.executeQuery();
	
		sbHtml.append("<books>");
		while(rs.next()) {

			sbHtml.append("<book>");
			sbHtml.append("<seq>" + rs.getString("seq") + "</seq>");
			sbHtml.append("<name>" + rs.getString("name") + "</name>");
			sbHtml.append("<publisher>" + rs.getString("publisher") + "</publisher>");
			sbHtml.append("<author>" + rs.getString("author") + "</author>");
			sbHtml.append("<price>" + rs.getString("price") + "</price>");
			sbHtml.append("</book>");
		}
		sbHtml.append("</books>");
	} catch(NamingException e) {
			System.out.println("[에러] : " + e.getMessage());		
		} catch(SQLException e) {
			System.out.println("[에러] : " + e.getMessage());
		} 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) {} 			
}
	
%>


<%=sbHtml %>



🌙 json (441p)

https://jsonlint.com/ (검사 사이트)

<%@ page language="java" contentType="text/plain; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true" %>
[
	{
		"name": "HTML5 + CSS3 입문",
		"publisher" : "삼국미디어",
		"author" : "유비",
		"price" : "30000원"
	},
	
	{
		"name": "Javascript + JQuery 입문",
		"publisher" : "삼국미디어",
		"author" : "관우",
		"price" : "32000원"
	},
	
	{
		"name": "Node.js 프로그래밍",
		"publisher" : "삼국미디어",
		"author" : "장비",
		"price" : "22000원"
	},
	
	{
		"name": "HTML5 프로그래밍",
		"publisher" : "삼국미디어",
		"author" : "조자룡",
		"price" : "32000원"
	}
]

실행도 되고 검사 사이트에서 valid 나오면 정상인 것( 안나오면 비정상)



🌙 json을 db 연동

json 형식에 맞게 써주면 된다. (out.println 하면 enter키 돼서 나옴)

<%@ page language="java" contentType="text/plain; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true" %>
<%@ page import="javax.naming.Context"  %>
<%@ page import="javax.naming.InitialContext"  %>
<%@ page import="javax.naming.NamingException"  %>

<%@ page import="javax.sql.DataSource" %>

<%@ page import="java.sql.Connection"  %>
<%@ page import="java.sql.PreparedStatement"  %>
<%@ page import="java.sql.ResultSet"  %>
<%@ page import="java.sql.SQLException"  %>
<%
	request.setCharacterEncoding("utf-8");

	
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	
	StringBuilder sbHtml = new StringBuilder();

	try { 
		Context initCtx = new InitialContext();
		Context envCtx = (Context)initCtx.lookup("java:comp/env");
		
		DataSource dataSource = (DataSource)envCtx.lookup("jdbc/mariadb1");
		
		conn = dataSource.getConnection();
	
		String sql = "select seq, name, publisher, author, price from books";
	
		pstmt = conn.prepareStatement(sql);
	
		rs = pstmt.executeQuery();
	
		sbHtml.append("[");
		while(rs.next()) {

			sbHtml.append("{");
			sbHtml.append("\"seq\" : \"" + rs.getString("seq") + "\",");
			sbHtml.append("\"name\" : \"" + rs.getString("name") + "\",");
			sbHtml.append("\"publisher\" : \"" + rs.getString("publisher") + "\",");
			sbHtml.append("\"author\" : \"" + rs.getString("author") + "\",");
			sbHtml.append("\"price\" : \"" + rs.getString("price") + "\"");
			sbHtml.append("},");
			
		}
		sbHtml.append("]");
		
		sbHtml.deleteCharAt(sbHtml.lastIndexOf(","));
	} catch(NamingException e) {
			System.out.println("[에러] : " + e.getMessage());		
		} catch(SQLException e) {
			System.out.println("[에러] : " + e.getMessage());
		} 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) {} 			
}
	
%>


<%=sbHtml %>


🌙 json 라이브러리를 넣어줘서 사용

json-simple-1.1.1.jar lib에 넣고 작업

<%@ page language="java" contentType="text/plain; charset=UTF-8"
    pageEncoding="UTF-8" trimDirectiveWhitespaces="true" %>
<%@page import="org.json.simple.JSONArray" %>
<%@page import="org.json.simple.JSONObject" %>    

<%
	JSONArray arr = new JSONArray();
	for(int i = 1; i <= 3; i++) {
	JSONObject obj = new JSONObject();
	obj.put("name", "책이름" + i);
	obj.put("publisher", "출판사" + i);
	obj.put("author", "이름" + i);
	obj.put("price", "가격" + i);
	
	arr.add(obj);
	}
	out.println(arr);
%>


db 연동한 것도 라이브러리 사용해서 바꾸기

<%
	JSONArray arr = new JSONArray();

		
		while(rs.next()) {
			JSONObject obj = new JSONObject();
			
			obj.put("seq", rs.getString("seq"));
			obj.put("name", rs.getString("name"));
			obj.put("publisher", rs.getString("publisher"));
			obj.put("author", rs.getString("author"));
			obj.put("price", rs.getString("price"));
			
		
			arr.add(obj);
		}
		
		out.println(arr);

%>

위에 선언하고 while문만 바꾸면 끝



🌕 Ajax 동기 / 비동기

동기
	요청하면 응답 때 까지 대기 하는 것
    
    요청
    		~대기~
    응답
    
비동기 (= 스레드)
    
    요청 후 응답 (진행과 다르게 실행)
    
    요청
     ↓		~진행~
    응답       ↓  



🌙 요청 (동기)

<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
	window.onload = function(){
		document.getElementById('btn').onclick = function() {
			//alert('버튼클릭');
			const request = new XMLHttpRequest();
            //false면 동기처리, true면 비동기처리
			request.open('get', 'csv1.jsp', false); //설정
			request.send(); //요청 보내기
		};
	};
</script>
</head>
<body>

	<button id="btn">요청하기</button>

</body>
</html>

동기라서 요청 후 응답이 있을 때까지 대기한다.


버튼 누르면 개발자 도구 네트워크 쪽에 뜬다(화면에서는 아무일도 없음, xhr은 XMLHttpRequest의 약자 )


csv.1 을 누르고 응답 보면 요청한 정보 뜬다.


🌙 응답 (동기)

밑에다 요청을 콘솔로 받아보기

console.log(request.responseText); //요청 받기




🌙 요청 (비동기)

p.456 /p.439 페이지 조건값 주기

false - > true로 바꿔주면 됨

이때 실행을 하면 개발자도구에도 보이지 않는데, 요청하는 순간에 요청과 메인이 분리돼서 실행돼서 그렇다.

이벤트 등록으로 해결해줄 수 있다.

request.readyState - 상태값 변화

 1. UNSENT (숫자 0) : XMLHttpRequest 객체가 생성됨.

 2. OPENED (숫자 1) : open() 메소드가 성공적으로 실행됨.

 3. HEADERS_RECEIVED (숫자 2) : 모든 요청에 대한 응답이 도착함.

 4. LOADING (숫자 3) : 요청한 데이터를 처리 중임.

 5. DONE (숫자 4) : 요청한 데이터의 처리가 완료되어 응답할 준비가 완료됨.
 
 4번 완료 상태가 중요!
		document.getElementById('btn2').onclick = function() {
			const request = new XMLHttpRequest();
			
			//상태값 변화 0:아무상태x 1:자료요청  2:응답헤더도착상태 3:로딩 4:사용할상태
			request.onreadystatechange = function() {
				//진행되는 상태를 볼 수 있음
				console.log(request.readyState);
            };
            
			request.open('get', 'csv1.jsp', true); 
			request.send(); 
			
			
		};


비동기 부분 코드

		//비동기
		document.getElementById('btn2').onclick = function() {
			const request = new XMLHttpRequest();
			
			console.log("1");
			//상태값 변화 0:아무상태x 1:자료요청  2:응답헤더도착상태 3:로딩 4:사용할상태
			request.onreadystatechange = function() {
				//진행되는 상태를 볼 수 있음
				//console.log(request.readyState);
				
				//4번일때 정상(받은 것)
				if(request.readyState == 4) {
					//페이지 검사(404,500 등 에러 페이지 때문에)
					if(request.status == 200) {
						console.log("2");
						console.log(request.responseText);
					}
					else {
						alert('페이지 오류');
					}
				}
			};
			request.open('get', 'csv1.jsp', true); 
			request.send(); 
			
			console.log("3");
			
		};
	};


보면 진행상황이 1 - 3 - 2로 나오는데, send되는 순간에 분리돼서 실행되는 것을 볼 수 있다( 1 출력 - send실행 - 대기하지 않고 바로 3 출력 - send는 위 가서 request.onreadystatechange = function() { 이쪽 실행하다가 2를 출력)

실행 순서가 중요하다!



tip : 아이디 중복검사 할때 ajax 사용하면 좀 더 편하게 하기 가능!

🌕 ajax로 데이터 보여주기

🌙 ajax: 버튼 클릭시 데이터 보여주기

<script type="text/javascript">
	window.onload = function(){
	
		document.getElementById('btn').onclick = function() {
			const request = new XMLHttpRequest();
			
			request.onreadystatechange = function() {

				if(request.readyState == 4) {
					if(request.status == 200) {
						const datas = request.responseText.trim();
						const rowdatas = datas.split('\n'); <-- 각 행 구분
						console.log(rowdatas[0]);
						
						let result = "<table border='1' width='600'>";
						for(let i = 0; i < rowdatas.length; i++) {
							let coldatas = rowdatas[i].split(',');  <--열 구분
							result += "<tr>";
							result += "<td>" + coldatas[0] +"</td>";
							result += "<td>" + coldatas[1] +"</td>";
							result += "<td>" + coldatas[2] +"</td>";
							result += "<td>" + coldatas[3] +"</td>";
							result += "</tr>";
						}
						result += "</table>";
						
						document.getElementById('result').innerHTML = result;
                        <-- 브라우저에 띄우기
					}
					else {
						alert('페이지 오류');
					}
				}
			};
			request.open('get', 'csv1.jsp', true); 
			request.send(); 
			
			
		};
	};
</script>


🌙 xml 문서 보여주기

<script type="text/javascript">
	window.onload = function(){
		document.getElementById('btn').onclick = function() {
			const request = new XMLHttpRequest();
			
			request.onreadystatechange = function() {

				if(request.readyState == 4) {
					if(request.status == 200) {
						//문자열
						//console.log(typeof request.responseText);
						//XML 객체
						//console.log( request.responseXML);
						
						const xmlData = request.responseXML;
						
						const names = xmlData.getElementsByTagName('name');
						//console.log(names);
						//console.log(names.length);
						//console.log(names[1]);
						//console.log(names[0].innerHTML);
						
						const publishers = xmlData.getElementsByTagName('publisher');
						const authors =  xmlData.getElementsByTagName('author');
						const prices =  xmlData.getElementsByTagName('price');
						
						let result = '<table border="1">'
						
						for(let i = 0; i <names.length; i++) {
							result += "<tr>"
							result += "<td>" + names[i].innerHTML + '</td>'							
							result += "<td>" + publishers[i].innerHTML + '</td>'							
							result += "<td>" +authors[i].innerHTML + '</td>'							
							result += "<td>" +prices[i].innerHTML + '</td>'							
							result += "</tr>"
						}
						result += "</table>"
						
					document.getElementById('result').innerHTML = result;
					}
					else {
						alert('페이지 오류');
					}
				}
			};
			request.open('get', 'xml2.jsp', true); 
			request.send(); 
			
			
		};
	};
</script>

가져온 xml에서 에러나면 실행시 에러남(주의)



🌙 ajax : json 보여주기

구조적으로 해석하기 편하다.

<script type="text/javascript">
	window.onload = function(){
		document.getElementById('btn').onclick = function() {
			const request = new XMLHttpRequest();
			
			request.onreadystatechange = function() {

				if(request.readyState == 4) {
					if(request.status == 200) {
						const data = request.responseText.trim();
						const jsonData = JSON.parse( data );
						
						//console.log(jsonData);
						console.log(jsonData[0]);
						console.log(jsonData[0].name);
						
						let result = '<table border="1">'
						for(let i = 0; i < jsonData.length; i++) {
							result += '<tr>';
							result += '<td>' + jsonData[i].name + '<td>';
							result += '<td>' + jsonData[i].publisher + '<td>';
							result += '<td>' + jsonData[i].author + '<td>';
							result += '<td>' + jsonData[i].price + '<td>';
							result += '</tr>';
						}
							result += '</table>';
							
							document.getElementById('result').innerHTML = result;
					}
					else {
						alert('페이지 오류');
					}
				}
			};
			request.open('get', 'json2.jsp', true); 
			request.send(); 
			
			
		};
	};
</script>

🌙 응용 : 주간 영화 사이트(api) 들어가서 순위, 영화이름 보여주기

방법 1

<script type="text/javascript">
	window.onload = function(){
		document.getElementById('btn').onclick = function() {
			const request = new XMLHttpRequest();
			
			request.onreadystatechange = function() {

				if(request.readyState == 4) {
					if(request.status == 200) {						
						const xmlData = request.responseXML;
						
						const rank = xmlData.getElementsByTagName('rank');
						const movieNm = xmlData.getElementsByTagName('movieNm');
						
						let result = '<table border="1">'
						for(let i = 0; i < rank.length; i++) {
							result += '<tr>'
							result += '<td>' + rank[i].innerHTML + '</td>'							
							result += '<td>' + movieNm[i].innerHTML + '</td>'							
							result += '</tr>'
						}
						result += '</table>'
						
						document.getElementById('result').innerHTML = result;
						
					}
					else {
						alert('페이지 오류');
					}
				}
			};
			request.open('get', 'http://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchWeeklyBoxOfficeList.xml?key=f5eef3421c602c6cb7ea224104795888&targetDt=20230506', true); 
			request.send(); 
			
			
		};
	};
</script>

방법2 : weeklyBoxOffices로 childNodes(하위 노드들) / nodeName(노드 이름) 활용하기

if(request.readyState == 4) {
					if(request.status == 200) {						
						const xmlData = request.responseXML;
						
						const weeklyBoxOffices = xmlData.getElementsByTagName('weeklyBoxOffice');
						
						let result = '<table border="1">'
						for(let i = 0; i < weeklyBoxOffices.length; i++) {
							result += '<tr>'
							for(let j =0; j<weeklyBoxOffices[i].childNodes.length; j++) {
								
							result += '<td>' + weeklyBoxOffices[i].childNodes[j].nodeName
								+ ":" + weeklyBoxOffices[i].childNodes[j].innerHTML + '</td>'
							
							}
							result += '</tr>'
						}
						result += '</table>'
						
						document.getElementById('result').innerHTML = result;
						
					}



profile
끄적끄적

0개의 댓글