웹 개발 한걸음

[JavaScript] AJAX / XMLHttpRequest 파헤쳐보기

Egu99 2021. 4. 14. 11:37

 

   1. AJAX란?    

 

  • AJAX는 Asynchronous JavaScript and XML의 약자로, JavaScript와 XML을 이용한 비동기적 정보 교환 기법이다.
  • 브라우저가 가지고있는 XMLHttpRequest 객체를 이용해서 전체 페이지를 새로 고치지 않고도 페이지의 일부만을 위한 데이터를 로드하는 기법 이며 JavaScript를 사용한 비동기 통신, 클라이언트와 서버간에 XML 데이터를 주고받는 기술이다.
  • 이름에 XML이라고 명시되어있긴 하지만 JSON이나 일반 텍스트 파일과 같은 다른 데이터 오브젝트들도 사용 가능해서 요즘엔 XML을 잘 안 쓰고 십중팔구 JSON을 다룬다.

 


      2. 역사        

 

** (1) 등장 이전

  • Ajax가 등장하기 이전에는 웹 브라우저가 어떤 정보를 요청하면 서버는 해당 정보를 포함한 페이지 전체를 전달해 주었다.
  • 웹 브라우저는 서버로부터 받은 마크업 데이터(HTML)를 브라우저 창에 렌더링하는 일을 했다. 사실 이 방법은 웹 브라우저에게도, 서버에게도 서로 불편했는데 브라우저는 매번 똑같은 레이아웃의 페이지를 처음부터 다시 렌더링해야 했고 서버 역시 매번 같은 페이지를 렌더링(이 경우에는 HTML 파일 생성)해야 해서 서로 부담이 되었다.
  • Ajax 기술을 사용하지 않는 사이트가 특유의 깜빡거림 현상이 생기는 이유가 매번 페이지를 싹 지우고 처음부터 다시 모든 것을 그려내기 때문이다. 

** (2) 등장 후 

  • 과거에도 이런 HTTP 프로토콜을 이용한 비동기식 통신이 MS의 Microsoft.XMLHTTP라는 이름의 컴포넌트로 존재하긴 했었다.
  • 하지만 이 컴포넌트는 브라우저의 고유스펙이 아닌 윈도우에 탑재된 ActiveX를 호출하는 비표준 기술에 무거운 http로 무거운 XML을 받아온다는 사실에 아무도 거들 떠 보지 않는 기술이었다.
  • 그러다 98년도 쯤 네오위즈의 세이클럽이 실시간 채팅을 구현하기 위해 이 기술을 사용했고 차츰 다른 웹 브라우저에서도 사용하게 되었다.
  • 결정적으로 다른 웹브라우저들이 XMLHttpRequest를 도입할 쯤에 구글이 2004년에 Gmail을, 2005년에 구글지도를 어떠한 플래그인없이 AJAX로 구현된 웹 어플리케이션으로 밝혀지면서 큰 화제거리가 되었다.
  • 구글 지도의 발표로부터 열흘 뒤 Jesse James Garrett가 이러한 비동기 통신을 "웹 애플리케이션에 대한 새로운 접근 방식, Ajax라고 부르면서 짧은 글자와 쉬운 발음 덕분에 점차 고유명사처럼 굳어졌다.
     

   3. 언제 사용하는가?    

 

  • 단순하게 WEB화면에서 무언가 부르거나 데이터를 조회하고 싶을 경우, 페이지 전체를 새로고침하지 않기 위해 사용한다고 볼 수 있다.
  • 기본적으로 HTTP 프로토콜은 클라이언트쪽에서 Request를 보내고 서버쪽에서 Response를 받으면 이어졌던 연결이 끊기게 되어있다. 그래서 화면의 내용을 갱신하기 위해서는 다시 request를 하고 response를 하며 페이지 전체를 갱신하게 된다. 하지만 이렇게 할 경우, 엄청난 자원낭비와 시간낭비를 초래하고 말 것이다.
  • AJAX는 HTML 페이지 전체가 아닌 일부분만 갱신할 수 있도록 XMLHttpRequest객체를 통해 서버에 request한다. 이 경우, JSON이나 XML형태로 필요한 데이터만 받아 갱신하기 때문에 그만큼의 자원과 시간을 아낄 수 있다.

 

 


 

    4. AJAX의 장단점    

 

** 1) 장점

  • 웹페이지의 속도향상
  • 서버의 처리가 완료될 때까지 기다리지 않고 처리가 가능하다.
  • 서버에서 Data만 전송하면 되므로 전체적인 코딩의 양이 줄어든다.
  • 기존 웹에서는 불가능했던 다양한 UI를 가능하게 해준다. ( Flickr의 경우, 사진의 제목이나 태그를 페이지의 리로드 없이 수정할 수 있다.)

** 2) 단점

  • 히스토리 관리가 되지 않는다.
  • 페이지 이동없는 통신으로 인한 보안상의 문제가 있다.
  • 연속으로 데이터를 요청하면 서버 부하가 증가할 수 있다.
  • XMLHttpRequest를 통해 통신하는 경우, 사용자에게 아무런 진행 정보가 주어지지 않는다. (요청이 완료되지 않았는데 사용자가 페이지를 떠나거나 오작동할 우려가 발생하게 된다.)
  • AJAX를 쓸 수 없는 브라우저에 대한 문제 이슈가 있다.
  • HTTP 클라이언트의 기능이 한정되어 있다.
  • 지원하는 Charset이 한정되어 있다.
  • Script로 작성되므로 디버깅이 용이하지 않다.
  • 동일-출처 정책으로 인하여 다른 도메인과는 통신이 불가능하다. (Cross-Domain문제)

 


 

    5. XMLHttpRequest    

 

  • XMLHttpRequest 객체는 Ajax의 핵심으로 클라이언트와 서버 간의 통신을 담당하는 객체이다.
  • XMLHttpRequest 객체는 서버로부터 XML 데이터를 전송받아 처리하는 데 사용되며 클라이언트와 서버 간의 통신할 때 가장 먼저 생성한다.
  • 현재 대부분의 주요 웹 브라우저는 XMLHttpRequest 객체를 내장하고 있다.
  • 이 객체를 사용하면 웹 페이지가 전부 로딩된 후에도 서버에 데이터를 요청하거나 서버로부터 데이터를 전송받을 수 있다.
  • 즉, 웹 페이지 전체를 다시 로딩하지 않고 일부분만을 갱신할 수 있게 된다.

   (1) JSP - Test.jsp    

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<% request.setCharacterEncoding("utf-8"); %>
<% response.setContentType("text/html; charset=utf-8"); %>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Ajax 테스트</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script type="text/javascript">

	var request = new XMLHttpRequest();
	
	
	function testPost() {
		
		var httpMethod = "Post";
		var httpURL = "./TestServlet";
		var httpParam = "name=동물을 좋아하는 개발자";
		
		request.open(httpMethod, httpURL, true);
		request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		request.onreadystatechange = function() {
			if(request.readyState == 4 && request.status == 200){
				var data = request.responseText;
				document.getElementById("here").innerText = data;
			}
		}
		request.send(httpParam);	
	}
	
	
	
	function testGet() {
		
		var httpMethod = "Get";
		var httpURL = "./TestServlet";
		var httpParam = encodeURI("동물을 좋아하는 개발자");
		
		request.open(httpMethod, httpURL+"?name="+httpParam, true);
		
		request.onreadystatechange = function() {
			if(request.readyState == 4 && request.status == 200){
				var data = request.responseText;
				document.getElementById("here").innerText = data;
			}
		}
		request.send();	
	}

</script>

</head>
<body>
	<h1 id="here">여기가 바뀌어야 함</h1>
	<input type="button" value="Ajax-Post" onclick="testPost()">
	<input type="button" value="Ajax-Get" onclick="testGet()">
</body>
</html>
  • 위는 XMLHttpRequest를 사용한 Ajax의 간단 예제를 만들어보았다. 하나하나 살펴보자.
  • Get방식과 Post 방식으로 각각 구현하였다.

 

1) XMLHttpRequest 객체 생성

var request = new XMLHttpRequest();

 

2) open( method, url, [async:true] ) 

request.open("전달방식", "요청URL", 동기여부); 
  • 요청준비단계.  request를 보내고자 하는 url, 그리고 전달 방식과 동기식을 셋팅하는 부분.
    • - method : 데이터 전송방식(GET/POST)
    • - url : 요청 URL
    • - async : 요청에 대한 응답을 기다리는 방식. 비동기(true: 기본값)와 동기(false) 방식이 있다.

 

3) setRequestHeader ( Post방식일 경우)

request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  • request의 header를 설정하는 부분.
  • POST 방식에서는 위와 같이 setRequestHeader 에 콘텐츠 타입이 form-urlencode 임을 지정해야 한다.



4) onreadystatechange

request.onreadystatechange = function() {

}
  • onreadystatechange 이벤트는 클라이언트와 서버간의 전송 상태가 바뀔 때마다 실행, 발생하는 이벤트. 
  • 요청 준비 단계인 open메서드와 실제 데이터 전송인 send 메서드가 이루어지면 이쪽이 실행된다. 

 

5) readyState와 status

if(request.readyState == 4 && request.status == 200){
}
  • readyState 프로퍼티는 XMLHttpRequest 객체의 현재 상태를 나타낸다.
    • 1. UNSENT (숫자 0) : XMLHttpRequest 객체가 생성됨.
    • 2. OPENED (숫자 1) : open() 메소드가 성공적으로 실행됨.
    • 3. HEADERS_RECEIVED (숫자 2) : 모든 요청에 대한 응답이 도착함.
    • 4. LOADING (숫자 3) : 요청한 데이터를 처리 중임.
    • 5. DONE (숫자 4) : 요청한 데이터의 처리가 완료되어 응답할 준비가 완료됨.
  • status 프로퍼티는 서버의 문서 상태를 나타낸다.
    • 200 : 서버에 문서가 존재함
    • 404 : 서버에 문서가 존재하지 않음

6) responseText

var data = request.responseText;
  • responseText는 서버에 요청에 대한 응답으로 받은 데이터가 여기에 문자열로 저장됨.

 

7) send( )

request.send(httpParam);
  • send는 http요청을 실제로 실행하는 메서드. 
  • 이 메서드가 실행되야 비로소 요청이 서버에 전달된다.
  • post방식일 때만 전달할 파라미터를 넣어주고 get방식일 때는 null이나 넣지 않는다.

 

    (2) Servlet  - TestServlet.java   

package user;

import java.io.IOException;
import java.io.PrintWriter;

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("/TestServlet")
public class TestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	
    	request.setCharacterEncoding("UTF-8");
    	response.setContentType("text/html, charset=utf-8");
    	
    	String name = request.getParameter("name");
    	
    	
    	response.getWriter().write(name+"  Post");

    }
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    	request.setCharacterEncoding("UTF-8");
    	response.setContentType("text/html, charset=utf-8");
    	
    	String name = request.getParameter("name");
    	
    	response.getWriter().write(name+ " Get");
    }

}

 

 

 

 

 

 

 

** 결과 화면

요청 method에 따라 다르게 동작한다.

 

 

 

 

 


 

 

 

 

 

 

♣ 참고 및 인용

webclub.tistory.com/195

velog.io/@surim014/AJAX%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80

www.tcpschool.com/ajax/ajax_jquery_ajax

tcpschool.com/xml/xml_dom_xmlHttpRequest