πŸ“² μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ AJAX

thumb_hyeokΒ·2022λ…„ 4μ›” 18일
0

🟑 JavaScript

λͺ©λ‘ 보기
11/15
post-thumbnail
post-custom-banner

πŸ€” AJAXλž€ λ¬΄μ—‡μΌκΉŒ?

Ajax(Asynchronus JavaScript and XML)λž€ μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ λΈŒλΌμš°μ €κ°€ μ„œλ²„μ—κ²Œ 비동기 λ°©μ‹μœΌλ‘œ 데이터λ₯Ό μš”μ²­ν•˜κ³  μ„œλ²„κ°€ μ‘λ‹΅ν•œ 데이터λ₯Ό μˆ˜μ‹ ν•˜μ—¬ μ›ΉνŽ˜μ΄μ§€λ₯Ό λ™μ μœΌλ‘œ κ°±μ‹ ν•˜λŠ” ν”„λ‘œκ·Έλž˜λ° 방식을 λ§ν•œλ‹€. AjaxλŠ” λΈŒλΌμš°μ €μ—μ„œ μ œκ³΅ν•˜λŠ” Web API인 XMLHttpRequest 객체λ₯Ό 기반으둜 λ™μž‘ν•œλ‹€.

Ajax μ΄μ „μ˜ μ›ΉνŽ˜μ΄μ§€λŠ” html νƒœκ·Έλ‘œ μ‹œμž‘ν•΄μ„œ html νƒœκ·Έλ‘œ λλ‚˜λŠ” μ™„μ „ν•œ HTML을 μ„œλ²„λ‘œλΆ€ν„° 전솑받아 μ›ΉνŽ˜μ΄μ§€ 전체λ₯Ό μ²˜μŒλΆ€ν„° λ‹€μ‹œ λ Œλ”λ§ν•˜λŠ” λ°©μ‹μœΌλ‘œ λ™μž‘ν–ˆλ‹€. 화면이 μ „ν™˜λ˜λ©΄ μ„œλ²„λ‘œλΆ€ν„° μƒˆλ‘œμš΄ HTML을 전솑받아 μ›ΉνŽ˜μ΄μ§€ 전체λ₯Ό μ²˜μŒλΆ€ν„° λ‹€μ‹œ λ Œλ”λ§ν–ˆλ‹€.

μ΄λŸ¬ν•œ 전톡적인 방식은 λ‹€μŒκ³Ό 같은 단점이 μžˆλ‹€.

  1. 변경사항과 상관없이 μ–Έμ œλ‚˜ μ™„μ „ν•œ HTML을 μ„œλ²„λ‘œλΆ€ν„° 전솑받기 λ•Œλ¬Έμ— λΆˆν•„μš”ν•œ 데이터 톡신 λ°œμƒ.
  2. λ³€κ²½ν•  ν•„μš”κ°€ μ—†λŠ” λΆ€λΆ„κΉŒμ§€ μ²˜μŒλΆ€ν„° λ‹€μ‹œ λ Œλ”λ§ β†’ μˆœκ°„μ μœΌλ‘œ κΉœλΉ‘μ΄λŠ” ν˜„μƒ λ°œμƒ
  3. ν΄λΌμ΄μ–ΈνŠΈ ←→ μ„œλ²„ 톡신이 동기 방식이라 λΈ”λ‘œν‚Ήμ΄ λ°œμƒν•  수 있음.

🏷️ JSON

JSON(JavaScript Object Notation)은 ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„ κ°„μ˜ HTTP 톡신을 μœ„ν•œ ν…μŠ€νŠΈ 데이터 포맷이닀. μžλ°”μŠ€ν¬λ¦½νŠΈμ— μ’…μ†λ˜μ§€ μ•ŠλŠ” μ–Έμ–΄ λ…λ¦½ν˜• 데이터 포맷으둜, λŒ€λΆ€λΆ„μ˜ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ μ‚¬μš©ν•  수 μžˆλ‹€. JSON은 μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 객체 λ¦¬ν„°λŸ΄κ³Ό μœ μ‚¬ν•˜κ²Œ 킀와 κ°’μœΌλ‘œ κ΅¬μ„±λœ μˆœμˆ˜ν•œ ν…μŠ€νŠΈλ‹€.

JSON.stringify

ν΄λΌμ΄μ–ΈνŠΈκ°€ μ„œλ²„λ‘œ 객체λ₯Ό μ „μ†‘ν•˜λ €λ©΄ 객체λ₯Ό λ¬Έμžμ—΄ν™”ν•΄μ•Ό ν•˜λŠ”λ° 이λ₯Ό 직렬화(serializing)μ΄λΌν•œλ‹€. JSON.stringify λ©”μ„œλ“œλŠ” κ°’μ΄λ‚˜ 객체λ₯Ό JSON 포맷의 λ¬Έμžμ—΄λ‘œ λ³€ν™˜ν•œλ‹€.

console.log(JSON.stringify({ x: 5, y: 6 }));
// expected output: "{"x":5,"y":6}"

console.log(JSON.stringify([new Number(3), new String('false'), new Boolean(false)]));
// expected output: "[3,"false",false]"

console.log(JSON.stringify({ x: [10, undefined, function(){}, Symbol('')] }));
// expected output: "{"x":[10,null,null,null]}"

console.log(JSON.stringify(new Date(2006, 0, 2, 15, 4, 5)));
// expected output: ""2006-01-02T15:04:05.000Z""

JSON.parse

μ„œλ²„λ‘œλΆ€ν„° ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ μ „μ†‘λœ JSON λ°μ΄ν„°λŠ” λ¬Έμžμ—΄μ΄λ‹€. 이 λ¬Έμžμ—΄μ„ κ°μ²΄λ‘œμ„œ μ‚¬μš©ν•˜λ €λ©΄ JSON 포맷의 객체화해야 ν•˜λŠ”λ° 이λ₯Ό 역직렬화(deserializing)라 ν•œλ‹€. JSON.parse λ©”μ„œλ“œλŠ” JSON 포맷의 λ¬Έμžμ—΄μ„ 객체둜 λ³€ν™˜ν•œλ‹€.

const json = '{"result":true, "count":42}';
const obj = JSON.parse(json);

console.log(obj.count);
// expected output: 42

console.log(obj.result);
// expected output: true

πŸ“² XMLHttpRequest

λΈŒλΌμš°μ €λŠ” μ£Όμ†Œμ°½μ΄λ‚˜ HTML의 form νƒœκ·Έ λ˜λŠ” a νƒœκ·Έλ₯Ό 톡해 HTTP μš”μ²­ 전솑 κΈ°λŠ₯을 κΈ°λ³Έ μ œκ³΅ν•œλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ HTTP μš”μ²­μ„ μ „μ†‘ν•˜λ €λ©΄ XMLHttpRequest 객체λ₯Ό μ‚¬μš©ν•œλ‹€.

XMLHttpRequest 객체 생성

XMLHttpRequest κ°μ²΄λŠ” XMLHttpRequest μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ μƒμ„±ν•œλ‹€. XMLHttpRequest κ°μ²΄λŠ” λΈŒλΌμš°μ €μ—μ„œ μ œκ³΅ν•˜λŠ” Web APIμ΄λ―€λ‘œ λΈŒλΌμš°μ € ν™˜κ²½μ—μ„œλ§Œ μ •μƒμ μœΌλ‘œ μ‹€ν–‰λœλ‹€.

const xhr = new XMLHttpRequest();

HTTP μš”μ²­ 전솑

HTTP μš”μ²­μ„ μ „μ†‘ν•˜λŠ” 경우 λ‹€μŒ μˆœμ„œλ₯Ό λ”°λ₯Έλ‹€.

  1. XMLHttpRequest.prototype.open λ©”μ„œλ“œλ‘œ HTTP μš”μ²­μ„ μ΄ˆκΈ°ν™”ν•œλ‹€.
  2. ν•„μš”μ— 따라 XMLHttpRequest.prototype.setRequestHeader λ©”μ„œλ“œλ‘œ νŠΉμ • HTTP μš”μ²­μ˜ 헀더 값을 μ„€μ •ν•œλ‹€.
  3. ν•„μš”μ— 따라 XMLHttpRequest.prototype.send λ©”μ„œλ“œλ‘œ HTTP μš”μ²­μ„ μ „μ†‘ν•œλ‹€.
// XMLHttpRequest 객체 생성
const xhr = new XMLHttpRequest();

// HTTP μš”μ²­ μ΄ˆκΈ°ν™”
xhr.open('GET', '/user');

// HTTP μš”μ²­ 헀더 μ„€μ •
// ν΄λΌμ΄μ–ΈνŠΈκ°€ μ„œλ²„λ‘œ 전솑할 λ°μ΄ν„°μ˜ MIME νƒ€μž… 지정:: json
xhr.setRequestHeader('content-type', 'application/json');

HTTP 응닡 처리

μ„œλ²„κ°€ μ „μ†‘ν•œ 응닡을 μ²˜λ¦¬ν•˜λ €λ©΄ XMLHttpRequest 객체가 λ°œμƒμ‹œν‚€λŠ” 이벀트λ₯Ό μΊμΉ˜ν•΄μ•Όν•œλ‹€. XMLHttpRequest 객체가 κ°–λŠ” 이벀트 ν•Έλ“€λŸ¬ ν”„λ‘œνΌν‹° μ€‘μ—μ„œ HTTP μš”μ²­μ˜ ν˜„μž¬ μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ” readyState ν”„λ‘œνΌν‹° 값이 λ³€κ²½λœ 경우 λ°œμƒν•˜λŠ” readystatechangae 이벀트λ₯Ό μΊμΉ˜ν•˜μ—¬ λ‹€μŒκ³Ό 같이 HTTP 응닡을 μ²˜λ¦¬ν•  수 μžˆλ‹€.

const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1')';
xhr.send();

// readystatechange μ΄λ²€νŠΈλŠ” HTTP μš”μ²­μ˜ ν˜„μž¬ μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ” readyState ν”„λ‘œνΌν‹°κ°€
// 변경될 λ•Œλ§ˆλ‹€ λ°œμƒν•œλ‹€.
xhr.onreadystatechange = () => {
	// readyState ν”„λ‘œνΌν‹°λŠ” HTTP μš”μ²­μ˜ ν˜„μž¬ μƒνƒœλ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
	// readyState ν”„λ‘œνΌν‹° 값이 4(XMLHttpRequest.DONE)κ°€ μ•„λ‹ˆλ©΄ 
	// μ„œλ²„ 응닡이 μ™„λ£Œλ˜μ§€ μ•Šμ€ μƒνƒœμ΄λ‹€.
	if (xhr.readyState !== XMLHttpRequest.DONE) {
		return;
	}
	if (xhr.status === 200) {
		console.log(JSON.parse(xhr.response));
	}
	else {
		console.error('Error', xhr.status, xhr.statusText));
	}
}

send λ©”μ„œλ“œλ₯Ό 톡해 HTTP μš”μ²­μ„ μ„œλ²„μ— μ „μ†‘ν•˜λ©΄ μ„œλ²„λŠ” 응닡을 λ°˜ν™˜ν•œλ‹€. ν•˜μ§€λ§Œ μ–Έμ œ 응닡이 ν΄λΌμ΄μ–ΈνŠΈμ— 도달할 지 μ•Œ 수 μ—†κΈ° λ•Œλ¬Έμ— readystatechange 같은 이벀트λ₯Ό 톡해 HTTP μš”μ²­μ˜ ν˜„μž¬ μƒνƒœλ₯Ό ν™•μΈν•΄μ•Όν•œλ‹€.

onreadystatechange 이벀트 ν•Έλ“€λŸ¬ ν”„λ‘œνΌν‹°μ— ν• λ‹Ήν•œ 이벀트 ν•Έλ“€λŸ¬λŠ” HTTP μš”μ²­μ˜ ν˜„μž¬ μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ” xhr.readyStateκ°€ XMLHttpRequest.DONE인지 ν™•μΈν•˜μ—¬ μ„œλ²„μ˜ 응닡이 μ™„λ£Œλ˜μ—ˆλŠ”μ§€ ν™•μΈν•œλ‹€. 이후 μ„œλ²„μ˜ 응닡이 μ™„λ£Œλ˜λ©΄ HTTP μš”μ²­μ— λŒ€ν•œ 응닡 μƒνƒœ(HTTP μƒνƒœ μ½”λ“œ)λ₯Ό λ‚˜νƒ€λ‚΄λŠ” xhr.statusκ°€ 200인지 ν™•μΈν•˜μ—¬ 정상 μ²˜λ¦¬μ™€ μ—λŸ¬ 처리λ₯Ό κ΅¬λΆ„ν•œλ‹€.


🧐 정리

  • AJAXλž€, μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ λΈŒλΌμš°μ €κ°€ μ„œλ²„μ—κ²Œ 비동기 λ°©μ‹μœΌλ‘œ 데이터λ₯Ό μš”μ²­ν•˜κ³  μ„œλ²„κ°€ μ‘λ‹΅ν•œ 데이터λ₯Ό μˆ˜μ‹ ν•˜μ—¬ μ›ΉνŽ˜μ΄μ§€λ₯Ό λ™μ μœΌλ‘œ κ°±μ‹ ν•˜λŠ” ν”„λ‘œκ·Έλž˜λ° 방식을 λ§ν•œλ‹€.
  • JSON은 ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„ κ°„μ˜ HTTP 톡신을 μœ„ν•œ ν…μŠ€νŠΈ 데이터 포맷이닀.
  • XMLHttpRequest κ°μ²΄λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ HTTP μš”μ²­μ„ μ „μ†‘ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•œλ‹€.

πŸ“– 참고자료

  • λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ Deep Dive
      1. AJAX (816p~827p)
profile
μš°μ•„ν•œν…Œν¬μ½”μŠ€ 4κΈ° μ›Ή ν”„λ‘ νŠΈμ—”λ“œ
post-custom-banner

0개의 λŒ“κΈ€