From ec5beba91237d85eff0654cc1ffe6cc468e0a39f Mon Sep 17 00:00:00 2001 From: narinn-star Date: Sat, 27 Jan 2024 02:10:38 +0900 Subject: [PATCH] docs : Day 19 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 43μž₯ Ajax --- .../\354\235\264\353\202\230\353\246\260.md" | 256 ++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 "docs/43_Ajax/\354\235\264\353\202\230\353\246\260.md" diff --git "a/docs/43_Ajax/\354\235\264\353\202\230\353\246\260.md" "b/docs/43_Ajax/\354\235\264\353\202\230\353\246\260.md" new file mode 100644 index 00000000..b04c649d --- /dev/null +++ "b/docs/43_Ajax/\354\235\264\353\202\230\353\246\260.md" @@ -0,0 +1,256 @@ +# 🎯 43 Ajax + +[43.1 Ajaxλž€?](#1-ajaxλž€) +[43.2 JSON](#2-json) +[43.3 XMLHttpRequest](#3-xmlhttprequest) + +## 1. Ajaxλž€? + +μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ λΈŒλΌμš°μ €κ°€ μ„œλ²„μ—κ²Œ 비동기 λ°©μ‹μœΌλ‘œ 데이터λ₯Ό μš”μ²­ν•˜κ³ , μ„œλ²„κ°€ μ‘λ‹΅ν•œ 데이터λ₯Ό μˆ˜μ‹ ν•΄ μ›ΉνŽ˜μ΄μ§€λ₯Ό λ™μ μœΌλ‘œ κ°±μ‹ ν•˜λŠ” ν”„λ‘œκ·Έλž˜λ° 방식 + +AjaxλŠ” λΈŒλΌμš°μ €μ—μ„œ μ œκ³΅ν•˜λŠ” Web API인 XMLHttpRequest 객체λ₯Ό 기반으둜 λ™μž‘ν•œλ‹€. XMLHttpRequestλŠ” HTTP 비동기 톡신을 μœ„ν•œ λ©”μ„œλ“œμ™€ ν”„λ‘œνΌν‹°λ₯Ό μ œκ³΅ν•œλ‹€. + +μ„œλ²„λ‘œλΆ€ν„° μ›ΉνŽ˜μ΄μ§€μ˜ 변경에 ν•„μš”ν•œ λ°μ΄ν„°λ§Œ 비동기 λ°©μ‹μœΌλ‘œ 전솑받아 μ›ΉνŽ˜μ΄μ§€λ₯Ό λ³€κ²½ν•  ν•„μš”κ°€ μ—†λŠ” 뢀뢄은 λ‹€μ‹œ λ Œλ”λ§ν•˜μ§€ μ•Šκ³ , λ³€κ²½ν•  ν•„μš”κ°€ μžˆλŠ” λΆ€λΆ„λ§Œ λ Œλ”λ§ν•˜λŠ” 방식이 κ°€λŠ₯ν•΄μ‘Œλ‹€. 이λ₯Ό 톡해 λΈŒλΌμš°μ €μ—μ„œλ„ λ°μŠ€ν¬ν†± μ• ν”Œλ¦¬μΌ€μ΄μ…˜κ³Ό μœ μ‚¬ν•œ λΉ λ₯Έ νΌν¬λ¨ΌμŠ€μ™€ λΆ€λ“œλŸ¬μš΄ ν™”λ©΄ μ „ν™˜μ΄ κ°€λŠ₯ν•΄μ‘Œλ‹€. + +✨ Ajax의 μž₯점 (전톡 방식과 비ꡐ) + +- λ³€κ²½ν•  뢀뢄을 κ°±μ‹ ν•˜λŠ” 데 ν•„μš”ν•œ λ°μ΄ν„°λ§Œ μ„œλ²„λ‘œλΆ€ν„° 전솑받기 λ•Œλ¬Έμ— λΆˆν•„μš”ν•œ 데이터 톡신이 λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. +- λ³€κ²½ν•  ν•„μš”κ°€ μ—†λŠ” 뢀뢄은 λ‹€μ‹œ λ Œλ”λ§ν•˜μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ 화면이 μˆœκ°„μ μœΌλ‘œ κΉœλ°•μ΄λŠ” ν˜„μƒμ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. +- ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„μ™€μ˜ 톡신이 비동기 λ°©μ‹μœΌλ‘œ λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ— μ„œλ²„μ—κ²Œ μš”μ²­μ„ 보낸 이후 λΈ”λ‘œν‚Ήμ΄ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. + +## 2. JSON + +ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„ κ°„μ˜ HTTP 톡신을 μœ„ν•œ ν…μŠ€νŠΈ 데이터 포맷으둜, μžλ°”μŠ€ν¬λ¦½νŠΈμ— μ’…μ†λ˜μ§€ μ•ŠλŠ” μ–Έμ–΄ λ…λ¦½ν˜• 데이터 포맷으둜, λŒ€λΆ€λΆ„μ˜ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ μ‚¬μš©ν•  수 μžˆλ‹€. + +## 2.1 JSON ν‘œκΈ° 방식 + +μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 객체 λ¦¬ν„°λŸ΄κ³Ό μœ μ‚¬ν•˜κ²Œ 킀와 κ°’μœΌλ‘œ κ΅¬μ„±λœ μˆœμˆ˜ν•œ ν…μŠ€νŠΈλ‹€. + +ν‚€λŠ” λ°˜λ“œμ‹œ ν°λ”°μ˜΄ν‘œλ‘œ λ¬Άμ–΄μ•Ό ν•˜λ©°, 값은 객체 λ¦¬ν„°λŸ΄κ³Ό 같은 ν‘œκΈ°λ²•μ„ κ·ΈλŒ€λ‘œ μ‚¬μš©ν•  수 μžˆλ‹€. +λ¬Έμžμ—΄μ€ λ°˜λ“œμ‹œ ν°λ”°μ˜΄ν‘œλ‘œ λ¬Άμ–΄μ•Ό ν•œλ‹€. + +```json +{ + "name": "Lee", + "age": 20, + "alive": true, + "hobby": ["traveling", "tennis"] +} +``` + +### 2.2 JSON.stringify + +객체λ₯Ό JSON 포맷의 λ¬Έμžμ—΄λ‘œ λ³€ν™˜ν•˜λŠ” λ©”μ„œλ“œ +ν΄λΌμ΄μ–ΈνŠΈκ°€ μ„œλ²„λ‘œ 객체λ₯Ό μ „μ†‘ν•˜λ €λ©΄ 객체λ₯Ό λ¬Έμžμ—΄ν™”ν•΄μ•Ό ν•˜λŠ”λ° 이λ₯Ό *직렬화*라 ν•œλ‹€. + +```javascript +const obj = { + name: 'Lee', + age: 20, + alive: true, + hobby: ['traveling', 'tennis'], +}; + +const json = JSON.stringify(obj); +console.log(typeof json, json); +// string {"name":"Lee","age":20,"alive":true,"hobby":["traveling","tennis"]} + +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 포맷의 λ¬Έμžμ—΄λ‘œ λ³€ν™˜ν•  수 μžˆλ‹€. + +### 2.3 JSON.parse + +JSON 포맷의 λ¬Έμžμ—΄μ„ 객체둜 λ³€ν™˜ν•˜λŠ” λ©”μ„œλ“œλ‹€. +μ„œλ²„λ‘œλΆ€ν„° ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ μ „μ†‘λœ JSON 데이터인 λ¬Έμžμ—΄μ„ κ°μ²΄λ‘œμ„œ μ‚¬μš©ν•˜λ €λ©΄ JSON 포맷의 λ¬Έμžμ—΄μ„ 객체화해야 ν•˜λŠ”λ° 이λ₯Ό *역직렬화*라 ν•œλ‹€. + +```javascript +const obj = { + name: 'Lee', + age: 20, + alive: true, + hobby: ['traveling', 'tennis'], +}; + +const json = JSON.stringify(obj); + +const parsed = JSON.parse(json); +console.log(typeof parsed, parsed); +// object {"name":"Lee","age":20,"alive":true,"hobby":["traveling","tennis"]} +``` + +배열이 JSON 포맷의 λ¬Έμžμ—΄λ‘œ λ³€ν™˜λ˜μ–΄ μžˆλŠ” 경우 JSON.parseλŠ” λ¬Έμžμ—΄μ„ λ°°μ—΄ 객체둜 λ³€ν™˜ν•œλ‹€. λ°°μ—΄μ˜ μš”μ†Œκ°€ 객체인 경우 λ°°μ—΄μ˜ μš”μ†ŒκΉŒμ§€ 객체둜 λ³€ν™˜ν•œλ‹€. + +## 3. XMLHttpRequest + +μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό μ‚¬μš©ν•΄ HTTP μš”μ²­μ„ μ „μ†‘ν•˜λ €λ©΄ XMLHttpRequest 객체λ₯Ό μ‚¬μš©ν•œλ‹€. +Web API인 XMLHttpRequest κ°μ²΄λŠ” HTTP μš”μ²­ 전솑과 HTTP 응닡 μˆ˜μ‹ μ„ μœ„ν•œ λ‹€μ–‘ν•œ λ©”μ„œλ“œμ™€ ν”„λ‘œνΌν‹°λ₯Ό μ œκ³΅ν•œλ‹€. + +### 3.1 XMLHttpRequest 객체 생성 + +XMLHttpRequest μƒμ„±μž ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄ μƒμ„±ν•œλ‹€. +λΈŒλΌμš°μ €μ—μ„œ μ œκ³΅ν•˜λŠ” Web APIμ΄λ―€λ‘œ λΈŒλΌμš°μ € ν™˜κ²½μ—μ„œλ§Œ μ •μƒμ μœΌλ‘œ μ‹€ν–‰λœλ‹€. + +```javascript +const xhr = new XMLHttpRequest(); +``` + +### 3.2 XMLHttpRequest 객체의 ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œ + +λŒ€ν‘œμ μΈ ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œλŠ” λ‹€μŒκ³Ό κ°™λ‹€. + +- XMLHttpRequest 객체의 ν”„λ‘œν† νƒ€μž… ν”„λ‘œνΌν‹° + + - readyState + - status + - statusText + - responseType + - response + - HTTP μš”μ²­μ— λŒ€ν•œ 응닡 λͺΈμ²΄ (response body), responseType에 따라 νƒ€μž…μ΄ 닀름 + - responseText + +- XMLHttpRequest 객체의 이벀트 ν•Έλ“€λŸ¬ ν”„λ‘œνΌν‹° + + - onreadystatechange + - onloadstart + - onprogress + - onabort + - abort λ©”μ„œλ“œμ— μ˜ν•΄ HTTP μš”μ²­μ΄ μ€‘λ‹¨λœ 경우 + - onerror + - onload + - ontimeout + - onloadend + +- XMLHttpRequest 객체의 λ©”μ„œλ“œ + + - open + - send + - abort + - setRequestHeader + - νŠΉμ • HTTP μš”μ²­ ν—€λ”μ˜ 값을 μ„€μ • + - getRequestHeader + - νŠΉμ • HTTP μš”μ²­ ν—€λ”μ˜ 값을 λ¬Έμžμ—΄λ‘œ λ°˜ν™˜ + +- XMLHttpRequest 객체의 정적 ν”„λ‘œνΌν‹° + - UNSENT (0) : open λ©”μ„œλ“œ 호좜 이전 + - OPENED (1) : open λ©”μ„œλ“œ 호좜 이후 + - HEADERS_RECEIVED (2) : send λ©”μ„œλ“œ 호좜 이후 + - LOADING (3) : μ„œλ²„ 응닡 쀑(응닡 데이터 λ―Έμ™„μ„± μƒνƒœ) + - DONE (4) : μ„œλ²„ 응닡 μ™„λ£Œ + +### 3.3 HTTP μš”μ²­ 전솑 + +1. XMLHttpRequest.prototype.open λ©”μ„œλ“œλ‘œ HTTP μš”μ²­μ„ μ΄ˆκΈ°ν™” +2. ν•„μš”μ— 따라 XMLHttpRequest.prototype.setRequestHeader λ©”μ„œλ“œλ‘œ νŠΉμ • HTTP μš”μ²­μ˜ 헀더 값을 μ„€μ • +3. XMLHttpRequest.prototype.send λ©”μ„œλ“œλ‘œ HTTP μš”μ²­μ„ 전솑 + +```javascript +const xhr = new XMLHttpRequest(); + +xhr.open('GET', '/users'); + +xhr.setRequestHeader('content-type', 'application/json'); + +xhr.send(); +``` + +✨ **XMLHttpRequest.prototype.open** + +open λ©”μ„œλ“œλŠ” μ„œλ²„μ— 전솑할 HTTP μš”μ²­μ„ μ΄ˆκΈ°ν™”ν•œλ‹€. +ν˜ΈμΆœμ€ μ•„λž˜μ™€ 같이 ν•œλ‹€. + +```javascript +xhr.open(method, url[, async]) +``` + +- method : HTTP μš”μ²­ λ©”μ„œλ“œ + - GET, POST, PUT, PATCH, DELETE +- url : HTTP μš”μ²­μ„ 전솑할 URL +- async : 비동기 μš”μ²­ μ—¬λΆ€. μ˜΅μ…˜μœΌλ‘œ 기본값은 true, 비동기 λ°©μ‹μœΌλ‘œ λ™μž‘ν•œλ‹€. + +✨ **XMLHttpRequest.prototype.send** + +send λ©”μ„œλ“œλŠ” open λ©”μ„œλ“œλ‘œ μ΄ˆκΈ°ν™”λœ HTTP μš”μ²­μ„ μ„œλ²„μ— μ „μ†‘ν•œλ‹€. +μ„œλ²„λ‘œ μ „μ†‘ν•˜λŠ” λ°μ΄ν„°λŠ” GET, POST μš”μ²­ λ©”μ„œλ“œμ— 따라 전솑 방식에 차이가 μžˆλ‹€. + +- GET μš”μ²­ λ©”μ„œλ“œμΌ 경우 데이터λ₯Ό URL의 일뢀뢄인 쿼리 λ¬Έμžμ—΄λ‘œ μ„œλ²„μ— μ „μ†‘ν•œλ‹€. (query string) +- POST μš”μ²­ λ©”μ„œλ“œμΌ 경우 데이터(νŽ˜μ΄λ‘œλ“œ, payload)λ₯Ό μš”μ²­ λͺΈμ²΄μ— λ‹΄μ•„ μ „μ†‘ν•œλ‹€. (request body) + +send λ©”μ„œλ“œμ—λŠ” μš”μ²­ λͺΈμ²΄μ— λ‹΄μ•„ 전솑할 데이터λ₯Ό 인수둜 전달할 수 μžˆλ‹€. νŽ˜μ΄λ‘œλ“œκ°€ 객체인 경우 λ°˜λ“œμ‹œ JSON.stringify λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ μ§λ ¬ν™”ν•œ λ‹€μŒ 전달해야 ν•œλ‹€. + +```javascript +xhr.send(JSON.stringify({ id: 1, content: 'HTML', completed: false })); +``` + +βœ”οΈ **HTTP μš”μ²­ λ©”μ„œλ“œκ°€ GET인 경우 send λ©”μ„œλ“œμ— νŽ˜μ΄λ‘œλ“œλ‘œ μ „λ‹¬ν•œ μΈμˆ˜λŠ” λ¬΄μ‹œλ˜κ³  μš”μ²­ λͺΈμ²΄λŠ” null둜 μ„€μ •λœλ‹€.** + +✨ **XMLHttpRequest.prototype.setRequestHeader** + +setRequestHeader λ©”μ„œλ“œλŠ” νŠΉμ • HTTP μš”μ²­μ˜ 헀더 값을 μ„€μ •ν•˜λ©° λ°˜λ“œμ‹œ open λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œ 이후에 ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€. + +자주 μ‚¬μš©ν•˜λŠ” HTTP μš”μ²­ 헀더인 Content-typeκ³Ό Accept에 λŒ€ν•΄ μ‚΄νŽ΄λ³΄μž. + +- Content-type + μš”μ²­ λͺΈμ²΄μ— λ‹΄μ•„ 전솑할 λ°μ΄ν„°μ˜ MIME νƒ€μž…μ˜ 정보λ₯Ό ν‘œν˜„ν•œλ‹€. + - MIME νƒ€μž… + text : text/plain, text/html, text/css, text/javascript + application : application/json, application/x-www-form-urlencode + multipart : multipart/formed-data + +```javascript +const xhr = new XMLHttpRequest(); + +xhr.open('POST', '/users'); + +xhr.setRequestHeader('content-type', 'application/json'); + +xhr.send(JSON.stringify({ id: 1, content: 'HTML', completed: false })); +``` + +- Accept + HTTP ν΄λΌμ΄μ–ΈνŠΈκ°€ μ„œλ²„μ— μš”μ²­ν•  λ•Œ 응닡할 λ°μ΄ν„°μ˜ MIME νƒ€μž…μ„ Accept둜 지정할 수 μžˆλ‹€. + Accept 헀더λ₯Ό μ„€μ •ν•˜μ§€ μ•ŠμœΌλ©΄ send λ©”μ„œλ“œκ°€ 호좜될 λ•Œ Accept 헀더가 */*으둜 μ „μ†‘λœλ‹€. + +```javascript +xhr.setRequestHeader('accept', 'application/json'); +``` + +### 3.4 HTTP 응닡 처리 + +- send λ©”μ„œλ“œλ₯Ό 톡해 HTTP μš”μ²­μ„ μ„œλ²„μ— μ „μ†‘ν•˜λ©΄ μ„œλ²„λŠ” 응닡을 λ°˜ν™˜ν•œλ‹€. +- readystatechange 이벀트λ₯Ό 톡해 HTTP μš”μ²­μ˜ ν˜„μž¬ μƒνƒœλ₯Ό ν™•μΈν•œλ‹€. +- μ„œλ²„μ˜ 응닡이 μ™„λ£Œλ˜λ©΄ 응닡 μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ” statusκ°€ 200인지 ν™•μΈν•˜κ³  정상 μ²˜λ¦¬μ™€ μ—λŸ¬ 처리λ₯Ό κ΅¬λΆ„ν•œλ‹€. +- μ •μƒμ μœΌλ‘œ λ„μ°©ν–ˆλ‹€λ©΄ μ„œλ²„κ°€ μ „μ†‘ν•œ 데이터λ₯Ό responseμ—μ„œ μ·¨λ“ν•˜λ©° μ—λŸ¬κ°€ λ°œμƒν–ˆλ‹€λ©΄ ν•„μš”ν•œ μ—λŸ¬ 처리λ₯Ό ν•œλ‹€.