동음이의어에 대한 내용은 Ajax(동음이의어) 문서 참고하십시오.
1. 개요
Ajax는 Asynchronous JavaScript and XML' 또는 'Asynchronous JavaScript transfer (x-fer)'의 약자[1]이다. 말 그대로 JavaScript와 XML 형식을 이용한 비동기적 정보 교환 기법이다.개념적으로 1999년 3월에 이미 정립되어 있었지만 Ajax란 용어 자체는 2005년 2월 18일 Jesse James Garrett에 의해 처음 소개되었다. 이름에 XML이 포함되어있긴 하지만 JSON 형식이나 일반 텍스트와 같은 다른 데이터 오브젝트들도 사용 가능해서 요즘엔 XML을 잘 사용하지 않고 대부분 JSON 형식을 다룬다. 용어와 실제 기술간의 차이가 커져서 요즘에는 약어가 아닌 고유명사 취급하고 있다.
발음은 '에이-잭스(IPA: /ˈeɪ.d͡ʒæks/)'라고 한다. Ajax가 한국에 알려진 초창기에 축구에 관심있던 사람들은 AFC 아약스를 따라 '아약스'로 부르거나 '아작스', '에이작스'로 부르는 경우도 있었다.
2. 역사
Ajax가 등장하기 이전에는 웹 브라우저가 어떤 정보를 요청하면 서버는 해당 정보를 포함한 페이지 전체를 전달해 주었다. 웹 브라우저는 서버로부터 받은 마크업 데이터(HTML)를 브라우저 창에 렌더링하는 일을 했다. 사실 이 방법은 웹 브라우저에게도, 서버에게도 서로 불편했는데 브라우저는 매번 똑같은 레이아웃의 페이지를 처음부터 다시 렌더링해야 했고 서버 역시 매번 같은 페이지를 렌더링(이 경우에는 HTML 파일 생성)해야 해서 서로 부담이 되었다. Ajax 기술을 사용하지 않는 사이트가 특유의 깜빡거림 현상이 생기는 이유가 매번 페이지를 싹 지우고 처음부터 다시 모든 것을 그려내기 때문이다. 이를 보완하기 위해 프레임을 썼지만, 수많은 부작용을 만들어냈다.Ajax는 웹 페이지의 디자인 요소와 정보 요소를 분리한다. 처음 사이트에 접속하면 웹 서버는 해당 페이지의 스타일과 레이아웃을 정의하는 정적 HTML 파일과 CSS 파일, 그리고 데이터를 어떻게 요청하면 되는지를 설명한 JavaScript 파일을 전달한다. 브라우저는 일단 이 내용으로 페이지의 기본적인 골격을 구축해 놓는다. 그리고 골격의 구축이 끝나면 브라우저는 전달받은 JavaScript를 실행해서 서버에 데이터만을 별도로 요청한다. 이 때 서버에서 주는 응답은 순수한 데이터 객체 즉 XML 또는 JSON 데이터이다.[2] 브라우저가 이 데이터를 수신하면 미리 만들어 둔 틀 안에 적절한 방법으로 데이터를 끼워 넣는다.
과거 이런 식의 HTTP 프로토콜을 이용한 비동기 통신은 Ajax라는 용어만 없었을 뿐, 지금 사람들이 생각하는 것과 다르게 MS가 Ajax같은 기능을 유일하게 제공하고 있었다.
MS는 1999년 3월에 발표된 Internet Explorer 5부터 도입된 독자 규격인 MSXML 2.0에 포함된 'Microsoft.XMLHTTP'라는 컴포넌트가 현재의 Ajax와 거의 동일한 개념으로써 유일하게 제공하고 있었다. 이 컴포넌트는 브라우저의 고유스펙이 아닌 윈도우에 탑재된 ActiveX를 호출해서 써야 하는 비표준 기술이며, 무거운 http로 무거운 XML을 받아온다는 사실에[3] 아무도 거들떠 보지 않는 기술이었다.
그러던 와중에 1998년쯤 네오위즈의 세이클럽이 실시간 채팅을 구현하기 위해 페이지 리플래시나 hidden iframe 트릭 같은 것들[4] 대신 아무도 안 쓰던 이 기술을 사용하게 된다. 당시 IE의 경쟁 웹 브라우저였던 Netscape는 이런 기술을 지원하지 않았기 때문에 세이클럽은 어쩔 수 없이 IE 전용으로만 이용이 가능하였다.
시간이 흘러 Netscape의 피를 이어받은 모질라가 2000년 12월 6일에 Firefox에 사용된 엔진 중 하나인 Gecko 0.6 버전에 XMLHttpRequest 매서드가 추가되었지만 2002년 6월 5일에 발표된 Gecko 1.0 버전부터 본격적으로 사용되었고, 사파리 2004년 2월 1.2 버전부터, 오페라는 2005년 4월부터 연달아 도입되었다.
다른 웹 브라우저들이 XMLHttpRequest를 도입할 즈음에 구글은 2004년 4월 1일에 발표된 Gmail, 2005년 2월 8일에 발표된 구글 지도가 아무런 플러그인 없이 Ajax로 구현된 웹 애플리케이션으로 밝혀지면서 화제거리가 되었다. 구글 지도의 발표로부터 열흘 뒤 Jesse James Garrett가 이러한 비동기 통신을 "웹 애플리케이션에 대한 새로운 접근 방식, Ajax"라고 부르면서 짧은 글자와 쉬운 발음 덕분에 점차 고유명사처럼 굳어졌다.
특히, 구글 지도가 막 나왔을 때의 충격적인 반응은 국내에서 더욱 두드러졌는데, 당시 한국의 지도 서비스는 열이면 열 ActiveX 기반이었기 때문이다. ActiveX 없이 지도 같은 서비스가 구현된다는 사실이 국내에서는 큰 충격으로 다가왔고, 국내에서는 너도나도 지도를 Ajax 기반으로 바꾸었다.
Ajax 기술은 현대 웹 사이트를 지탱하는 근간(코어) 기술이 된 지 오래이기 때문에 여러 서드 파티 라이브러리가 나와 있으며 대규모 웹 프레임워크는 아예 Ajax 기능을 내장하고 있기도 하다. axios나 Oboe 라이브러리 같이 비동기 HTTP 요청만 전문적으로 처리하는 라이브러리들이 있다.
요즘은 XMLHttpRequest를 보완한 Promise, Async/Await과 같은 비동기 방식의 Fetch API를 주로 사용한다.
3. 원리
- 브라우저가 사이트에 접속하면 서버는 사이트의 기본 얼개를 담은 '템플릿'을 전달한다.
- 브라우저는 수신받은 템플릿 HTML과 CSS를 해석해 화면의 기본 모양을 그린다.
- 계속해서 서버는 데이터의 요청 방식과 수신받은 데이터를 어떻게 가공해야 하는지를 기술한 자바스크립트 파일을 전달한다.[5]
- 브라우저는 자바스크립트 파일을 해석해서 파일에 기술된 방식대로 서버에 추가 데이터를 요청한다.
- 서버는 순수 데이터를 응답으로 되돌려준다.
- 브라우저는 수신한 데이터를 해석하여 템플릿의 적절한 위치에 삽입한다. 데이터의 가공 방식에 따라 삽입 외의 작업(변경, 삭제)을 할 수도 있다.
4. 단점
Ajax 는 동적 페이지 렌더링을 하기 때문에 자바스크립트를 해석하지 못하는 검색 엔진에서는 내용이 검색되지 않는다는 문제가 있다.[6] 일단 구글은 Ajax 기반의 웹 사이트도 읽을 수 있다.레이아웃이 너무 복잡한 사이트는 웹 브라우저가 렌더링하는 데 힘겨워할 수도 있다. 또는 아주 신속하게 첫 화면을 보여 줄 필요가 있는 경우에도 Ajax는 최소 두 번의 데이터 요청(일반적으로 4회 이상. HTML, CSS, JS 로딩 후 Ajax call 1회)을 해야 한다는 문제가 있다.(속도 저하가 필연적으로 발생한다.) 이런 경우에는 의도적으로 옛 방식 그대로 서버가 모든 페이지를 그려서 전달한다. '서버 사이드 렌더링'이라는 새로운 포장(?)을 두르고 있는데 결국 옛 기술의 현대적 재해석이다.
JavaScript를 반드시 써야 한다. 모든 웹 브라우저에서 공통으로 지원되는 프로그래밍 언어는 아직까지는 자바스크립트 단 하나뿐이다. 따라서 브라우저에서 자바스크립트를 꺼 버리면 Ajax 기반 사이트는 화면의 일부만 그려진다. 특히 쓸모 있는 정보는 전혀 없는 화면이 그려진다. 스크립팅 기능이 제한되는 특수 목적 기기에서는 이게 문제가 될 수 있다. 예를 들어 디지털 액자 같은 초저성능 임베디드 기기에서는 자바스크립트 엔진을 돌릴 여건이 안 될 수도 있다.
htmx라이브러리를 이용하면 html 태그 만으로도 간단히 ajax가 구현이 가능하지만 이것 역시도 어쨋거나 javascript로 만들어진 라이브러리가 브라우저 뒤에서 몰래 일을 해주는 것일 뿐이다.
5. 예제
아래의 예제에서는 모두 "//namu.wiki/raw/틀:틀%20모음/" 의 내용을 가져와서 뿌려주는 자바스크립트 코드이다.5.1. Vanilla JS
플러그인 없이, 자바스크립트만을 사용한 예제이다.XMLHttpRequest를 사용한 예제
#!syntax xml
<html>
<head>
<script type="text/javascript">
var request = new XMLHttpRequest(); // XMLHttpRequest 생성
request.open("GET", "//namu.wiki/raw/틀:틀%20모음/"); // 데이터를 GET Method로 요청
request.send(); // 실제 Send
request.onreadystatechange = function() {
if ( request.readyState == 4 && request.status == 200 ) { // request가 끝났으며(4), 성공적(200)인 경우. request.onload=()=>{} 으로 교체해도 가능하다.
document.getElementById("content").innerHTML = request.responseText; // #content 태그 내의 내용을 받아온 텍스트로 교체.
}
};
</script>
</head>
<body>
<div id="content"></div>
</body>
</html>
Fetch API 사용 예제
#!syntax xml
<html>
<head>
<script type="text/javascript">
fetch("//namu.wiki/raw/틀:틀%20모음/") // fetch API로 데이터를 요청
.then((response) => {
if (response.ok) { // HTTP Status가 성공적인 (200 등) 경우
return response.text(); // Response Body를 text로 꺼내옴
} else { // 4xx/5xx 에러로 요청 실패
return Promise.reject(`Error code ${response.status}`);
}
}).then((text) => {
document.getElementById("content").innerHTML = text; // #content 태그 내의 내용을 받아온 텍스트로 교체.
}).catch(() => { // 네트워크 문제일 경우만 reject됨
console.warn('network problem');
});
</script>
</head>
<body>
<div id="content"></div>
</body>
</html>
5.2. jQuery
jQuery를 이용한 예제이다. $.ajax 함수를 이용해서 자체적인 Ajax를 지원해주기 때문에, 기본적인 설정과 콜백 함수만 넣어주면 간단히 작동된다.#!syntax xml
<html>
<head>
<script type="text/javascript">
$.ajax({
url: "//namu.wiki/raw/틀:틀%20모음/",
method: "GET",
dataType: "text",
success: function(data) {
$("#content").html(data);
}
})
</script>
</head>
<body>
<div id="content"></div>
</body>
</html>
6. 대체/보완 기술
Ajax 는 비동기 데이터 전송 기술이지만 '양방향' 기술이 아니며 또한 '요청-응답' 사이클이 지나고 나면 통신 소켓을 닫아버린다는 문제가 있다. 따라서 완전한 실시간 통신을 지원하기 위해 웹 소켓이라는 새로운 기술이 구현되었다. 웹 소켓은 요청-응답 사이클이 지나도 통신 소켓을 닫지 않고 계속해서 요청을 송수신할 수 있도록 기존의 HTTP프로토콜에 약간의 변형을 가한다.웹 소켓이 TCP에 기반하고 있어 대규모 실시간 데이터 전송에 적합하지 않기 때문에 UDP에 기반한 WebRTC라는 기술이 구현되었다. WebRTC는 여기서 한 발 더 나아가 서버의 중개를 필요로 하지 않는 브라우저간 P2P 통신 채널을 형성하는 기능도 가지고 있다.
자세한 내용은 웹소켓 문서 참고하십시오.
Ajax 기술 위에서 구현된 실시간 통신 기술로 Long polling 기술이 있다. Long polling 은 서버에 요청을 보내면 서버는 즉시 응답을 주는 게 아니라 새로운 정보가 갱신될 때까지 소켓을 열어둔 채 응답을 미룬다. 그러다 새로운 정보가 들어오면 그 때 열려 있는 소켓을 통해 응답을 돌려주며 클라이언트(웹 브라우저)는 응답을 받는 즉시 새로운 요청을 서버에 날린다. 이렇게 해서 '응답하면 통신 채널이 닫히는' 문제를 우회한다. Socket.io 라이브러리의 웹 소켓 대체 모드가 이 Long polling 방식으로 이루어진다. 웹 소켓이 지원되지 않는 브라우저가 감지되면 Socket.io는 이 Long polling 방식으로 통신 방식을 바꾼다.
Polling 과 Long polling 의 차이점은, Polling은 갱신된 정보가 없으면 서버가 '갱신된 정보 없음'이라는 응답을 즉시 돌려주지만 Long polling은 갱신된 정보가 없을 경우 사전에 약속한 시간(수 초에서 수십초)까지 기다려보고 그래도 갱신된 정보가 들어오지 않으면 '갱신된 정보 없음'이라는 응답을 돌려준다.[7] 물론 요청을 받은 시점에 갱신된 정보가 있거나 기다리던 도중에 새로운 정보가 들어오면 그 즉시 갱신된 정보를 응답으로 돌려준다. 요청자(브라우저) 입장에서의 Long polling 은 '특정 시간 간격'으로 요청을 보내는 대신 '서버에서 응답이 돌아오는 즉시' 새로운 요청을 보내는 것으로 바뀐다. 이건 the seed의 스레드에도 적용되어 있는데, F12를 눌러 개발자 창을 열고, 아무 토론이나 들어가면 xhr로 Long polling 실시간 갱신을 하고 있는 것을 볼 수 있다.
7. 기타
[1] 약자인 AJAX가 아닌 고유명사로 취급하므로 Ajax로 표기한다.[2] 사실 어떠한 데이터 객체도 전달받을 수 있다. 텍스트 데이터가 아닌 데이터도 Ajax로 보낼 수 있다.[3] 지금 우리가 쓰고 있는 Ajax와 달라진게 없다.[4] 당시 IE는 이걸로 구현하면 딱딱 소리가 나기 때문에 사용감에 불편함을 줬다.[5] 정확히는 위에서 수신받은 템플릿 HTML파일 안에 이 자바스크립트 파일을 추가로 요청하라는 지시가 적혀 있으며 브라우저는 이 지시에 따라 서버에 해당 파일을 요청한다.[6] 이전에 쓰였던 프레임과 단점을 공유한다.[7] 통신이 끊어진 상태와 구분하기 위해 최대 대기시간이 정해져 있다. 이 시간을 초과하면 브라우저는 자체적으로 타임아웃 에러를 발생시킨다.