AJAX
Ajax (Asynchronous Javascript and XML)
은 자바스크립트를 사용하여 브라우저가 서버에게 비동기 방식으로 데이터를 요청하고, 서버가 응답한 데이터를 수신하여 동적으로 갱신하는 프로그래밍 방식
을 말한다.
위 네이버 페이지의 이미지를 보면, 뉴스 창에서 뉴스의 목록만 변경 할 떄 변경되는 내용에 대해서만 서버 측에 요청을 보내는 모습을 볼 수 있다. 이는 Ajax
를 이용한 것이다.
HTML
파일이 페이지에 렌더링 되는 것은 클라이언트
가 서버측에 GET
요청을 보내 HTML
파일을 받아 렌더링 한다.
이 때 HTML
파일의 일부분만 변경 할 때 Ajax
가 나타나기 전에는 일부분이 변경되더라도 , 일부분이 변경된 전체 HTML
파일을 모두 받아 렌더링했었다.
이는 새로운 렌더링이 필요하지 않은 영역까지 요청하여 렌더링 했기 때문에
서버측에서는 불필요한 데이터 통신이 발생하고
사용자는 일부분만 변경해도 새로운 HTML
을 모두 렌더링 하는 동안 기다려야 하며, 렌더링으로 인해 화면이 깜박이는 현상이 발생한다. 또한 렌더링 되는 동안 다른 행위는 하지 못하는 블로킹
이 발생한다.
Ajax
는 2005년 구글 맵스에서 사용된 이후 폭발적으로 관심이 증가하였다.
하지만 Ajax
를 이용하면 변경이 필요한 부분에 대해서만 변경된 HTML
부분만 렌더링 하기 때문에
불필요한 데이터 통신이 일어나지도 않고 , 화면이 전체적으로 렌더링 되느라 깜박이는 현상이 발생하지 않는다.
또한Ajax
이름에서 나타나듯 비동기
적으로 처리되기 때문에 블로킹
현상도 발생하지 않는다.
JSON (Javascript Object Notation)
Ajax
를 이용하여 비동기적으로 렌더링 할 부분들에 대해서 미리 html
파일들을 만들어두는 방법도 존재하기도 하지만 JSON
이라는 자료구조를 이용하여 동적으로 렌더링 하는 방법을 자주 사용한다.
정의
JSON(제이슨[1], JavaScript Object Notation)은 속성-값 쌍(attribute–value pairs), 배열 자료형(array data types) 또는 기타 모든 시리얼화 가능한 값(serializable value) 또는 키-값 쌍으로 이루어진 데이터 오브젝트를 전달하기 위해 인간이 읽을 수 있는 텍스트를 사용하는 개방형 표준 포맷이다. 비동기 브라우저/서버 통신 (AJAX)을 위해, 넓게는 XML(AJAX가 사용)을 대체하는 주요 데이터 포맷이다. 특히 인터넷에서 자료를 주고 받을 때 그 자료를 표현하는 방법으로 알려져 있다. 자료의 종류에 큰 제한은 없으며, 특히 컴퓨터 프로그램의 변수값을 표현하는 데 적합하다.
출처 : 위키백과 - JSON
예시를 통해 JSON
의 생김새에 대해서 알아보자
{
"squadName" : "Super Hero Squad",
"homeTown" : "Metro City",
"formed" : 2016,
"secretBase" : "Super tower",
"active" : true,
"members" : [
{
"name" : "Molecule Man",
"age" : 29,
"secretIdentity" : "Dan Jukes",
"powers" : [
"Radiation resistance",
"Turning tiny",
"Radiation blast"
]
},
{
"name" : "Madame Uppercut",
"age" : 39,
"secretIdentity" : "Jane Wilson",
"powers" : [
"Million tonne punch",
"Damage resistance",
"Superhuman reflexes"
]
},
{
"name" : "Eternal Flame",
"age" : 1000000,
"secretIdentity" : "Unknown",
"powers" : [
"Immortality",
"Heat Immunity",
"Inferno",
"Teleportation",
"Interdimensional travel"
]
}
]
}
MDN
홈페이지에서 제공하는 JSON
파일이다. (JSON 링크)
생김새를 보면 마치 객체
처럼 데이터를 저장하고 있는 모습을 볼 수 있다.
JSON
은 데이터를 효과적으로 표현하고 전송하기 위한 간단하면서도 가벼운 데이터 교환 형식을 지원한다.
JSON
은 사람이 읽고 쓰기 쉬운 형식을 가지고 있으며 (객체처럼 생겼다
)
자바스크립트에서는 텍스트 형식인 JSON
파일을 자바스크립트 객체
로 변환 할 수 있기 때문에 개발자 입장에서는 JSON
데이터를 쉽게 다룰 수 있다.
Ajax
이름에XML
이 들어가는데 왜JSON
을 설명하나요
Ajax
는XML
뿐이 아니라 비동기적으로 데이터를 교환하는 방식을 의미한다.
JSON
이XML
에 비해 가독성이 좋고 간결하며 더 적은 크기를 가지고 있기 때문에 더 자주 사용된다.
그러니 그냥JSON
공부해 ~!!!
XMLHttpRequest
JSON
이 담긴 URL
에게 JSON
파일을 받기 위한 request
를 요청하려면 Web API
인 XMLHttpRequest
객체를 이용한다.
const request = new XMLHttpRequest();
생성자 함수로 XMLHttpRequest
객체를 생성하고, 생성된 객체의 프로퍼티와 메소드를 이용해 HTTP request
를 보낼 수 있다.
XMLHttpRequest
프로퍼티프로퍼티 | 설명 |
---|---|
onreadystatechange |
상태 변경 이벤트를 처리하는 이벤트 핸들러입니다. |
readyState |
요청의 현재 상태를 나타내는 값으로, 0부터 4까지의 값을 가집니다. |
response |
요청에 대한 응답 데이터를 나타냅니다. (읽기 전용) |
responseText |
응답 데이터를 문자열로 반환합니다. |
responseType |
응답 데이터의 형식을 나타내는 문자열로, "text", "json", "document" 등이 있습니다. |
status |
HTTP 상태 코드를 나타냅니다. |
statusText |
HTTP 상태 코드에 대한 설명을 나타냅니다. |
timeout |
요청이 지연되기 전에 대기할 시간(밀리초)을 나타냅니다. |
withCredentials |
크로스 오리진 요청일 때 인증 정보를 포함할지 여부를 나타냅니다. |
대표적인 프로퍼티들은 다음과 같다.
프로퍼티를 이용하여 request
를 보낼 XMLHttpRequest
객체의 요청 타입이나 요청 상태 등을 확인 할 수 있다.
XMLHttpRequest
의 프로토타입 메소드메서드 | 설명 |
---|---|
open(method, url, async) |
요청의 초기 설정을 수행합니다. HTTP 메서드, URL, 비동기 여부 등을 설정합니다. |
send(data) |
요청을 서버로 보냅니다. 데이터를 인자로 전달할 수 있습니다. |
setRequestHeader(header, value) |
HTTP 헤더를 설정합니다. 요청 전에 호출되어야 합니다. |
abort() |
현재의 HTTP 요청을 취소합니다. |
getAllResponseHeaders() |
응답에 포함된 모든 헤더를 반환합니다. |
getResponseHeader(header) |
특정 헤더의 값을 반환합니다. |
프로토타입 메소드를 통해 URL
주소로 요청을 보내기 위한 준비, 보내기, 취소 등을 할 수 있다.
XMLHttpRequest
의 이벤트 핸들러 프로퍼티프로퍼티 | 설명 |
---|---|
onreadystatechange |
readyState 속성이 변경될 때 호출되는 이벤트 핸들러를 설정하거나 반환합니다. |
onload |
요청이 성공적으로 완료될 때 호출되는 이벤트 핸들러입니다. |
onerror |
요청이 실패할 때 호출되는 이벤트 핸들러입니다. |
ontimeout |
타임아웃이 발생했을 때 호출되는 이벤트 핸들러입니다. |
onprogress |
요청이 진행 중일 때 주기적으로 호출되는 이벤트 핸들러입니다. |
이벤트 핸들러 프로퍼티는 다음과 같다.
사실 위의 3개를 달달달 외우기보다 실습하면서 복습해보자
XMLHttpRequest
실습하기사용하고자 하는 JSON
파일의 형태는 다음과 같다.
{
"squadName" : "Super Hero Squad",
"homeTown" : "Metro City",
"formed" : 2016,
"secretBase" : "Super tower",
"active" : true,
"members" : [
{
"name" : "Molecule Man",
"age" : 29,
"secretIdentity" : "Dan Jukes",
"powers" : [
"Radiation resistance",
"Turning tiny",
"Radiation blast"
]
},
...
Suepr Hero Squad
와 관련된 정보들이 담겨있으며 members
라는 키에는 배열로 된 값이 존재한다.
JSON
파일의 URL
은 MDN
에서 제공하는 URL
을 이용하기로 하자
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<button>request</button>
<header></header>
<section></section>
</body>
<script src="request.js"></script>
</html>
맨 처음 초기페이지의 경우에는 버튼만 딸랑 존재하며 해당 버튼을 누르면 JSON
파일이 담긴 URL
에 request
를 보내 JSON
파일을 파싱해오고, 파싱한 파일을 가지고 동적으로 렌더링해보자
Script
const $button = document.querySelector('button');
const request = new XMLHttpRequest();
const URL =
'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
버튼에 이벤트 핸들러를 장착하기 위해 버튼 태그를 설정하고
XMLRequestHttp
객체를 생성하자
sendRequest
const sendRequest = () => {
// HTTP 요청 초기화
request.open('GET', URL);
// HTTP 수신 설정
request.responseType = 'json';
// HTTP 요청 보내기
request.send();
};
버튼이 눌리면 요청을 보낼 콜백 함수를 생성했다.
.open(method , url)
프로토타입 메소드를 통해 요청을 보낼 URL
주소와 보낼 요청을 설정해준다.
이후 request
의 responseType
프로퍼티를 json
으로 설정해, 파싱해올 데이터가 JSON
형식임을 알려줘 파싱해올 때 자바스크립트의 객체 형식으로 변화 시킬 수 있도록 한다.
// 버튼이 눌리면 JSON 파일이 있는 URL에 GET 요청을 보내 JSON 파일을 가져옴
$button.addEventListener('click', () => {
if (request.readyState !== 0) return;
sendRequest();
});
버튼이 눌리면 해당 콜백 함수를 시행하고, 파싱해온 JSON
파일을 살펴보자
// 요청이 완료되면 파싱해온 객체를 로그하자
request.addEventListener('load', () => {
console.log(request.response);
});
요청이 완료되면 요청해온 값이 response
프로퍼티에 담기기 때문에
load
가 되면 로그하도록 이벤트 핸들러를 등록해주었다.
버튼이 눌리면 개발자 도구 - network
창에서 볼 수 있듯이 해당 json
파일을 가져오고
파싱해온 json
파일은 객체 형식으로 존재하는 모습을 볼 수 있다.
그럼 이제 객체 형식으로 파싱된 json
파일을 가지고 DOM
을 조작하여 페이지를 꾸밀 수 있다.
popularHeader , shwHeroes
// 기존 html 에 존재하는 header 태그 가져오기
const $header = document.querySelector('header');
// JSON의 프로퍼티로 접근하여 header에 내용 붙이기
const populateHeader = (jsonObj) => {
const $h1 = document.createElement('h1');
$h1.textContent = jsonObj.squadName;
$header.appendChild($h1);
const $p = document.createElement('p');
$p.textContent = `Hometown : ${jsonObj.homeTown} // Formed : ${jsonObj.formed} `;
$header.appendChild($p);
};
// JSON의 프로퍼티에 접근하여 article에 내용 붙이기
const showHeroes = (jsonObj) => {
const heroes = jsonObj.members; // json 내의 members의 프로퍼티 값은 유사배열 객체
const $section = document.querySelector('section');
[...heroes].forEach((hero) => {
const $div = document.createElement('div');
const $h2 = document.createElement('h2');
const $p1 = document.createElement('p');
const $p2 = document.createElement('p');
const $p3 = document.createElement('p');
const $ul = document.createElement('ul');
$h2.textContent = hero.name;
$p1.textContent = `Secret identity : ${hero.secretidentity}`;
$p2.textContent = `Age : ${hero.age}`;
$p3.textContent = 'SuperPowers:';
const superPowers = hero.powers; // hero.power 는 배열
superPowers.forEach((power) => {
const $li = document.createElement('li');
$li.textContent = power;
$ul.appendChild($li);
});
[$h2, $p1, $p2, $p3, $ul].forEach((tag) => $div.appendChild(tag));
$section.appendChild($div);
});
};
// 요청이 완료되면 요청한 불러온 JSON 파일을 이용하여 태그 생성하기
request.addEventListener('load', () => {
const superHeroes = request.response;
populateHeader(superHeroes);
showHeroes(superHeroes);
});
파싱해온 JSON
을 이용하여 동적으로 DOM
을 생성하고 페이지에 렌더링 해주었다.
DOM
을 조작하는 것이 해당 챕터의 주제는 아니기 때문에 자세히 쓰지는 않겠다.
다만 파싱된 JSON
은 자바스크립트의 객체
형식으로 오기 때문에 파싱해온 JSON
의 키와 값을 이용해
렌더링을 해줄 수 있었다.
위에서 Ajax
의 장점에 대해서 비동기 통신과 서버 부하 감소, UX
향상 등에 대해서도 말하였지만
그 뿐만 아니라
실시간으로 변하는 데이터를 렌더링 해야 하는 경우 (예를 들어 게시글, 댓글 등) 변한 데이터를 JSON
에 저장하고 변한 데이터만을 렌더링 하면 되기 때문에 실시간 업데이트가 가능하다.
JSON
다루기JSON
은 자바스크립트의 객체 형식과 매우 유사하며, 자바스크립트는 문자열 형식인 JSON
을 자바스크립트의 객체 형식으로 파싱해와 다루기 쉽게 만든다.
그럼 어떻게 할까 ?
JSON.stringify
JSON.stringify
는 객체를 JSON
포맷의 문자열로 변환한다.
이는 클라이언트가 서버로 객체를 전송하려면 객체를 문자열화 하여야 하는데 이를 직렬화
라고 한다.
const obj = {
name: 'lee',
age: 20,
alive: true,
hobby: ['soccer', 'bascketball'],
};
다음과 같은 객체가 있을 때
const json = JSON.stringify(obj);
console.log(json);
// {"name":"lee","age":20,"alive":true,"hobby":["soccer","bascketball"]}
다음과 같이 객체를 JSON
표기 방식에 맞게 직렬화 해준다.
매개변수를 보면 value
와 replacer
, space
가 존재한다.
value
는 직렬화 할 객체를 넣어주면 된다.
replacer
replacer
에는 콜백함수
나 배열
이 들어 갈 수 있다.
JSON.stringify
가 실행 될 때 콜백함수에는 key , value
값이 매개변수로 들어간다.
const replacer = (key, value) => {
if (key === 'name') return undefined;
if (typeof value === 'boolean') return undefined;
return value;
};
const json = JSON.stringify(obj, replacer);
console.log(json); // {"age":20,"hobby":["soccer","bascketball"]}
stringify
는 반환값이 undefined
가 아닌 값들에 대해서만 직렬화 하기 때문에 조건에 맞지 않는 값들은 JSON
형태로 저장되지 않은 모습을 볼 수 있다.
const json = JSON.stringify(obj, ['age', 'alive']);
console.log(json); // {"age":20,"alive":true}
배열 형태에선 배열에만 존재하는 key
값을 직렬화 한다.
space
space
인수는 json
문자열의 들여쓰기 정도를 나타낸다.
const json = JSON.stringify(obj, null, 2);
console.log(json);
/**
{
"name": "lee",
"age": 20,
"alive": true,
"hobby": [
"soccer",
"bascketball"
]
}
*/
JSON.parse
JSON.parse
는 반대로 문자열 형태의 JSON
을 자바스크립트 객체
타입으로 파싱한다.
const obj = {
name: 'lee',
age: 20,
alive: true,
hobby: ['soccer', 'bascketball'],
};
const json = JSON.stringify(obj, null, 4);
console.log(JSON.parse(json));
/**
{
name: 'lee',
age: 20,
alive: true,
hobby: [ 'soccer', 'bascketball' ]
}
*/
인수를 보면 reviver
이라는 값이 존재한다.
reviver
reviver
은 문자열을 파싱 할 때 속성에 대해 호출되며, 키와 값을 가지고 조건에 따라 객체로 변환 될 떼 값을 변경 할 수 있다.
const json = JSON.stringify(obj, null, 4);
const result = JSON.parse(json, (key, value) => {
if (value === true) return '살았지롱';
return value;
});
console.log(result);
/*
{
name: 'lee',
age: 20,
alive: '살았지롱',
hobby: [ 'soccer', 'bascketball' ]
}
*/