Ajax(Asynchronous JavaScript and XML)는 동적인 웹 페이지를 만들기 위한 개발 기법이다. 그 자체로 새로운 언어는 아니고 HTML, CSS, 자바스크립트, DOM, XML 등 기존에 사용되던 여러 기술을 함께 사용한다.
Ajax는 웹 페이지 전체를 다시 로딩하지 않고도 웹 페이지의 일부분만을 갱신할 수 있다. 이 때 Ajax는 서버와 JSON, XML, HTML, 텍스트 파일 등 다양한 형식의 데이터를 주고받을 수 있는데 최근에는 주로 JSON을 사용한다.
Ajax를 사용하지 않고 클라이언트 요청에 대해 뷰를 반환하는 기존의 방식은 매 HttpRequest
요청마다 전체 페이지가 갱신되어야 한다. 따라서 웹 애플리케이션이 다양한 기능을 제공하기 위해서는 여러 개의 웹 페이지가 필요하다.
반면 Ajax는 XMLHttpRequest
객체를 사용하여 요청하고 서버는 JSON으로 응답한다. 클라이언트는 이 응답을 받아 자바스크립트를 이용하여 DOM을 조작하여 웹 페이지의 일부분만을 다시 로딩한다. 때문에 기존 방식과 달리 웹 애플리케이션은 하나의 페이지만으로도 여러 가지 기능을 제공할 수 있다.
DOM(Document Object Model, 문서 객체 모델)은 HTML 문서나 XML 문서에 접근하기 위한 일종의 인터페이스이며, 노드(node)라고 불리는 계층적 단위에 정보를 저장하고 있다.
Ajax는 자바스크립트를 이용해 노드를 삭제하거나 추가하는 등 조작함으로써 웹 페이지의 일부를 변경할 수 있다.
웹 애플리케이션이 사용자에게 두 가지 기능을 제공하는 상황을 가정해 보자 :
Ajax를 사용하지 않는 기존의 방식에서 다음 두 가지 일을 하나의 페이지에서 동시에 처리할 수 있을까?
결론부터 말하자면 불가능하다. 기존 방식에서 두 가지 기능을 제공하려면 다음과 같은 식으로 구현해야 할 것이다 :
map.jsp
)를 보여준다.list.jsp
)로 이동한다.이런 방식을 동기식 처리 방법이라고 한다. 각 응답에 대한 별도의 뷰가 필요하며, 첫 번째 일이 끝난 후에야 그 다음 일이 처리될 수 있다. 만약 지도를 로딩하는 것이 시간이 오래 걸리는 일이라면, 맛집 리스트를 보고 싶은 사용자는 지도 로딩이 끝날 때까지 기다려야만 한다.
Ajax 비동기 처리를 이용하면 하나의 뷰에서 두 개의 요청을 동시에 처리할 수 있다.
Ajax를 사용하는 경우 하나의 페이지(예. main.jsp
)에서 첫 번째로 지도 데이터를 요청하고, 첫 번째 요청이 완료되지 않아도 두 번째 요청으로 맛집 리스트를 요청할 수 있다.
첫 번째 요청과 두 번째 요청은 서로의 동작에 관여하지 않으므로 비동기 방식이라고 한다.
비동기 통신에서 첫 번째 요청 이후 다른 요청을 하기 위해 콜백 함수를 사용한다. 자바스크립트에서 콜백이란 전달인자로 함수를 받는 함수를 말하는데, Ajax에서는 클라이언트가 서버로 요청 후 서버에서 응답한 데이터를 클라이언트에서 받아 처리하는 함수라고도 말할 수 있다.
XMLHttpRequest
객체는 Ajax에서 웹 브라우저가 서버와 데이터를 교환할 때 사용된다. 웹 브라우저가 백그라운드에서 계속해서 서버와 통신할 수 있는 것은 이 객체 덕분이다.
XMLHttpRequest
객체를 생성하는 방법은 두 가지가 있다 :
XMLHttpRequest
객체를 이용한 방법ActiveXObject
객체를 이용한 방법비동기식 통신 방식인 XMLHttp
는 가장 처음으로 익스플로러 5 버전에서 ActiveXObject
라는 객체를 사용하여 구현되었고, 그 후에 모질라와 사파리에서 XMLHttpRequest
라는 이름으로 도입하여 널리 사용되기 시작했다.
초기에는 XMLHttpRequest
객체가 W3C 표준이 아니었기 때문에 웹 브라우저마다 구현상의 차이가 존재했으나, 현재는 XMLHttpRequest
객체가 W3C 표준으로도 제정되었고 모든 브라우저가 기본적으로 지원하고 있다.
따라서 이제는 브라우저와 관계 없이 다음과 같이 XMLHttpRequest
를 생성하면 된다:
var httpRequest = new XMLHttpRequest();
XMLHttpRequest
인스턴스의 메서드를 통해 요청을 보낼 수 있다. 다음은 GET과 POST 요청의 예시이다 :
// GET 방식으로 요청을 보내면서 데이터를 동시에 전달함.
httpRequest.open("GET", "/examples/media/request_ajax.php?city=Seoul&zipcode=06141", true);
httpRequest.send();
// POST 방식의 요청은 데이터를 Http 헤더에 포함시켜 전송함.
httpRequest.open("POST", "/examples/media/request_ajax.php", true);
httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
httpRequest.send("city=Seoul&zipcode=06141");
서버에 비동기식 요청을 보내기 위해서는 open()
메소드의 세 번째 인수로 true
를 전달하면 된다. false
를 전달하는 경우 동기식 요청이 되어 자바스크립트는 서버로부터 응답이 도착할 때까지 대기하게 된다.
onreadystatechange
프로퍼티는 XMLHttpRequest
객체의 readyState
프로퍼티 값이 변할 때마다 자동으로 호출되는 함수를 설정한다.
이 함수는 서버에서 응답이 도착할 때까지 readyState
프로퍼티 값의 변화에 따라 총 5번 호출된다. 이 프로퍼티를 이용하면 서버에 요청한 데이터가 존재하고, 서버로부터 응답이 도착하는 순간을 특정할 수 있다.
UNSET
, OPENED
, HEADERS_RECIEVED
, LOADING
, DONE
document.getElementById("status").innerHTML = currentState;
if (httpRequest.readyState == XMLHttpRequest.DONE && httpRequest.status == 200 ) {
document.getElementById("text").innerHTML = httpRequest.responseText;
}
요청에 대한 응답이 완료(DONE
)되고 정상 응답(200
)인 경우 응답으로 받은 데이터를 문자열로 id
가 text
인 엘리먼트에 HTML에 삽입한다.
Ajax를 이용하여 개발을 손쉽게 할 수 있도록 미리 여러 가지 기능을 포함해 놓은 개발 환경을 Ajax 프레임워크라고 한다. 제이쿼리는 많이 사용되는 Ajax 프레임워크 중 하나이다.
제이쿼리는 Ajax와 관련된 다양하고도 편리한 메소드를 많이 제공하고 있는데, 그 중 가장 핵심적인 메서드는 $.ajax()
이다.
$.ajax([옵션])
$.ajax(
type : “post” or “get”,
url : “요청할 URL”,
data : { 서버로 전송할 데이터},
dataType : “서버에서 전송받을 데이터형식”,
success : function(서버로부터 데이터 받기){
// 정상 요청, 응답시 처리
},
error : function(오류정보){
// 오류 발생시 처리
}
);
Ajax를 사용하면 위와 같이 페이지 전체를 다시 로딩하지 않고도 화면을 전환할 수도 있고 서버에 요청을 보내 응답을 받아 처리할 수도 있다.
<script type="text/javascript">
$(document).ready(function () {
loadList();
});
function loadList() {
//서버와 통신 : 게시판 리스트 가져오기
$.ajax({
url: "boardList.do",
type: "get",
dataType: "json",
success: makeView,
error: function () {
alert("error");
}
});
}
</script>
사용자가 처음 사이트에 접속하면 main.jsp
로 이동한다. 페이지가 로딩되면 loadList()
함수가 호출되어 제이쿼리 $.ajax()
를 통해 서버에게 게시글 목록을 요청한다(@GetMapping
boardList.do
). 요청이 성공적으로 처리되는 경우(success
) makeView
함수가 호출된다.
function makeView(data) { //콜백 함수 : 서버에서 응답으로 받은 데이터(data)를 처리하는 함수
var listHtml = "<table class='table table-bordered'>"
listHtml += "<tr>";
listHtml += "<td>번호</td>";
listHtml += "<td>제목</td>";
listHtml += "<td>작성자</td>";
listHtml += "<td>작성일</td>";
listHtml += "<td>조회수</td>";
listHtml += "</tr>";
$.each(data, function (index, obj) {
//...
});
listHtml += "<tr>";
listHtml += "<td colspan='5'>";
listHtml += "<button class='btn btn-primary btn-sm' onclick='goForm()'>글쓰기</button>";
listHtml += "</td>";
listHtml += "</tr>";
listHtml += "</table>";
$("#view").html(listHtml); //view라는 id를 가진 div에 listHTML을 출력
}
makeView(data)
함수는 서버로부터 응답받은 데이터(data
)를 받아 게시글 목록을 표시하는 HTML을 작성해 listHTML
에 저장한다. 그리고 view
라는 이름을 가진 엘리먼트에 이 HTML을 삽입한다.
이러한 동작을 통해 사용자가 처음 페이지(/controller
)에 접속하면 게시글 목록을 볼 수 있게 되는 것이다.
<div class="panel-body" id="view">Panel Content</div>
<div class="panel-body" id="wform" style="display: none">
<form action="boardInsert.do" method="post"></form>
</div>
게시글 목록 뿐 아니라 게시글 등록 폼도 표시하기 위해서 main.jsp
는 두 개의 HTML body를 가지고 있다.
하나는 처음 페이지가 로딩되었을 때 게시글 목록을 보여주는 view
이다. 다른 하나는 게시글 입력 폼을 가지고 있는 wform
이다. wform
은 처음에 display: none
스타일을 가지고 있어서 표시되지 않는다.
function goForm() {
$("#view").css("display", "none"); //숨기기
$("#wform").css("display", "block"); //보이기
}
function goList() {
$("#view").css("display", "block"); //보이기
$("#wform").css("display", "none"); //숨기기
}
그러나 사용자가 글쓰기 버튼을 클릭하면 onclick='goForm()'
이 동작하여 view
바디가 숨겨지고 wform
바디가 표시되게 된다. 반대로 글쓰기 폼에서 리스트 버튼을 클릭하면 wform
바디를 숨기고 view
를 표시하는 goList()
함수가 호출되게 된다.
이러한 과정을 통해 한 페이지에서 글쓰기 목록과 글쓰기 화면을 전환할 수 있게 되었다.