상세 컨텐츠

본문 제목

[Javascript / jQuery] Ajax

Web/JQuery

by 클리엘 클리엘 2020. 6. 30. 23:46

본문

1. Ajax 개요

 

Ajax는 웹브라우저가 서버와 통신하는 방식을 말합니다. 전통적인 웹브라우저의 동작 방식은 웹브라우저가 필요한 데이터를 서버에 요청하고 서버가 그 결과를 반환하면 웹브라우저가 결과를 받아 화면에 표시합니다. 이 과정에서 웹브라우저는 서버에 요청하고 서버의 응답을 받아 표시하는 과정에서 페이지 전환이 이루어지게 되는데 이때 사용자는 화면이 제대로 표시될 때까지 매번 기다려야 합니다.

 

뿐만 아니라 서버에서 결과를 받아 새롭게 표시해야 할 내용이 전체 페이지 내용 중에서 일부분에 불과한 경우에는 이 일부분의 결과를 표시하기 위해 페이지 전체를 새로 받아 표시해야 하므로 대역 팽나무 비도 초래하죠. 이 문제를 해결하고자 하는 통신방식이 바로 Ajax입니다.

 

예를 들어 티스토리 블로그에서 덧글을 달면 페이지 전체를 새로 가져오지 않더라도 필요한 부분(덧글)만 가져와 화면에 표시하게 됩니다. Ajax는 바로 이러한 동작을 가능하게 합니다.


2. 데이터 전송 포맷

 

Ajax는 통신방식입니다. 통신 방식을 Ajax로 구현하기로 결정했다면 이제 이 통신방식에서 어떤 포맷으로 데이터를 교환할지를 정해야 합니다. 현재는 크게 3가지 정도의 포맷이 활용되고 있습니다.

 

● CSV

 

CSV는 단순 문자열 형식입니다.

 

홍길동, 30세, 서울
홍길순, 32세, 대구
홍길남, 28세, 부산

 

위와 같은 단순 문자열은 곧 csv형식의 데이터가 될 수 있습니다. 아무런 추가사항도 필요 없고 딱 필요한 내용만 전송하기 때문에 전송 효 휼은 가장 좋습니다. 다만 이러한 포맷의 데이터를 상호 교환하기 위해서는 홍길동이나 서울과 같은 내용이 무엇을 의미하는지 대해 데이터를 교환하는 상호 간에 규칙이 정의되어 있어야 한다는 단점이 있습니다. 데이터 자체만 놓고 보면 각각의 항목이 무엇을 의미하는지 알 수 없기 때문입니다.

 

● XML

 

XML은 eXtensible Markup Language의 약자입니다. HTML 태그처럼 각각의 데이터에 의미를 부여하기 위한 태그를 붙여놓아 데이터만 보더라도 대략 무슨 의미의 데이터인지를 구분할 수 있게 합니다.

 

</members><?xml version="1.0" encoding="UTF-8" ?>
<members>
   <member>
       <name>홍길동</name>
       <age>30세</age>
       <address>서울</address>
   </member>
   <member>
      <name>홍길순</name>
      <age>32세</age>
      <address>대구</address>
   </member>
   <member>
      <name>홍길남</name>
      <age>28세</age>
      <address>부산</address>
   </member>
</members>

 

상기 에제와 같이 각 데이터가 의미하는 바가 무엇인지 명확하게 전달할 수 있습니다. 다만 각 항목마다 일일이 태그를 붙여야 하므로 데이터의 양이 그만큼 증가하게 됩니다. 범용적이고 의미론적인 면에서는 가장 좋지만 효 휼은 가장 떨어지는 방식으로 알려져 있습니다.

 

● JSON

 

위에서 언급한 CSV와 XML의 장점만을 취합한 것이 바로 JSON입니다.

 

[
   {
      "name":"홍길동",
      "age":"30세",
      "address":"서울"
   },
   {
      "name":"홍길순",
      "age":"32세",
      "address":"대구"
   },
   {
      "name":"홍길남",
      "age":"28세",
      "address":"부산"
   }
]

 

단순 문자열로 구성되어 있으면서도 각각의 항목에 의미를 부여하고 있습니다.

 

다만 JSON도 내용이 너무 많아지면 속도가 느려진다는 단점이 있습니다. JSON을 사용하는데 속도가 부담될 정도의 양이라면 CSV를 사용해야 합니다.


3. XMLHttpRequest

 

XMLHttpRequest객체는 웹서비스에 접근해 데이터를 가져오는 동작을 Ajax로 수행할 수 있도록 해주는 객체입니다. 우선 아래와 같이 간단한 html 파일을 생성하고

<!DOCTYPE html>
<html>
	<head>
	</head>
	<body>
		cliel.com
	</body>
</html>

XMLHttpRequest객체를 통해 해당 페이지 내용을 그대로 가져오는 기능을 만들어 보겠습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
	<script>
		$(function () {
			
		});

		var request = function() {
			var XHreq = new XMLHttpRequest();
			XHreq.open('get', '/test/sample.html', false);

			XHreq.send();

			alert(XHreq.responseText);
		};
	</script>
</head>
<body>
	<input type="button" onclick="javascript:request();" value="가져오기" />
</body>
</html>

new 키워드를 통해 XMLHttpRquest 객체를 생성한 다음 해당 객체의 open메서드로 데이터를 가져오고 있습니다. 이때 open() 메서드의 첫 번째 매개변수는 전송방식, 두 번째는 Ajax를 요청할 주소, 세 번째는 동기/비동기 여부를 의미합니다.

 

우선 전송방식으로 에제에서는 get을 사용했습니다. 물론 필요하다면 post, put, delete와 같은 요청을 수행할 수도 있습니다. 또한 open() 메서드의 마지막에 false를 지정했으므로 이 동작은 동기화로 동작하게 됩니다. 하지만 실제 웹브라우저에서는 다음과 같은 경고를 내기도 하는데

 

동기적으로 수행하면 경우에 따라 사용자가 화면을 조작하지 못하는 문제가 있을 수 있기 때문입니다. 실제로 가져와야 할 데이터가 너무 많거나 통신환경이 느린 여건에 처해 있다면 요청 후 응답이 올 때까지 기다려야 하는 동기방식에서는 프로그램이 멈춘 것처럼 보일 수 있습니다.

 

따라서 필요하다면 요청을 비동기로 수행해야 하는 경우도 있는데 이를 위해서는 open메서드의 마지막에 비동기 요청을 사용하겠다는 뜻으로 true를 넣어주면 됩니다.

var request = function() {
	var XHreq = new XMLHttpRequest();
	XHreq.open('get', '/test/sample.html', true); //캐싱처리가 필요하다면 '/test/sample.html' + new Date().getTime() 로 시간을 붙여주면 됩니다. 

	XHreq.send();

	alert(XHreq.responseText);
};

물론 경우에 따라 위의 코드를 실행하면 응답이 비어 있는 경우를 볼 수도 있습니다.

 

비동기는 응답이 올때까지 기다리지 않고 곧바로 다음 코드(alert(XHreq.responseText))를 수행해 버리기 때문입니다. 따라서 다음과 같이 onreadystatechange이벤트를 연결해 사용해야 합니다.

var request = function() {
	var XHreq = new XMLHttpRequest();
	XHreq.onreadystatechange = function(e) {
		if (XHreq.readyState == 4) {
			alert(XHreq.responseText);
		}
	};

	XHreq.open('get', '/test/sample.html', true);
	XHreq.send();
};

onreadystatechange 이벤트는 XMLHttpRequest객체의 상태가 바뀔 때마다 호출되며 때문에 readyState속성을 통해 현재 XMLHttpRequest의 상태가 어떤지를 확인하고 응답을 처리할 수 있도록 합니다. 만약 readyState속성의 값이 4라면 모든 데이터를 받았다는 것을 의미하므로 이때 필요한 처리를 수행하면 됩니다.

 

0 open() 메서드 호출전
1 send() 메서드 호출전
2 응답 데이터 없음
3 응답 데이터 일부 수신
4 응답 데이터 전체 수신

 

참고로 XMLHttpRequest객체의 status속성을 사용하면 요청을 수행하는 페이지의 응답 상태를 확인할 수도 있습니다.

var request = function() {
	var XHreq = new XMLHttpRequest();
	XHreq.onreadystatechange = function(e) {
		if (XHreq.readyState == 4) {
			if (XHreq.status == 200) {
				alert(XHreq.responseText);
			}
		}
	};

	XHreq.open('get', '/test/sample.html', true);
	XHreq.send();
};

HTTP 응답 코드는 아래 표를 참고해 주세요.

 

100 처리 중 100 Continue
200 정상 200 OK
300 리다이렉트 300 Multiple Choices
400 잘못된 요청 400 Bad Request
500 서버 오류 500 Server Error

 

만약 응답받는 데이터가 json형태라면 JSON.parse() 메서드로 받을 수 있습니다. sample.html을 위에 데이터 전송 포맷에서 언급한 json예시로 수정하고 XHreq.responseText를 JSON.parse()로 받을 수 있게 다음과 같이 변경합니다.

var request = function() {
	var XHreq = new XMLHttpRequest();
	XHreq.onreadystatechange = function(e) {
		if (XHreq.readyState == 4) {
			if (XHreq.status == 200) {
				var json = JSON.parse(XHreq.responseText);

				var tag = '<ul>';
				for (var i = 0; i < json.length; i++) {
					tag += '<li>' + json[i].name + '-(' + json[i].age + ')' + '</li>';
				}
				tag += '</ul>';

				document.body.innerHTML = tag;
			}
		}
	};

	XHreq.open('get', '/test/sample.html', true);
	XHreq.send();
};

응답 데이터가 XML 형식이라면 HTML에서 요소를 다룰 때 사용하던 것과 비슷한 메서드를 통해 XML요소를 가져올 수 있습니다. sample.xml로 위에서 제시된 XML 포맷으로 새로운 파일을 생성하고 응답 내용을 다음과 같이 수정합니다.

var request = function() {
	var XHreq = new XMLHttpRequest();
	XHreq.onreadystatechange = function(e) {
		if (XHreq.readyState == 4) {
			if (XHreq.status == 200) {
				var xml = XHreq.responseXML;

				var names = xml.getElementsByTagName('name');
				var ages = xml.getElementsByTagName('age');

				var tag = '<ul>';
				for(var i = 0; i < names.length; i++) {
					tag += '<li>' + names[i].childNodes[0].nodeValue + '-(' + ages[i].childNodes[0].nodeValue + ')</li>';
				}
				tag += '</ul>';

				document.body.innerHTML = tag;
			}
		}
	};

	XHreq.open('get', '/test/sample.xml', true);
	XHreq.send();
};

reponseXML로 XML 형식의 데이터를 응답받고 getElementsByTagName메서드로 각 요소의 데이터를 가져오고 있습니다.

 

참고로 post전송을 해야 한다면 get대신 post를 사용하면 되는데 post나 put의 경우 필요한 데이터를 요청 URL 쪽에 보내야 하므로 setRequestHeader메서드로 헤더를 붙이고 send() 메서드에서 데이터를 실어 보내면 됩니다.

var request = function() {
	var XHreq = new XMLHttpRequest();

	var id = 'userid';
	var pw = 'userpw';

	XHreq.onreadystatechange = function(e) {
		if (XHreq.readyState == 4) {
			if (XHreq.status == 200) {
				var res = XHreq.responseText;
				document.body.innerHTML = res;
			}
		}
	};

	XHreq.open('post', '/test/sample.xml', true);
	XHreq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
	XHreq.send('id=' + id +'&pw=' + pw);
};

4. jquery AJAX

 

jquery를 통해 AJAX를 수행하기 위한 가장 기본적인 메서드는 ajax() 메서드이며 XMLHttpRequest객체를 내부적으로 생성해 AJAX동작을 수행합니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
	<script>
		$(function () {
			$.ajax('/test/sample.html', {
				success: function (data) {
					alert(data);
				}
			});
		});
	</script>
</head>
<body>
</body>
</html>

예제에서는 ajax의 첫 번째 매개변수로 데이터를 가져올 URL을 지정하고 두 번째 매개변수로 옵션 객체를 설정했습니다. 참고로 ajax메서드는 필요한 매개변수 전체를 옵션 객체로 설정할 수도 있습니다.

$(function () {
	$.ajax({
		url: '/test/sample.html',
		success: function (data) {
			alert(data);
		}
	});
});

예제에서 옵션 객체는 데이터를 성공적으로 가져왔을 때(success) 지정한 메서드를 실행하도록 했습니다.

 

물론 이외에 다음과 같은 여러 옵션을 지정할 수도 있습니다.

 

async 동기, 비동기 여부를 지정합니다.
data 요청 데이터를 설정합니다.
error 에러 발생시 처리부분을 지정합니다.
success 성공했을때 처리부분을 지정합니다.
timeout 만료시간을 지정합니다.
type GET / POST등 요청방식을 설정합니다.
url 대상 URL을 지정합니다.

 

$(function () {
	$.ajax({
		url: '/test/sample.html',
		type: 'POST',
		data: {
			id: 'test',
			pw: 'test123'
		},
		success: function (data) {
			alert(data);
		}
	});
});

또한 JQuery에서는 ajax() 메서드 이외에 상황에 맞는 추가적은 메서드를 제공하고 있습니다.

$(function () {
	$.get('/test/sample.html', function (data) {
		alert(data);
	});
});

예제는 get() 메서드를 통해 AJAX를 수행하도록 합니다. ajax() 메서드에서 type을 get으로 지정한 것과 마찬가지 메서드입니다. 동일한 방법으로 post() 메서드를 사용할 수도 있으며 json데이터를 가져오는 getJSON() 메서드도 존재합니다. getJSON() 메서드를 사용하면 간략하게 JSON 데이터를 다룰 수 있습니다.

$(function () {
	$.getJSON('/test/sample.html', function (data) {
		$.each(data, function(key, value) {
			alert('key : ' + key + '--' + 'value : ' + value.name);
		});
	});
});

특정 요소에 결과를 채워야 하는 경우에는 요소.load() 메서드를 사용할 수 있습니다. 이때 load() 메서드에 두 번째 매개변수를 이용하면 필요한 데이터 값을 첫 번째 매개변수에서 지정한 url로 전송할 수 있습니다.

$(function () {
	$('div').load('/test/sample.html');
});

※ 예제는 상기 HTML, JSON, XML에제를 사용했습니다.

 

JQuery에서는 getJSON()처럼 JSON포맷을 위한 전용 메서드를 제공하지만 XML은 별도의 메서드가 없습니다. 그래서 ajax로 데이터를 요청하고 결과를 가져와 XML 데이터를 분해해야 합니다.

$(function () {
	$.ajax({
		url: '/test/sample.xml',
		type: 'GET',
		success: function (data) {
			$(data).find('member').each(function () {
				alert($(this).find('name').text() + '---' + $(this).find('age').text());
			});
		}
	});
});

예제에서 처럼 XML요소의 데이터 값을 가져오기 위해서는 find로 요소를 찾아야 합니다.

 

5. 데이터 전송

 

AJAX를 통해 데이터를 불러오는 경우 대부분은 필요한 데이터를 전송하는 동작을 포함합니다. 예컨대 게시판에서 덧글 작성하는 부분을 AJAX로 구현한다면 먼저 작성한 덧글을 전송하고 현재 덧글 목록을 받아오는 식입니다.

 

jQuery에서는 바로 이런 경우 AJAX구현 시 데이터 전송을 좀 더 편리하게 구현할 수 있도록 하기 위해 serialize() 메서드를 지원하고 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title></title>
	<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
	<script>
		$(function () {
			$('div').load('/test/sample.html', $(this).serialize());

			event.preventDefault();
		});
	</script>
</head>
<body>
	<div>
		입력 : <input type="text" id="comment" name="comment" /><br />
		<input type="submit" value="전송" />
	</div>
</body>
</html>

위와 같이 하면 sample.html 쪽으로 'comment=[입력값]' 형태의 쿼리 문자열을 생성해 전송하게 됩니다. 혹은

$(function () {
	$('div').load('/test/sample.html', $(this).serializeArray());

	event.preventDefault();
});

처럼 serializeArray() 메서드를 사용하는 경우도 있는데 serialize() 메서드는 쿼리 문자열의 형태를 가지지만 serializeArray() 메서드는 필요한 데이터를 다음과 같은

[
    { name: 'comment', value: '[입력값]'
]

객체 형태를 가진다는 차이가 있습니다. 둘 중 무엇을 사용해도 괜찮습니다.

 

참고로 객체를 쿼리 문자열로 변환하고자 한다면 $.param() 메서드를 사용할 수 있습니다.

var data = {
	name: 'comment',
	value: 'abc'
};

alert($.param(data));

6. 이벤트 처리

 

jQuery에서는 AJAX처리과정에서 특정 메서드를 실행할 수 있는 연결 메서드를 제공하고 있습니다. 이를 이용하면 처리시간이 오래 걸리는 요청의 경우 사용자에게 대기 표시를 하는 등, 여러 가지 유용한 처리를 추가할 수 있으며 다음과 같은 메서드를 사용할 수 있습니다.

 

ajaxComplete() 요청 완료시 실행
ajaxError() 요청 실패시 실행
ajaxSend() 요청 보낼때 실행
ajaxStart() 요청을 시작할때 실행
ajaxStop() 요청이 중지될때 실행
ajaxSuccess() 요청 성공시 실행
$(function () {
	$(document).ajaxComplete(function() {
		alert('처리를 완료하였습니다.');
	});

	$.ajax({
		url: '/test/sample.xml',
		type: 'GET',
		success: function (data) {
			$(data).find('member').each(function () {
				alert($(this).find('name').text() + '---' + $(this).find('age').text());
			});
		}
	});
});

만약 여러 이벤트를 섞어서 사용하는 경우라면 대략 Start, Send, Success, Complete 순으로 이벤트가 실행될 것입니다.

'Web > JQuery' 카테고리의 다른 글

[jQuery] 쿠키(Cookies)  (0) 2020.07.06
[Javascript / jQuery] Ajax  (0) 2020.06.30
[jQuery] 전역함수  (0) 2020.06.17
[jQuery] 효과  (0) 2020.06.16
[jQuery] 이벤트 다루기  (0) 2020.06.11
[jQuery] 요소 조작 메서드  (0) 2020.06.07

태그

관련글 더보기

댓글 영역