Javascript
Ecmascript
프로그램 언어 = 자바와 비슷
let / const
함수
객체
기본객체
BOM
DOM(처리하는 거 중요) 책 05,06,07 챕터
P. 431 http 통신 (웹 서버와 통신 = 자바의 urlconnection과 비슷)
p. 438 ~ 439 (중요) 서버에서 자료 가져오기
빠르게 동작하는 동적인 웹 페이지를 만들기 위한 개발 기법의 하나
자바스크립트가 사용하는 기술 (문법 아님)
Jsp -> html(web 1.0 방식)이 아니라 Jsp -> data(web 2.0 방식)로 끝난다.
요청을 보내면 url 변화가 없다.(디자인만 바뀜)
Ajax / Dom 에 따라 바뀔 수 있다.
자료
jsp
csv (, 구분자를 가진 데이터)
값,값,값 ...
xml
json
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 프로그래밍,삼국미디어,장비,22000원
HTML5 프로그래밍,삼국미디어,조자룡,30000원
이렇게 만든 csv는 무슨 데이터인지 구별하기가 힘든 감이 좀 있다.
데이터를 조금 구분짓기 위하여 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로 만들기
<%@ page language="java" contentType="text/xml; charset=UTF-8"
pageEncoding="UTF-8"%>
선언부만 바꿔주면 된다. 다른건 동일
테이블 생성
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 %>
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 형식에 맞게 써주면 된다. (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-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문만 바꾸면 끝
동기
요청하면 응답 때 까지 대기 하는 것
요청
~대기~
응답
비동기 (= 스레드)
요청 후 응답 (진행과 다르게 실행)
요청
↓ ~진행~
응답 ↓
<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 사용하면 좀 더 편하게 하기 가능!
<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>
<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에서 에러나면 실행시 에러남(주의)
구조적으로 해석하기 편하다.
<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>
방법 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;
}