Ajax(Asynchronous JavaScript and XML)λ μλ°μ€ν¬λ¦½νΈλ₯Ό μ¬μ©νμ¬ λΈλΌμ°μ κ° μλ²μκ² λΉλκΈ° λ°©μμΌλ‘ λ°μ΄ν°λ₯Ό μμ²νκ³ , μλ²κ° μλ΅ν λ°μ΄ν°λ₯Ό μμ νμ¬ μΉνμ΄μ§λ₯Ό λμ μΌλ‘ κ°±μ νλ νλ‘κ·Έλλ° λ°©μμ λ§νλ€. Ajaxλ λΈλΌμ°μ μμ μ 곡νλ Web APIμΈ XMLHttpRequest κ°μ²΄λ₯Ό κΈ°λ°μΌλ‘ λμνλ€. XMLHttpRequestλ HTTP λΉλκΈ° ν΅μ μ μν λ©μλμ νλ‘νΌν°λ₯Ό μ 곡νλ€.
Ajaxμ μ₯μ μ λμννλ©΄ λ€μκ³Ό κ°λ€.
JSON(JavaScript Object Notation)μ ν΄λΌμ΄μΈνΈμ μλ² κ°μ HTTP ν΅μ μ μν ν μ€νΈ λ°μ΄ν° ν¬λ§·μ΄λ€. μλ°μ€ν¬λ¦½νΈμ μ’ μλμ§ μλ μΈμ΄ λ 립ν λ°μ΄ν° ν¬λ§·μΌλ‘ λλΆλΆμ νλ‘κ·Έλλ° μΈμ΄μμ μ¬μ©ν μ μλ€.
JSONμ μλ°μ€ν¬λ¦½νΈμ κ°μ²΄ 리ν°λ΄κ³Ό μ μ¬νκ² ν€μ κ°μΌλ‘ ꡬμ±λ μμν ν μ€νΈλ€. JSONμ ν€λ λ°λμ ν°λ°μ΄νλ‘ λ¬Άμ΄μΌ νλ©° κ°μ κ°μ²΄ 리ν°λ΄κ³Ό κ°μ νκΈ°λ²μ κ·Έλλ‘ μ¬μ©ν μ μλ€. νμ§λ§ λ¬Έμμ΄μ λ°λμ ν°λ°μ΄νλ‘ λ¬Άμ΄μΌ νλ€.
{
"name": "Lee",
"age": 20,
"alive": true,
"hobby": ["traveling", "tennis"]
}
JSON.stringify λ©μλλ κ°μ²΄λ₯Ό JSON ν¬λ©§μ λ¬Έμμ΄λ‘ λ°ννλ€. ν΄λΌμ΄μΈνΈκ° μλ²λ‘ κ°μ²΄λ₯Ό μ μ‘νλ €λ©΄ κ°μ²΄λ₯Ό λ¬Έμμ΄νν΄μΌ νλλ€. μ΄λ₯Ό μ§λ ¬ν(serializing)λΌ νλ€.
const obj = {
name: 'Lee',
age: 20,
alive: true,
hobby: ['traveling', 'tennis']
};
// κ°μ²΄λ₯Ό JSON ν¬λ§·μ λ¬Έμμ΄λ‘ λ³ννλ€.
const json = JSON.stringify(obj);
console.log(typeof json, json);
// string {"name":"Lee","age":20,"alive":true,"hobby":["traveling","tennis"]}
// κ°μ²΄λ₯Ό JSON ν¬λ§·μ λ¬Έμμ΄λ‘ λ³ννλ©΄μ λ€μ¬μ°κΈ° νλ€.
const prettyJson = JSON.stringify(obj, null, 2);
console.log(typeof prettyJson, prettyJson);
/*
string {
"name": "Lee",
"age": 20,
"alive": true,
"hobby": [
"traveling",
"tennis"
]
}
*/
// replacer ν¨μ. κ°μ νμ
μ΄ Numberμ΄λ©΄ νν°λ§λμ΄ λ°νλμ§ μλλ€.
function filter(key, value) {
// undefined: λ°ννμ§ μμ
return typeof value === 'number' ? undefined : value;
}
// JSON.stringify λ©μλμ λ λ²μ§Έ μΈμλ‘ replacer ν¨μλ₯Ό μ λ¬νλ€.
const strFilteredObject = JSON.stringify(obj, filter, 2);
console.log(typeof strFilteredObject, strFilteredObject);
/*
string {
"name": "Lee",
"alive": true,
"hobby": [
"traveling",
"tennis"
]
}
*/
JSON.stringify λ©μλλ κ°μ²΄λΏλ§ μλλΌ λ°°μ΄λ JSON ν¬λ§·μ λ¬Έμμ΄λ‘ λ°ννλ€.
const todos = [
{ id: 1, content: 'HTML', completed: false },
{ id: 2, content: 'CSS', completed: true },
{ id: 3, content: 'Javascript', completed: false }
];
// λ°°μ΄μ JSON ν¬λ§·μ λ¬Έμμ΄λ‘ λ³ννλ€.
const json = JSON.stringify(todos, null, 2);
console.log(typeof json, json);
/*
string [
{
"id": 1,
"content": "HTML",
"completed": false
},
{
"id": 2,
"content": "CSS",
"completed": true
},
{
"id": 3,
"content": "Javascript",
"completed": false
}
]
*/
JSON.parse λ©μλλ JSON ν¬λ§·μ λ¬Έμμ΄μ κ°μ²΄λ‘ λ³ννλ€. μλ²λ‘λΆν° ν΄λΌμ΄μΈνΈμκ² μ μ‘λ JSON λ°μ΄ν°λ λ¬Έμμ΄μ΄λ€. μ΄ λ¬Έμμ΄μ κ°μ²΄λ‘μ μ¬μ©νλ €λ©΄ JSON ν¬λ§·μ λ¬Έμμ΄μ κ°μ²΄ν ν΄μΌ νλλ° μ΄λ₯Ό μμ§λ ¬ν(deserializing)λΌ νλ€.
const obj = {
name: 'Lee',
age: 20,
alive: true,
hobby: ['traveling', 'tennis']
};
// κ°μ²΄λ₯Ό JSON ν¬λ§·μ λ¬Έμμ΄λ‘ λ³ννλ€.
const json = JSON.stringify(obj);
// JSON ν¬λ§·μ λ¬Έμμ΄μ κ°μ²΄λ‘ λ³ννλ€.
const parsed = JSON.parse(json);
console.log(typeof parsed, parsed);
// object {name: "Lee", age: 20, alive: true, hobby: ["traveling", "tennis"]}
λ°°μ΄μ΄ JSON ν¬λ§·μ λ¬Έμμ΄λ‘ λ³νλμ΄ μλ κ²½μ° JSON.parseλ λ¬Έμμ΄μ λ°°μ΄ κ°μ²΄λ‘ λ³ννλ€. λ°°μ΄μ μμκ° κ°μ²΄μΈ κ²½μ° λ°°μ΄μ μμκΉμ§ κ°μ²΄λ‘ λ³ννλ€.
const todos = [
{ id: 1, content: 'HTML', completed: false },
{ id: 2, content: 'CSS', completed: true },
{ id: 3, content: 'Javascript', completed: false }
];
// λ°°μ΄μ JSON ν¬λ§·μ λ¬Έμμ΄λ‘ λ³ννλ€.
const json = JSON.stringify(todos);
// JSON ν¬λ§·μ λ¬Έμμ΄μ λ°°μ΄λ‘ λ³ννλ€. λ°°μ΄μ μμκΉμ§ κ°μ²΄λ‘ λ³νλλ€.
const parsed = JSON.parse(json);
console.log(typeof parsed, parsed);
/*
object [
{ id: 1, content: 'HTML', completed: false },
{ id: 2, content: 'CSS', completed: true },
{ id: 3, content: 'Javascript', completed: false }
]
*/
λΈλΌμ°μ λ μ£Όμμ°½μ΄λ HTMLμ form νκ·Έ λλ a νκ·Έλ₯Ό ν΅ν΄ HTTP μμ² μ μ‘ κΈ°λ₯μ κΈ°λ³Έ μ 곡νλ€. μλ°μ€ν¬λ¦½νΈλ₯Ό μ¬μ©νμ¬ HTTP μμ²μ μ μ‘νλ €λ©΄ XMLHttpRequest κ°μ²΄λ₯Ό μ¬μ©νλ€. Web APIμΈ XMLHttpRequest κ°μ²΄λ HTTP μμ² μ μ‘κ³Ό HTTP μλ΅ μμ μ μν λ€μν λ©μλμ νλ‘νΌν°λ₯Ό μ 곡νλ€.
XMLHttpRequest κ°μ²΄λ XMLHttpRequest μμ±μ ν¨μλ₯Ό νΈμΆνμ¬ μμ±νλ€. XMLHttpRequest κ°μ²΄λ λΈλΌμ°μ μμ μ 곡νλ Web API μ΄λ―λ‘ λΈλΌμ°μ νκ²½μμλ§ μ μμ μΌλ‘ μ€νλλ€.
// XMLHttpRequest κ°μ²΄ μμ±
const xhr = new XMLHttpRequest();
XMLHttpRequest κ°μ²΄λ λ€μκ³Ό κ°μ λ€μν νλ‘νΌν°μ λ©μλλ₯Ό μ 곡νλ€.
νλ‘ν νμ νλ‘νΌν° | μ€λͺ |
---|---|
readyState | HTTP μμ²μ νμ¬ μνλ₯Ό λνλ΄λ μ μ |
λ€μκ³Ό κ°μ XMLHttpRequestμ μ μ νλ‘νΌν°λ₯Ό κ°μΌλ‘ κ°λλ€. | |
βͺ UNSENT: 0 | |
βͺ OPENED: 1 | |
βͺ HEADERS_RECEIVED: 2 | |
βͺ LOADING: 3 | |
βͺ DONE: 4 | |
status | HTTP μμ²μ λν μλ΅ μν(HTTP μν μ½λ)λ₯Ό λνλ΄λ μ μ |
ex) 200 | |
statusText | HTTP μμ²μ λν μλ΅ λ©μμ§λ₯Ό λνλ΄λ λ¬Έμμ΄ex) "OK" |
responseType | HTTP μλ΅ νμ ex) document, json, text, blob, arraybuffer |
response | HTTP μμ²μ λν μλ΅ λͺΈμ²΄. responseTypeμ λ°λΌ νμ μ΄ λ€λ₯΄λ€. |
responseText | μλ²κ° μ μ‘ν HTTP μμ²μ λν μλ΅ λ¬Έμμ΄ |
μ΄λ²€νΈ νΈλ€λ¬ νλ‘νΌν° | μ€λͺ |
---|---|
onreadystatechange | readyState νλ‘νΌν° κ°μ΄ λ³κ²½λ κ²½μ° |
onloadstart | HTTP μμ²μ λν μλ΅μ λ°κΈ° μμν κ²½μ° |
onprogress | HTTP μμ²μ λν μλ΅μ λ°λ λμ€ μ£ΌκΈ°μ μΌλ‘ λ°μ |
onabort | abort λ©μλμ μν΄ HTTP μμ²μ΄ μ€λ¨λ κ²½μ° |
onerror | HTTP μμ²μ μλ¬κ° λ°μν κ²½μ° |
onload | HTTP μμ²μ΄ μ±κ³΅μ μΌλ‘ μλ£ν κ²½μ° |
ontimeout | HTTP μμ² μκ°μ΄ μ΄κ³Όν κ²½μ° |
onloadend | HTTP μμ²μ μλ£ν κ²½μ°, HTTP μμ²μ΄ μ±κ³΅ λλ μ€ν¨νλ©΄ λ°μ |
λ©μλ | μ€λͺ |
---|---|
open | HTTP μμ² μ΄κΈ°ν |
end | HTTP μμ² μ μ‘ |
abort | μ΄λ―Έ μ μ‘λ HTTP μμ² μ€λ¨ |
setRequestHeader | νΉμ HTTP μμ² ν€λμ κ°μ μ€μ |
getResponseHeader | νΉμ HTTP μμ² ν€λμ κ°μ λ¬Έμμ΄λ‘ λ°ν |
μ μ νλ‘νΌν° | κ° | μ€λͺ |
---|---|---|
UNSENT | 0 | open λ©μλ νΈμΆ μ΄μ |
OPENED | 1 | open λ©μλ νΈμΆ μ΄ν |
HEADERS_RECEIVED | 2 | send λ©μλ νΈμΆ μ΄ν |
LOADING | 3 | μλ² μλ΅ μ€(μλ΅ λ°μ΄ν° λ―Έμμ± μν) |
DONE | 4 | μλ² μλ΅ μλ£ |
HTTP μμ² μ μ‘μ λ€μ μμλ₯Ό λ°λ₯Έλ€.
// XMLHttpRequest κ°μ²΄ μμ±
const xhr = new XMLHttpRequest();
// HTTP μμ² μ΄κΈ°ν
xhr.open('GET', '/users');
// HTTP μμ² ν€λ μ€μ
// ν΄λΌμ΄μΈνΈκ° μλ²λ‘ μ μ‘ν λ°μ΄ν°μ MIME νμ
μ§μ : json
xhr.setRequestHeader('content-type', 'application/json');
// HTTP μμ² μ μ‘
xhr.send();
XMLHttpRequest.prototype.open
open λ©μλλ μλ²μ μ μ‘ν HTTP μμ²μ μ΄κΈ°ννλ€. open λ©μλλ λ€μκ³Όκ°μ΄ νΈμΆνλ€.
xhr.open(method, url[, async])
맀κ°λ³μ | μ€λͺ |
---|---|
method | HTTP μμ² λ©μλ("GET", "POST", "PUT", "DELETE" λ±) |
url | HTTP μμ²μ μ μ‘ν URL |
async | λΉλκΈ° μμ² μ¬λΆ. μ΅μ μΌλ‘ κΈ°λ³Έκ°μ trueμ΄λ©°, λΉλκΈ° λ°©μμΌλ‘ λμνλ€. |
HTTP μμ² λ©μλλ ν΄λΌμ΄μΈνΈκ° μλ²μκ² μμ²μ μ’ λ£μ λͺ©μ (리μμ€μ λν νμ)μ μ리λ λ°©λ²μ΄λ€. μ£Όλ‘ 5κ°μ§ μμ² λ©μλ(GET, POST, PUT, PATCH, DELETE λ±)λ₯Ό μ¬μ©νμ¬ CRUDλ₯Ό ꡬννλ€.
HTTP μμ² λ©μλ | μ’ λ₯ | λͺ©μ | νμ΄λ‘λ |
---|---|---|---|
GET | index/retrieve | λͺ¨λ /νΉμ 리μμ€ μ·¨λ | X |
POST | create | 리μμ€ μμ± | O |
PUT | replace | 리μμ€μ μ 체 κ΅μ²΄ | O |
PATCH | modify | 리μμ€μ μΌλΆ μμ | O |
DELETE | delete | λͺ¨λ /νΉμ 리μμ€ μμ | X |
send λ©μλμλ μμ² λͺΈμ²΄μ λ΄μ μ μ‘ν λ°μ΄ν°(νμ΄λ‘λ)λ₯Ό μΈμλ‘ μ λ¬ν μ μλ€. νμ΄λ‘λκ° κ°μ²΄μΈ κ²½μ° λ°λμ JSON.stringify λ©μλλ₯Ό μ¬μ©νμ¬ μ§λ ¬νν λ€μ μ λ¬ν΄μΌ νλ€.
xhr.send(JSON.stringify({ id: 1, content: 'HTML', completed: false }));
HTTP μμ² λ©μλκ° GETμΈ κ²½μ° send λ©μλλ‘ νμ΄λ‘λμ μ λ¬ν μΈμλ 무μλκ³ μμ² λͺΈμ²΄λ nullλ‘ μ€μ λλ€.
MIME νμ | μλΈνμ |
---|---|
text | text/plain, text/html, text/css, text/javascript |
application | application/json, application/x-www-form-urlencode |
multipart | multipart/formed-data |
// XMLHttpRequest κ°μ²΄ μμ±
const xhr = new XMLHttpRequest();
// HTTP μμ² μ΄κΈ°ν
xhr.open('POST', '/users');
// HTTP μμ² ν€λ μ€μ
// ν΄λΌμ΄μΈνΈκ° μλ²λ‘ μ μ‘ν λ°μ΄ν°μ MIME νμ
μ§μ : json
xhr.setRequestHeader('content-type', 'application/json');
// HTTP μμ² μ μ‘
xhr.send(JSON.stringify({ id: 1, content: 'HTML', completed: false }));
HTTP ν΄λΌμ΄μΈνΈκ° μλ²μ μμ²ν λ μλ²κ° μλ΅ν λ°μ΄ν°μ MIME νμ
μ Acceptλ‘ μ§μ ν μ μλ€. λ€μμ μλ²κ° μλ΅ν λ°μ΄ν°μ MIME νμ
μ μ§μ νλ μμ΄λ€.// μλ²κ° μλ΅ν λ°μ΄ν°μ MIME νμ
μ§μ : json
xhr.setRequestHeader('accept', 'application/json');
λ§μ½ Accept ν€λλ₯Ό μ€μ νμ§ μμΌλ©΄ sendκ° νΈμΆλ λ Accept ν€λκ°Β / μΌλ‘ μ μ‘λλ€.μλ²κ° μ μ‘ν μλ΅μ μ²λ¦¬νλ €λ©΄ XMLHttpRequest κ°μ²΄κ° λ°μμν€λ μ΄λ²€νΈλ₯Ό μΊμΉν΄μΌ νλ€. XMLHttpRequest κ°μ²΄λ onreadystatechange, onload, onerror κ°μ μ΄λ²€νΈ νΈλ€λ¬ νλ‘νΌν°λ₯Ό κ°λλ€. μ΄ μ΄λ²€νΈ νΈλ€λ¬ νλ‘νΌν° μ€μμ HTTP μμ²μ νμ¬ μνλ₯Ό λνλ΄λ readyState νλ‘νΌν° κ°μ΄ λ³κ²½λ κ²½μ° λ°μνλ readystatechange μ΄λ²€νΈλ₯Ό μΊμΉνμ¬ λ€μκ³Ό κ°μ΄ HTTP μλ΅μ μ²λ¦¬ν μ μλ€.
XMLHttpRequest κ°μ²΄λ λΈλΌμ°μ μμ μ 곡νλ Web APIμ΄λ―λ‘ λ€μ μμ λ λ°λμ λΈλΌμ°μ νκ²½μμ μ€νν΄μΌ νλ©° μ°Έκ³ λ‘ HTTP μμ²μ μ μ‘νκ³ μλ΅μ λ°μΌλ €λ©΄ μλ²κ° νμνλ€.
// XMLHttpRequest κ°μ²΄ μμ±
const xhr = new XMLHttpRequest();
// HTTP μμ² μ΄κΈ°ν
// https://jsonplaceholder.typicode.comμ Fake REST APIλ₯Ό μ 곡νλ μλΉμ€λ€.
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1');
// HTTP μμ² μ μ‘
xhr.send();
// readystatechange μ΄λ²€νΈλ HTTP μμ²μ νμ¬ μνλ₯Ό λνλ΄λ readyState νλ‘νΌν°κ°
// λ³κ²½λ λλ§λ€ λ°μνλ€.
xhr.onreadystatechange = () => {
// readyState νλ‘νΌν°λ HTTP μμ²μ νμ¬ μνλ₯Ό λνλΈλ€.
// readyState νλ‘νΌν° κ°μ΄ 4(XMLHttpRequest.DONE)κ° μλλ©΄ μλ² μλ΅μ΄ μλ£λμ§ μνλ€.
// λ§μ½ μλ² μλ΅μ΄ μμ§ μλ£λμ§ μμλ€λ©΄ μλ¬΄λ° μ²λ¦¬λ₯Ό νμ§ μλλ€.
if (xhr.readyState !== XMLHttpRequest.DONE) return;
// status νλ‘νΌν°λ μλ΅ μν μ½λλ₯Ό λνλΈλ€.
// status νλ‘νΌν° κ°μ΄ 200μ΄λ©΄ μ μμ μΌλ‘ μλ΅λ μνμ΄κ³
// status νλ‘νΌν° κ°μ΄ 200μ΄ μλλ©΄ μλ¬κ° λ°μν μνλ€.
// μ μμ μΌλ‘ μλ΅λ μνλΌλ©΄ response νλ‘νΌν°μ μλ²μ μλ΅ κ²°κ³Όκ° λ΄κ²¨ μλ€.
if (xhr.status === 200) {
console.log(JSON.parse(xhr.response));
// {userId: 1, id: 1, title: "delectus aut autem", completed: false}
} else {
console.error('Error', xhr.status, xhr.statusText);
}
};
send λ©μλλ₯Ό ν΅ν΄ HTTP μμ²μ μλ²μ μ μ‘νλ©΄ μλ²λ μλ΅μ λ°ννμ§λ§ μΈμ μλ΅μ΄ ν΄λΌμ΄μΈνΈμ λλ¬ν μ§λ μ μ μλ€. λ°λΌμ readystatechange μ΄λ²€νΈλ₯Ό ν΅ν΄ HTTP μμ²μ νμ¬ μνλ₯Ό νμΈν΄μΌ νλ€. readystatechange μ΄λ²€νΈλ HTTP μμ²μ νμ¬ μνλ₯Ό λνλ΄λ readyState νλ‘νΌν°κ° λ³κ²½λ λλ§λ€ λ°μνλ€.
readystatechange μ΄λ²€νΈ λμ load μ΄λ²€νΈλ₯Ό μΊμΉν΄λ μ’λ€. load μ΄λ²€νΈλ HTTP μμ²μ΄ μ±κ³΅μ μΌλ‘ μλ£λ κ²½μ° λ°μνλ€. λ°λΌμ load μ΄λ²€νΈλ₯Ό μΊμΉνλ κ²½μ° xhr.readyStateκ° XMLHttpRequest.DONEμΈμ§ νμΈν νμκ° μλ€.
// XMLHttpRequest κ°μ²΄ μμ±
const xhr = new XMLHttpRequest();
// HTTP μμ² μ΄κΈ°ν
// https://jsonplaceholder.typicode.comμ Fake REST APIλ₯Ό μ 곡νλ μλΉμ€λ€.
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1');
// HTTP μμ² μ μ‘
xhr.send();
// load μ΄λ²€νΈλ HTTP μμ²μ΄ μ±κ³΅μ μΌλ‘ μλ£λ κ²½μ° λ°μνλ€.
xhr.onload = () => {
// status νλ‘νΌν°λ μλ΅ μν μ½λλ₯Ό λνλΈλ€.
// status νλ‘νΌν° κ°μ΄ 200μ΄λ©΄ μ μμ μΌλ‘ μλ΅λ μνμ΄κ³
// status νλ‘νΌν° κ°μ΄ 200μ΄ μλλ©΄ μλ¬κ° λ°μν μνλ€.
// μ μμ μΌλ‘ μλ΅λ μνλΌλ©΄ response νλ‘νΌν°μ μλ²μ μλ΅ κ²°κ³Όκ° λ΄κ²¨ μλ€.
if (xhr.status === 200) {
console.log(JSON.parse(xhr.response));
// {userId: 1, id: 1, title: "delectus aut autem", completed: false}
} else {
console.error('Error', xhr.status, xhr.statusText);
}
};