Ajax 기술 문서(작성자 : 김연수)
(첫 회사에 입사하여 만든 사내 배포용 기술 문서)
Ajax In Action 도서를 참고하며 자료를 만들었으며, 이 자료를 만들면서 AJAX에 대한 많은 이해를 하게 됐던 거 같다.
작성일자는 잘못된 것이고, 2007년에 만들고 발표한 것으로 추정된다.
Ajax 기술 문서(작성자 : 김연수)
(첫 회사에 입사하여 만든 사내 배포용 기술 문서)
Ajax In Action 도서를 참고하며 자료를 만들었으며, 이 자료를 만들면서 AJAX에 대한 많은 이해를 하게 됐던 거 같다.
작성일자는 잘못된 것이고, 2007년에 만들고 발표한 것으로 추정된다.
JSP 프로그래밍 #01 웹 프로그래밍
1.1 웹 (온라인 강의: https://youtu.be/qDZXXHhMr4A)
1.2 서블릿 (온라인 강의: https://youtu.be/a8hHeUhbz2k)
1.3 JSP(Java Server Page) (온라인 강의: https://youtu.be/Q4ezLP6KLwM)
1.4 프로그래밍을 위한 환경 설정 (온라인 강의: https://youtu.be/k2eR6gLULA8)
node.js를 처음 접하는 개발자를 위한 스터디 자료입니다.
실습 위주로, 간단한 웹 페이지를 만들어 보는 것을 목표로 하며,
express를 활용하기에 앞서, node.js 기본 API만으로 GET/POST 처리 방식을 알아봅니다.
내용의 깊이가 있지는 않으며, 단지 node.js의 입문을 위한 가벼운 수준으로 내용이 구성되었습니다.
JSP 프로그래밍 #01 웹 프로그래밍
1.1 웹 (온라인 강의: https://youtu.be/qDZXXHhMr4A)
1.2 서블릿 (온라인 강의: https://youtu.be/a8hHeUhbz2k)
1.3 JSP(Java Server Page) (온라인 강의: https://youtu.be/Q4ezLP6KLwM)
1.4 프로그래밍을 위한 환경 설정 (온라인 강의: https://youtu.be/k2eR6gLULA8)
node.js를 처음 접하는 개발자를 위한 스터디 자료입니다.
실습 위주로, 간단한 웹 페이지를 만들어 보는 것을 목표로 하며,
express를 활용하기에 앞서, node.js 기본 API만으로 GET/POST 처리 방식을 알아봅니다.
내용의 깊이가 있지는 않으며, 단지 node.js의 입문을 위한 가벼운 수준으로 내용이 구성되었습니다.
2. www.javaspecialist.co.kr
1. AJAX(Asynchronous JavaScript and XML)
• "비동기 방식의 자바스크립트와 XML" 로서 "자바스크립트와 XML" 만을 사용하는 일종의 '자바'나 '
베이직' 그리고 'C' 와 같은 프로그래밍의 언어 이름 일것 같지만 실제로는 보다 많은 기술을 복합적
으로 사용하여 프로그램을 개발하는데 필요한 하나의 개발 패턴(기술)이라고 할수 있다.
• 기존 웹사이트 구현 방식의 특징
1. 클라이언트(사용자 컴퓨터)의 웹브라우저(인터넷익스플로러)가 웹서버(아파치)에게 요청을 전
송한다.
2. 웹서버는 요청 처리를 하기 위해 DB와 연동을 해야하는데 DB와 연동을 하기 위해서는
JSP/ASP/PHP 등의 서버 측 어플리케이션을 사용해서 즉 서버사이트 스크립트의 도움을 받아
사용자의 요청을 처리한다.
3. 처리 결과를 HTML(FORM 태그)을 생성해서(이용해서) 클라이언트 측 웹브라우저(인터넷익스
플로러)에게 전송을 한다.
4. 클라이언트 측 웹브라우저(인터넷익스플로러)는 응답으로 받은 HTML을 분석한 뒤 그 내용을
화면에 그려준다.
• 기존 웹사이트의 단점
– 데이터를 처리후 HTML(FORM 태그)를 이용해서 값을 전달할 때 submit()을 통해서 값을 보내게
되는데 이때 사용되는 페이지는 서버와 통신하고 response 값이 넘어오기 전까지는 아무것도 못
하는 상태가 된다.
– 즉, 사용자가 서버측으로 요청을 보내면 사용자는 서버의 응답이 올 때까지 어떠한 다른 화면도
볼 수 없고, 사용자가 요청을 하면 서버로부터 응답을 받아야만 브라우저에서 결과를 볼 수 있다.
• Ajax의 장점
– Ajax는 자바스크립트를 통해서 서버와 통신하고 값을 받아온다.
– 서버와 통신하고 값을 받아오는 중에도 다른 일을 수행할 수 있다.
2
3. www.javaspecialist.co.kr
2. XMLHttpRequest
• 비동기 요청을 수행하기 위한 JavaScript API
– XMLHttpRequest(XHR) 객체는 익스플로러 5에서 ActiveX 컴포넌트 형식으로 가장 먼저 제공되
었음
– XHR은 W3C 표준이 아니며 브라우저마다 작동방식에 있어서 약간의 차이가 있었기 때문에 모
질라와 사파리 웹브라우저에서 이 객체를 도입하기 전까지 많은 개발자들이 XMLHttpRequest
객체의 사용을 꺼려했다.
– 현재 대부분의 브라우저들은 XHR 기능을 서로 비슷하게 구현하고 있으며 현재 대부분의 브라우
저들이 네이티브 자바스크립트(native javascript) 객체로 XHR 을 지원하고 있다.
• Ajax 구현의 시작은 XHR 객체의 생성에서 시작한다.
– XHR 은 W3C 의 표준이 아니므로, 과거 익스플로러 5, 6에서는 ActiveX Component 형식으로 구
현되었고, 그 밖에 다른 브라우저들(FireFox, Chrome, Safari, Opera)은 네이티브 자바스크립트
객체로 구현되었다.
– 익스플로러 7이후부터는 XMLHttpRequest를 네이티브 자바스크립트 객체로 지원한다. 만일 여
러분이 익스플로러 6, 7과 그 이후의 익스플로러 버전, 그리고 그 외 다른 브라우저에서도 XHR
을 사용하기 위해서 XHR 객체를 얻어오는 자바스크립트 코드를 다음과 같이 작성할 수 있다.
• XMLHttpRequest 객체를 얻는 방법
var xmlHttp;
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest(); //IE7+, Firefox, Chrome, Opera, Safari에서
동작
} else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); //IE6, IE5를 위한 것.
}
3
4. www.javaspecialist.co.kr
3. XMLHttpRequest 메서드
메서드 설명
open()
void open(string method, string url, boolean async, string username, string password)
요청을 초기화한다.
- method : POST, GET, PUT 3가지 중 하나를 사용함(필수항목)
- url : 요청하고자 하는 서버의 url(필수항목)
- async : 요청이 비동기인지 여부를 판단하는 항목. true(기본값)일 경우 요청은 비동기로 처리과고,
false이면 요청은 동기로 처리됨.
- username과 password : 인증이 필요할 경우 사용자이름과 비밀번호
send()
void send(content)
실질적으로 요청을 서버로 보낸다. 요청이 비동기이면 이 메서드는 바로 리턴된다. 그러나 요청이 동
기이면 서버에서 응답을 받을 때까지 대기한다.
- content : content 파라미터는 HttpRequest body 의 한 부분으로 서버로 전달된다. DOM 객체(XML 객
체), input stream, string 값으로 설정할 수 있다. content 에 값을 넘기려면 open() 메서드는 반드시
POST 로 설정해야 하며, GET 방식으로 요청하려면 null 을 설정한다. send(null), send(), send("")는
모두 같은 의미이다.
setRequestHeader()
void setRequestHeader(string header, string value)
header 에 해당하는 value 값으로 HttpRequest 헤더에 값을 설정하는 메서드. 반드시 open() 메서드
다음에 위치해야 한다.
- header : 헤더 이름.
- value : 헤더에 설정할 값.
* POST방식 요청의 파라미터가 한글이 포함된 key=value 형식 일 경우 Content-type 헤더의 값을
application/x-www-form-urlencoded로 설정해야 한다.
abort()
void abort()
요청을 중지한다.
getAllResponseHeaders()
string getAllResponseHeaders()
요청에 대응되는 응답의 헤더정보를 리턴한다. Content-Length, Date, URI등을 포함하는 헤더정보를
string 형식으로 반환한다.
getResponseHeader()
string getResponseHeader(string header)
응답의 헤더정보 중에서 header 에 대응되는 값을 string 형식으로 반환한다.
- header : 헤더 이름.
4
5. www.javaspecialist.co.kr
4. XMLHttpRequest 속성
속성 설명
readyState
readyState 속성은 서버의 처리 상태를 0에서 4까지 정수 값으로 나타낸다.
0: open() 메서드 수행 전
1: 로딩(Loading) 중인 상태 (send() 수행 전)
2: 로딩 완료 (서버가 Request를 받은 상태)
3: 서버가 처리 중인 상태
4: 서버 처리 완료
responseText
서버의 응답을 string 형식으로 나타낸다. 단순 text를 innerHTML 속성으로 표현할 때 사
용한다. 그러나 논리적으로 파싱하거나 동적으로 페이지 컨텐츠를 생성하기는 힘들다.
responseXML 서버의 응답을 XML 로 나타낸다. 이 속성은 DOM 객체로 파싱할 수 있다.
responseBody 서버의 응답을 배열로 나타낸다. 이 속성은 DOM 객체로 파싱할 수 있다.
responseStream 서버의 응답을 ADO Stream으로 나타낸다. 이 속성은 DOM 객체로 파싱할 수 있다.
status
서버로부터의 HTTP 상태코드입니다. 200(OK), 204(No Content), 403(Forbidden), 404(
Not Found), 500(Internal Server Error) 등이 있다.
statusText
HTTP 상태코드에 대한 텍스트 값입니다. OK, NOT Found 등 각 상태 코드들에 대한 텍
스트 값.
5
6. www.javaspecialist.co.kr
5. readystatechange 이벤트와 readyState 속성
• readystatechange는 readyState 값이 바뀔 때 마다 발생하는 이벤트
• onreadystatechange 이벤트 핸들러를 통해 readyState 값의 변경에 따른 처리를 작성해야
한다.
• 서버로부터 응답을 받았을 경우 데이터 처리
– readyState 값이 COMPLETED(4)로 변경될 경우
– state 값이 200인 경우(서버로부터 정상적으로 응답을 받았을 경우)
xmlHttp.onreadystatechange = function() { //처리상태 변경이 발생했을 때
if (xmlHttp.readyState == 4) { //서버 처리 완료
if (xmlHttp.status == 200) { //서버의 OK응답
doMainProcess(xmlHttp); //메인 처리
}
}
};
• readyState 속성 설명
코드 상태 설명
0 UNINITIALIZED
XMLHttpRequest 객체를 생성하였지만, 초기화되지 않았다.
즉, open() 메서드를 실행하지 않은 상태
1 LOADING
XMLHttpRequest 객체를 생성하였고, open() 메서드를 수행하였지만, send() 메서드를 수행하지 않
은 상태.
2 LOADED send() 메서드를 수행하였지만, 서버가 처리를 준비하고 있는 상태.
3 INTERACTIVE 처리를 완료하지 않았지만, 진행 중인 상태.
4 COMPLETED 처리를 완료한 상태.
6
7. www.javaspecialist.co.kr
6. 비동기 요청 코드 예
1. <script>
2. var xmlHttp;
3. function createXMLHttpRequest() {
4. if (window.ActiveXObject) {
5. xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
6. }
7. else if (window.XMLHttpRequest) {
8. xmlHttp = new XMLHttpRequest();
9. }
10. }
11. function startRequest() {
12. createXMLHttpRequest();
13. xmlHttp.onreadystatechange = handleStateChange;
14. xmlHttp.open("GET", "result.jsp", true);
15. xmlHttp.send(null);
16. }
17.
18. function handleStateChange() {
19. if(xmlHttp.readyState == 4) {
20. if(xmlHttp.status == 200) {
21. alert("The server replied with: " + xmlHttp.responseText);
22. }
23. }
24. }
25. </script>
7
12. www.javaspecialist.co.kr
7. AHOH(Asynchronous HTML over HTTP) (1/2)
• AHOH는 브라우저에서 HTTP를 통한 요청을 ajax를 이용해 비동기 적으로 수행해주는 것을 의미한
다.
• AHOH는 서버에 비동기 요청을 위해 자바스크립트를 반복적으로 작성하는 것을 줄여줄 수 있다.
1. //파일명 : ahoh.js
2. function ahoh(url, target) {
3. document.getElementById(target).innerHTML = ' Fetching data...';
4. if (window.XMLHttpRequest) {
5. req = new XMLHttpRequest();
6. } else if (window.ActiveXObject) {
7. req = new ActiveXObject("Microsoft.XMLHTTP");
8. }
9. if (req != undefined) {
10. req.onreadystatechange = function() {
11. ahohDone(target);
12. };
13. req.open("GET", url, true);
14. req.send("");
15. }
16. }
17. function ahohDone(target) {
18. if (req.readyState == 4) { // only if req is "loaded"
19. if (req.status == 200) { // only if "OK"
20. document.getElementById(target).innerHTML = req.responseText;
21. } else {
22. document.getElementById(target).innerHTML=" AHOH Error:n"+ req.status + "n"
+req.statusText;
23. }
24. }
25. }
12
13. www.javaspecialist.co.kr
7. AHOH(Asynchronous HTML over HTTP) (2/2)
• AHOH를 이용하면 <a> 엘리먼트를 이용해 작성된 링크를 클릭했을 때 비동기 요청이 발생
되게 할 수도 있다.
1. <!-- 파일명 : ahoh.html -->
2. <!DOCTYPE html>
3. <html>
4. <head>
5. <meta charset="EUC-KR">
6. <title>AHOH(Asynchronous HTML over HTTP)</title>
7. <script src="ahoh.js"></script>
8. <script>
9. //Calls the library function 'ahoh' - defined in 'ahoh.js' file.
10. function load(filename) {
11. ahoh(filename,"content");
12. }
13. </script>
14. </head>
15. <body>
16. <ul id="tabs">
17. <li><a href="result.jsp">동기 요청</a></li>
18. <li><a href="javascript:load('result.jsp');">비동기 요청</a></li>
19. </ul>
20. <div id="content"></div>
21. </body>
22. </html>
13
14. www.javaspecialist.co.kr
8. 동일 도메인 정책(CORS)
• CORS(Cross-Origin Resource Sharing) 사양에 정의된 CORS는 HTTP 헤더를 사용하여 대
개 동일 도메인 출처 정책으로 제한되는 도메인 간 웹 요청을 가능하게 한다.
• 기본적으로 동일한 사이트 출처 정책은 웹 사이트가 다른 도메인에 있는 서버의 리소스를 요
청하지 못하도록 한다. 그래서 XHR 객체는 요청할 수 있는 서버의 리소스 URL 에 제한이 있
다.
• 즉, 접근 할 수 있는 서버 리소스 URL 은 XHR 객체가 존재하는 도메인에 있어야 한다.
• XHR 객체가 자기가 속해있는 도메인이 아닌 그 밖에 있는 서버의 URL 을 호출하면 브라우
저 마다 약간의 차이가 있지만 요청자체를 브라우저에서 차단한다.
다른 도메인의 자원을 Ajax API을 이용해 요청할 경우
지원 브라우저(브라우저 엔진)
• Gecko 1.9.1 이상.
• WebKit(Safari 4이상, Google Chrome 3 이상)
• MSHTML/Trident 6.0 (Internet Explorer 10) 이상
• MSHTML/Trident 4.0 & 5.0 (Internet Explorer 8 & 9)
XDomainRequest 객체에 의해 지원함
• Opera 12.00 이상, Opera Mobile 12 이상, Opera Mini 지원 안 함.
14
15. www.javaspecialist.co.kr
9. 동일 도메인 정책 회피
• 다른 도메인의 페이지를 비동기적으로 요청해야 할 경우
• 해결방법 1
– 서버에서 응답할 때 수실할 도메인을 Access-Control-Allow-Origin 헤더를 설정하여 해결
– 도메인을 *로 하면 모든 도메인에서 수신 가능하도록 함
– 헤더의 이름은 Access-Control-Allow-Origin, 그리고 값은 수신할 도메인이름 이어야 한다.
– 예) - JSP 코드
<%
response.setHeader("Access-Control-Allow-Origin", "*");
%>
– 정보 제공자가 해줘야 함
• 해결 방법 2
– 같은 도메인 내에 외부 도메인 페이지를 포함시킬 서버페이지를 이용한다.
– 예) - JSP 코드(프락시 페이지로 이용됨)
<%@ page language="java" contentType="text/xml; charset=EUC-KR"
pageEncoding="EUC-KR" trimDirectiveWhitespaces="true"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:import charEncoding="UTF-8" url="http://otherdomain/reqpage.jsp"></c:import>
– 정보 요청자가 직접 해결 할 수 있음
• JSP에서는 jstl.jar 파일과 standard.jar 파일이 필요함
서버 구현 언어
마다 응답헤더를
설정하는 방법이
다를 수 있다.
아래 두 가지 방법 외에도
iframe 과 Communication
API를 이용할 수도 있다.
15
16. www.javaspecialist.co.kr
10. Proxy page를 이용한 CORS 회피
Client
Web Server(Domain A)
-----------------------------------------------------
-----------------------------------------------------Browser
Web Container
<<HTTP>>
HTTP response
(Data)
HTTP request
(Asynchronous)
HTML CSS JS
구조 표현 동작
Server Side Page를 이용
해 다른 도메인의 데이터
를 요청하도록 한다.
Web Server(Domain B)
RSS feed page
<?xml
--------
--------
-----
-------
--------
-----
<%
--------
--------
-----
-------
--------
-----
%>
Proxy
page
문서가 별도로 존재하는 것
을 의미하는 것이 아님 프록
시 페이지의 실행 결과가
XML 또는 JSON 표현 형식
으로 제공됨을 의미함
16
17. www.javaspecialist.co.kr
Lab - 문제
• 뉴스 구독하는 모바일 앱 만들기
• 제공되는 HTML 문서는 UI 개발의 편의를 위해 jQuery mobile 라이브러리를 사용했음
• 서블릿을 실행시킬 수 있는 Tomcat 웹서버가 필요함
– 동일 도메인 정책 문제를 요청자가 해결하기 위해
• 제공되는 파일
– proxy_common.jsp
• 요청을 대신 해주는 프락시 코드
– news_rss.html
• 뉴스 구독 모바일 페이지
• jquery mobile 라이브러리를 이용했음
• 작성해야 하는 파일
– rss.js
• 이클립스에서 톰캣 서버 Proxy 설정
– Run -> Run Configuration
• Apache Tomcat
- Tomcat v7.0 Server at localhost
• Arguments 탭
– VM Arguments 에 아래 내용 추가
-Dhttp.proxyHost=168.219.61.252
-Dhttp.proxyPort=8080
• 톰캣 서버 Proxy 설정
– bin/catalina.bat(Window) 또는 catalina.sh(Linux) 파일 수정
set PROXYHOST_CONFIG=-Dhttp.proxyHost=168…
set PROXYPORT_CONFIG=-Dhttp.proxyPort=8080
JAVA_OPTS = %PROXYHOST_CONFIG%
%PROXYPORT_CONFIG%
17
19. www.javaspecialist.co.kr
Lab - Solution (Ajax/end/news_rss.html)
31. <div data-role="footer">
32. <h4>푸터</h4>
33. </div>
34.</div>
35.
36.<!-- 위의 #news_rss a 태그 중에 하나 클릭시 아래의 내용이 동적으로 해당 RSS정보가 나타남 -->
37.<div data-role="page" id="news_rss">
38. <div data-role="header">
39. <a data-rel="back">뒤로</a>
40. <h1>RSS 헤더</h1>
41. </div>
42.
43. <div data-role="content">
44. <p class="content-list">RSS 내용</p>
45. <div class="content-desc"></div>
46. </div>
47.</div>
48.
49.</body>
50.</html>
19
20. www.javaspecialist.co.kr
Lab - Solution (Ajax/end/proxy_common.jsp)
1. <%-- proxy_common.jsp --%>
2. <%@ page language="java" contentType="text/xml; charset=EUC-KR"
3. pageEncoding="EUC-KR" trimDirectiveWhitespaces="true"%>
4. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
5. <c:import charEncoding="UTF-8" url="${param.rssurl}"></c:import>
6. <!-- 위에서 가장중요한 부분은 param.rssurl 인데 이것으로 jquery mobile 과 교신할때 쓰이
는 주소 파라미터 값으로 작동된다.-->
7. <!-- import 태그에서 charEncoding 속성의 값은 RSS서버의 XML 인코딩과 일치해야 한다. -->
• 설명
– 위 코드의 실행은 5라인 url의 값으로 전달되는 페이지를 대신 호출해 준다.
– 이 페이지의 실행 결과는 XML문서이다.
• XML 문서의 경우 Well-formed 규칙을 만족해야 파싱이 가능하다.
– Well-formed 규칙은 최소한의 XML 문서 규칙을 만족해야 한다는 것
– 문서의 처음은 반드시 <?xml 로 시작해야 한다
– 시작태그가 있으면 반드시 끝 태그가 있어야 한다.
• 그런데 위 코드에서 1~4라인은 JSP에서 사용하는 코드인데 실행 후 빈 라인이 삽입된다.
– 그래서 3라인에 trimDirectiveWhitespaces="true"를 넣은 것이며, 이는 <% %>로 인해
발생하는 공백과 빈줄을 제거해 준다.
• 이 문서는 XML 문서로 리턴되야 하므로 페이지의 컨텐트 타입을 text/xml로 설정해야 한다.
20
21. www.javaspecialist.co.kr
Lab - Solution (Ajax/end/rss.js)
1. var xhr = new XMLHttpRequest(); //ajax를 위한 객체 생성
2.
3. function init(){
4. var links = document.querySelectorAll("div[data-role='content'] p > a");
5.
6. for(var i=0, n=links.length ; i<n; i++) {
7. //console.log(links[i]);
8. links[i].addEventListener('click', getRssData);
9. }
10.};
11.
12.function getRssData(event) {
13. //event.preventDefault(); //넣으면 페이지 전환 안됨
14. var rss_url = this.dataset.rssurl;
15. if (rss_url == "") {
16. alert('RSS address is empty.');
17. return false;
18. }
19. xhr.onreadystatechange = function() {
20. if(xhr.readyState == 4 && xhr.status == 200){
21. displayResult(xhr.responseXML); //결과를 XML로 받아야 파싱이 가능함
22. }
23. };
24. rss_url = encodeURIComponent(rss_url); //주소 인코딩,주소에 한글이 포함되어 있을 경우
25. xhr.open("GET", "./proxy_common.jsp?rssurl=" + rss_url, true);
26. xhr.send(null);
27.}
21
22. www.javaspecialist.co.kr
Lab - Solution (Ajax/end/rss.js)
28.function displayResult(result) {
29. var items = result.querySelectorAll('item');
30. //console.log(items.length);
31.
32. var target = document.querySelector("#news_rss div[data-role=content] .content-list");
33.
34. target.innerHTML = "";
35.
36. for(var i=0, n=items.length; i<n; i++) {
37. var title = items[i].querySelector('title').textContent;
38. //var title = items[i].getElementsByTagName('title')[0].textContent; //위 코드아 동일한 의
미
39. var link = items[i].querySelector('link').textContent;
40. var desc = items[i].querySelector('description').textContent;
41. var temp_el = document.createElement("p"); //<p> 요소를 생성함, 뉴스기사 1개 포함
42.
43. temp_el.innerHTML = (i+1) +". <a href='" + link + "'>" + title + "</a><span>" + desc +
"</span>";
44. target.appendChild(temp_el);
45. }
46.};
47.
48.init();
22