diff --git a/Aug/article/Axios-vs-Fetch-API:-Selecting-the-Right-Tool-for-HTTP-Requests.md b/Aug/article/Axios-vs-Fetch-API:-Selecting-the-Right-Tool-for-HTTP-Requests.md new file mode 100644 index 0000000..c6205d2 --- /dev/null +++ b/Aug/article/Axios-vs-Fetch-API:-Selecting-the-Right-Tool-for-HTTP-Requests.md @@ -0,0 +1,371 @@ +## πŸ”— [Axios vs. Fetch API: Selecting the Right Tool for HTTP Requests](https://medium.com/@johnnyJK/axios-vs-fetch-api-selecting-the-right-tool-for-http-requests-ecb14e39e285) + +### πŸ—“οΈ λ²ˆμ—­ λ‚ μ§œ: 2024.08.05 + +### 🧚 λ²ˆμ—­ν•œ 크루: μ†Œν•˜(μ΅œμ†Œμ—°) + +--- + + + +μ†Œν”„νŠΈμ›¨μ–΄ 개발 λΆ„μ•Όμ—μ„œλŠ” 웹을 톡해 원격 μ„œλ²„μ™€ μ›ν™œν•˜κ²Œ μƒν˜Έ μž‘μš©ν•˜κ³  데이터λ₯Ό κ΅ν™˜ν•˜λŠ” λŠ₯λ ₯이 맀우 μ€‘μš”ν•©λ‹ˆλ‹€. APIμ—μ„œ 데이터λ₯Ό κ°€μ Έμ˜€κ±°λ‚˜, CRUD μž‘μ—…μ„ μˆ˜ν–‰ν•˜κ±°λ‚˜, 기타 λ„€νŠΈμ›Œν¬ κ΄€λ ¨ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” 경우 HTTP μš”μ²­μ„ λ§Œλ“œλŠ” κ²ƒμ˜ μ€‘μš”μ„±μ€ 아무리 강쑰해도 μ§€λ‚˜μΉ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. Fetch와 AxiosλΌλŠ” 두 개의 널리 μ‚¬μš©λ˜λŠ” JavaScript λΌμ΄λΈŒλŸ¬λ¦¬λŠ” HTTP μš”μ²­μ„ μ²˜λ¦¬ν•˜κ³ μž ν•˜λŠ” κ°œλ°œμžλ“€μ—κ²Œ 졜고의 선택이 λ˜μ—ˆμŠ΅λ‹ˆλ‹€. + +이 κΈ°μ‚¬μ—μ„œλŠ” Axios와 Fetchλ₯Ό λΉ„κ΅ν•˜μ—¬ λ‹€μ–‘ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” 방법을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€. 이 글을 마칠 λ•Œμ―€μ΄λ©΄ 두 API에 λŒ€ν•΄ 더 잘 μ΄ν•΄ν•˜κ²Œ 될 κ²ƒμž…λ‹ˆλ‹€. + +### AXIOS + +AxiosλŠ” λ„€νŠΈμ›Œν¬ μš”μ²­μ„ λ§Œλ“œλŠ” 데 μ‚¬μš©λ˜λŠ” third-party HTTP ν΄λΌμ΄μ–ΈνŠΈ λΌμ΄λΈŒλŸ¬λ¦¬μž…λ‹ˆλ‹€. Promiseλ₯Ό 기반으둜 ν•˜λ©° μš”μ²­ 및 응닡을 μ²˜λ¦¬ν•˜κΈ° μœ„ν•œ κΉ”λ”ν•˜κ³  μΌκ΄€λœ APIλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€. + +μ½˜ν…μΈ  배포 λ„€νŠΈμ›Œν¬(CDN) λ˜λŠ” νŒ¨ν‚€μ§€ κ΄€λ¦¬μž(예: npm)λ₯Ό μ‚¬μš©ν•˜μ—¬ ν”„λ‘œμ νŠΈμ— μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 핡심 κΈ°λŠ₯ 쀑 μΌλΆ€λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€: +λΈŒλΌμš°μ € λ‚΄μ—μ„œ XMLHttpRequests μˆ˜ν–‰, node.js ν™˜κ²½ λ‚΄μ—μ„œ http μš”μ²­ μˆ˜ν–‰, μš”μ²­ μ·¨μ†Œ, μš”μ²­ 및 응닡 κ°€λ‘œμ±„κΈ° + +### FETCH + +Axios와 λ§ˆμ°¬κ°€μ§€λ‘œ FetchλŠ” Promise 기반 HTTP ν΄λΌμ΄μ–ΈνŠΈμž…λ‹ˆλ‹€. λ‚΄μž₯ APIμ΄λ―€λ‘œ μ„€μΉ˜ν•˜κ±°λ‚˜ κ°€μ Έμ˜¬ ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. ν˜„λŒ€μ˜ λͺ¨λ“  λΈŒλΌμš°μ €μ—μ„œ μ‚¬μš©ν•  수 있으며 [caniuse](https://caniuse.com/fetch)μ—μ„œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ node.jsμ—μ„œλ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. + +이제 두 인기 μžˆλŠ” 라이브러리λ₯Ό μ΄ν•΄ν•˜κΈ° μœ„ν•΄ κΈ°λ³Έ ꡬ문, κΈ°λŠ₯ 및 μ‚¬μš© 사둀λ₯Ό 비ꡐ해 λ³΄κ² μŠ΅λ‹ˆλ‹€. + +### κΈ°λ³Έ ꡬ문 + +AxiosλŠ” μš”μ²­ λ§€κ°œλ³€μˆ˜(헀더, 데이터, μš”μ²­ λ©”μ„œλ“œ λ“±)λ₯Ό κ°„λ‹¨ν•˜κ²Œ ꡬ성할 수 μžˆλŠ” μ—°κ²° κ°€λŠ₯ν•œ APIλ₯Ό μ œκ³΅ν•˜μ—¬ HTTP μš”μ²­μ„ κ°„μ†Œν™”ν•©λ‹ˆλ‹€. + +λ‹€μŒμ€ Axiosλ₯Ό μ‚¬μš©ν•˜μ—¬ μ‚¬μš©μž μ •μ˜ 헀더와 ν•¨κ»˜ URL에 [POST] μš”μ²­μ„ λ³΄λ‚΄λŠ” λ°©λ²•μž…λ‹ˆλ‹€. AxiosλŠ” 데이터λ₯Ό μžλ™μœΌλ‘œ JSON으둜 λ³€ν™˜ν•˜λ―€λ‘œ 직접 λ³€ν™˜ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. + +```jsx +const axios = require('axios'); + +const url = 'https://jsonplaceholder.typicode.com/posts'; +const data = { + title: 'Hello World', + body: 'This is a test post.', + userId: 1, +}; + +axios + .post(url, data, { + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json;charset=UTF-8', + }, + }) + .then(({ data }) => { + console.log('POST request successful. Response:', data); + }) + .catch((error) => { + console.error('Error:', error); + }); +``` + +ν•΄λ‹Ή μ½”λ“œλ₯Ό fetch API μ½”λ“œμ™€ 비ꡐ해 보면, μ •ν™•νžˆ λ™μΌν•œ κ²°κ³Όλ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€. + +```jsx +const url = 'https://jsonplaceholder.typicode.com/todos'; + +const options = { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json;charset=UTF-8', + }, + body: JSON.stringify({ + title: 'Hello World', + body: 'This is a test post.', + userId: 1, + }), +}; + +fetch(url, options) + .then((response) => response.json()) + .then((data) => { + console.log('POST request successful. Response:', data); + }); +``` + +FetchλŠ” POST μš”μ²­μ— 데이터λ₯Ό λ³΄λ‚΄λŠ” 데 body 속성을 μ‚¬μš©ν•˜λŠ” 반면, AxiosλŠ” data 속성을 ν™œμš©ν•©λ‹ˆλ‹€. AxiosλŠ” μ„œλ²„μ˜ 응닡 데이터λ₯Ό μžλ™μœΌλ‘œ λ³€ν™˜ν•˜μ§€λ§Œ, Fetchλ₯Ό μ‚¬μš©ν•  λ•ŒλŠ” response.json() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ 데이터λ₯Ό JavaScript 객체둜 νŒŒμ‹±ν•΄μ•Ό ν•©λ‹ˆλ‹€. λ˜ν•œ AxiosλŠ” 데이터 응닡을 data 객체 내에 μ „λ‹¬ν•˜λŠ” 반면, FetchλŠ” μ΅œμ’… 데이터λ₯Ό μ–΄λ–€ λ³€μˆ˜μ—λ„ μ €μž₯ν•  수 μžˆλ„λ‘ ν•©λ‹ˆλ‹€. + +### 응닡 및 였λ₯˜ 처리 + +FetchλŠ” λ‘œλ”© ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•œ μ •ν™•ν•œ μ œμ–΄λ₯Ό μ œκ³΅ν•˜μ§€λ§Œ 두 개의 약속을 μ²˜λ¦¬ν•΄μ•Ό ν•˜λ―€λ‘œ λ³΅μž‘μ„±μ΄ μΆ”κ°€λ©λ‹ˆλ‹€. λ˜ν•œ 응닡을 λ‹€λ£° λ•Œ FetchλŠ” .json() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ JSON 데이터λ₯Ό νŒŒμ‹±ν•΄μ•Ό ν•©λ‹ˆλ‹€. 그런 λ‹€μŒ κ²€μƒ‰λœ μ΅œμ’… λ°μ΄ν„°λŠ” μ–΄λ–€ λ³€μˆ˜μ—λ„ μ €μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€. + +HTTP 응닡 였λ₯˜μ˜ 경우 FetchλŠ” μžλ™μœΌλ‘œ 였λ₯˜λ₯Ό λ˜μ§€μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λŒ€μ‹  μ„œλ²„μ—μ„œ 였λ₯˜ μƒνƒœ μ½”λ“œ(예: 404 Not found)λ₯Ό λ°˜ν™˜ν•˜λ”λΌλ„ 응닡을 μ„±κ³΅ν•œ κ²ƒμœΌλ‘œ κ°„μ£Όν•©λ‹ˆλ‹€. + +Fetchμ—μ„œ HTTP 였λ₯˜λ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ²˜λ¦¬ν•˜λ €λ©΄ κ°œλ°œμžλŠ” `.then()` 블둝 λ‚΄μ—μ„œ 쑰건문을 μ‚¬μš©ν•˜μ—¬ `response.ok` 속성을 확인해야 ν•©λ‹ˆλ‹€. `response.ok`κ°€ false이면 μ„œλ²„κ°€ 였λ₯˜ μƒνƒœ μ½”λ“œλ‘œ μ‘λ‹΅ν–ˆμŒμ„ μ˜λ―Έν•˜λ―€λ‘œ κ°œλ°œμžλŠ” ν•΄λ‹Ή 였λ₯˜λ₯Ό 적절히 μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€. + +λ‹€μŒμ€ Fetchλ₯Ό μ‚¬μš©ν•œ [GET] μš”μ²­μž…λ‹ˆλ‹€: + +```jsx +fetch('https://jsonplaceholder.typicode.com/todos') + .then((response) => { + if (!response.ok) { + throw Error(`HTTP error: ${response.status}`); + } + return response.json(); + }) + .then((data) => { + console.log('Data received:', data); + }) + .catch((error) => { + console.error('Error message:', error.message); + }); +``` + +λ°˜λ©΄μ— AxiosλŠ” data 속성에 직접 μ•‘μ„ΈμŠ€ν•  수 있게 ν•˜μ—¬ 응닡 처리λ₯Ό κ°„μ†Œν™”ν•©λ‹ˆλ‹€. 200-299 λ²”μœ„(성곡적인 응닡)λ₯Ό λ²—μ–΄λ‚œ 응닡은 μžλ™μœΌλ‘œ κ±°λΆ€ν•©λ‹ˆλ‹€. `.catch()` 블둝을 μ‚¬μš©ν•˜λ©΄ 응닡을 λ°›μ•˜λŠ”μ§€, λ°›μ•˜λ‹€λ©΄ μƒνƒœ μ½”λ“œκ°€ 무엇인지 λ“± 였λ₯˜μ— λŒ€ν•œ 정보λ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” μ‹€νŒ¨ν•œ 응닡도 ν•΄κ²°λ˜λŠ” fetch와 λŒ€μ‘°λ©λ‹ˆλ‹€. + +λ‹€μŒμ€ Axiosλ₯Ό μ‚¬μš©ν•œ [GET] μš”μ²­μž…λ‹ˆλ‹€: + +```jsx +const axios = require('axios'); + +axios + .get('https://jsonplaceholder.typicode.com/todos') + .then((response) => { + console.log('Data received:', response.data); + }) + .catch((error) => { + if (error.response) { + console.error(`HTTP error: ${error.response.status}`); + } else if (error.request) { + console.error('Request error: No response received'); + } else { + console.error('Error:', error.message); + } + }); +``` + +AxiosλŠ” μžλ™μœΌλ‘œ μ‹€νŒ¨ν•œ 응닡에 λŒ€ν•΄ 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚€λ―€λ‘œ, 였λ₯˜ 처리λ₯Ό κ°„μ†Œν™”ν•˜κ³  κ°œλ°œμžκ°€ 각 μ‘λ‹΅μ˜ 성곡 λ˜λŠ” μ‹€νŒ¨λ₯Ό μˆ˜λ™μœΌλ‘œ ν™•μΈν•˜μ§€ μ•Šκ³ λ„ μ μ ˆν•œ 였λ₯˜ 처리 λ‘œμ§μ„ κ΅¬ν˜„ν•˜λŠ” 데 집쀑할 수 μžˆλ„λ‘ ν•©λ‹ˆλ‹€. + +### HTTP μš”μ²­ 및 응닡 κ°€λ‘œμ±„κΈ°(Intercepting) + +Axios의 μ£Όμš” κΈ°λŠ₯ 쀑 ν•˜λ‚˜λŠ” HTTP μš”μ²­μ„ μΈν„°μ…‰νŠΈν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. HTTP μΈν„°μ…‰ν„°λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ μ„œλ²„λ‘œ λ˜λŠ” κ·Έ λ°˜λŒ€λ‘œ HTTP μš”μ²­μ„ κ²€μ‚¬ν•˜κ±°λ‚˜ λ³€κ²½ν•΄μ•Ό ν•  λ•Œ μœ μš©ν•©λ‹ˆλ‹€. λ‘œκΉ…, 인증 λ˜λŠ” μ‹€νŒ¨ν•œ HTTP μš”μ²­μ„ λ‹€μ‹œ μ‹œλ„ν•˜λŠ” 것과 같은 λ‹€μ–‘ν•œ μž‘μ—…μ— ν•„μˆ˜μ μž…λ‹ˆλ‹€. + +인터셉터λ₯Ό μ‚¬μš©ν•˜λ©΄ 각 HTTP μš”μ²­μ— λŒ€ν•΄ λ³„λ„μ˜ μ½”λ“œλ₯Ό μž‘μ„±ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. HTTP μΈν„°μ…‰ν„°λŠ” μš”μ²­ 및 응닡을 μ²˜λ¦¬ν•˜λŠ” 방법에 λŒ€ν•œ μ „μ—­ μ „λž΅μ„ μ„€μ •ν•˜κ³ μž ν•  λ•Œ μœ μš©ν•©λ‹ˆλ‹€. + +λ‹€μŒμ€ Axiosλ₯Ό μ‚¬μš©ν•˜μ—¬ HTTP μš”μ²­μ„ μΈν„°μ…‰νŠΈν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€: + +```jsx +const axios = require('axios'); + +// 인터셉터 μš”μ²­ 등둝 +axios.interceptors.request.use((config) => { + // HTTP μš”μ²­μ΄ μ „μ†‘λ˜κΈ° 전에 λ©”μ‹œμ§€λ₯Ό κΈ°λ‘ν•©λ‹ˆλ‹€. + console.log('Request was sent'); + return config; +}); + +// GET μš”μ²­ 전솑 +axios + .get('https://jsonplaceholder.typicode.com/todos') + .then(({ data }) => { + console.log('Data received:', data); + }) + .catch((error) => { + console.error('Error:', error.message); + }); +``` + +이 μ½”λ“œμ—μ„œλŠ” `axios.interceptors.request.use()` λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ HTTP μš”μ²­μ΄ μ „μ†‘λ˜κΈ° 전에 μ‹€ν–‰ν•  μ½”λ“œλ₯Ό μ •μ˜ν•©λ‹ˆλ‹€. + +λ˜ν•œ `axios.interceptors.response.use()`λ₯Ό μ‚¬μš©ν•˜μ—¬ μ„œλ²„μ˜ 응닡을 인터셉터할 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ λ„€νŠΈμ›Œν¬ 였λ₯˜κ°€ λ°œμƒν•œ 경우 응닡 인터셉터λ₯Ό μ‚¬μš©ν•˜μ—¬ λ™μΌν•œ μš”μ²­μ„ λ‹€μ‹œ μ‹œλ„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. + +기본적으둜 fetch()λŠ” μš”μ²­μ„ μΈν„°μ…‰νŠΈν•  방법을 μ œκ³΅ν•˜μ§€ μ•Šμ§€λ§Œ, μš°νšŒμ±…μ„ μ°ΎλŠ” 것은 어렡지 μ•ŠμŠ΅λ‹ˆλ‹€. μ „μ—­ fetch() λ©”μ„œλ“œλ₯Ό μž¬μ •μ˜ν•˜κ³  λ‹€μŒκ³Ό 같이 인터셉터λ₯Ό μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. + +λ‹€μŒμ€ Fetchλ₯Ό μ‚¬μš©ν•˜μ—¬ HTTP μš”μ²­μ„ μΈν„°μ…‰νŠΈν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€. + +```jsx +fetch = ((originalFetch) => { + return (...arguments) => { + return originalFetch.apply(this, arguments).then((response) => { + if (!response.ok) { + throw new Error(`HTTP error: ${response.status}`); + } + console.log('Request was sent'); + return response; + }); + }; +})(fetch); + +fetch('https://jsonplaceholder.typicode.com/todos') + .then((response) => response.json()) + .then((data) => { + console.log('Data received:', data); + }) + .catch((error) => { + console.error('Error:', error.message); + }); +``` + +FetchλŠ” Axios에 λΉ„ν•΄ 더 λ§Žμ€ λ³΄μΌλŸ¬ν”Œλ ˆμ΄νŠΈ μ½”λ“œλ₯Ό κ°€μ§€λŠ” κ²½ν–₯이 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ 선택은 μ‚¬μš© 사둀와 개인적인 ν•„μš”μ— 따라 이루어져야 ν•©λ‹ˆλ‹€. + +### 응닡 μ‹œκ°„ 초과 + +응닡 μ‹œκ°„ μ΄ˆκ³ΌλŠ” Fetch와 Axiosλ₯Ό 비ꡐ할 λ•Œ 또 λ‹€λ₯Έ μ€‘μš”ν•œ μ˜μ—­μž…λ‹ˆλ‹€. 응닡 μ‹œκ°„ μ΄ˆκ³ΌλŠ” ν΄λΌμ΄μ–ΈνŠΈκ°€ μ„œλ²„μ˜ 응닡을 κΈ°λ‹€λ¦¬λŠ” μ‹œκ°„μœΌλ‘œ, 이 μ‹œκ°„μ΄ μ§€λ‚˜λ©΄ μš”μ²­μ΄ μ‹€νŒ¨ν•œ κ²ƒμœΌλ‘œ κ°„μ£Όν•©λ‹ˆλ‹€. + +Axiosμ—μ„œ μ‹œκ°„μ„ μ„€μ •ν•˜λŠ” 간결함은 일뢀 κ°œλ°œμžκ°€ Fetch보닀 Axiosλ₯Ό μ„ ν˜Έν•˜λŠ” 이유 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€. Axiosμ—μ„œλŠ” config 객체의 선택적 timeout 속성을 μ‚¬μš©ν•˜μ—¬ μš”μ²­μ΄ μ€‘λ‹¨λ˜κΈ° 전에 λ°€λ¦¬μ΄ˆ λ‹¨μœ„λ‘œ μ‹œκ°„μ„ μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 직관적인 μ ‘κ·Ό 방식은 κ°œλ°œμžκ°€ μš”μ²­ ꡬ성 λ‚΄μ—μ„œ 직접 μ‹œκ°„ 초과 기간을 μ •μ˜ν•  수 있게 ν•˜μ—¬ 더 큰 μ œμ–΄μ™€ κ΅¬ν˜„ μš©μ΄μ„±μ„ μ œκ³΅ν•©λ‹ˆλ‹€. + +λ‹€μŒμ€ Axiosλ₯Ό μ‚¬μš©ν•˜μ—¬ μ§€μ •λœ μ‹œκ°„ μ œν•œμ΄ μžˆλŠ” [GET] μš”μ²­μž…λ‹ˆλ‹€. + +```jsx +const axios = require('axios'); + +// νƒ€μž„μ•„μ›ƒ μ‹œκ°„μ„ λ°€λ¦¬μ΄ˆ λ‹¨μœ„λ‘œ μ •μ˜ν•©λ‹ˆλ‹€. +const timeout = 5000; // 5초 + +// νƒ€μž„μ•„μ›ƒ 속성이 μžˆλŠ” config 객체λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. +const config = { + timeout: timeout, +}; + +// μ§€μ •λœ νƒ€μž„μ•„μ›ƒμœΌλ‘œ GET μš”μ²­μ„ λ³΄λƒ…λ‹ˆλ‹€. +axios + .get('https://jsonplaceholder.typicode.com/todos', config) + .then((response) => { + console.log('Data received:', response.data); + }) + .catch((error) => { + console.error('Error fetching data:', error.message); + }); +``` + +Axiosλ₯Ό μ‚¬μš©ν•˜μ—¬ GET μš”μ²­μ„ 보내고 있으며, 두 번째 인수둜 config 객체λ₯Ό μ „λ‹¬ν•˜μ—¬ μ‹œκ°„ μ œν•œμ„ μ§€μ •ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μš”μ²­μ΄ μ„±κ³΅ν•˜λ©΄ μˆ˜μ‹ ν•œ 데이터가 μ½˜μ†”μ— λ‘œκ·Έλ©λ‹ˆλ‹€. μš”μ²­ 쀑에 였λ₯˜κ°€ λ°œμƒν•˜κ±°λ‚˜ μ‹œκ°„μ΄ 초과되면 였λ₯˜ λ©”μ‹œμ§€κ°€ μ½˜μ†”μ— λ‘œκ·Έλ©λ‹ˆλ‹€. + +FetchλŠ” AbortController μΈν„°νŽ˜μ΄μŠ€λ₯Ό 톡해 μœ μ‚¬ν•œ κΈ°λŠ₯을 μ œκ³΅ν•˜μ§€λ§Œ Axios λ²„μ „λ§ŒνΌ μ§κ΄€μ μ΄μ§€λŠ” μ•ŠμŠ΅λ‹ˆλ‹€. + +λ‹€μŒμ€ Fetchλ₯Ό μ‚¬μš©ν•˜μ—¬ HTTP μš”μ²­μ„ μΈν„°μ…‰νŠΈν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€. + +```jsx +const timeout = 5000; // 5초 +// AbortController μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. +const controller = new AbortController(); +const signal = controller.signal; + +// μ§€μ •λœ νƒ€μž„μ•„μ›ƒ 후에 fetch μš”μ²­μ„ μ€‘λ‹¨ν•˜κΈ° μœ„ν•΄ setTimeout ν•¨μˆ˜λ₯Ό μ„€μ •ν•©λ‹ˆλ‹€. +const timeoutId = setTimeout(() => { + controller.abort(); +}, timeout); + +// μ§€μ •λœ URLκ³Ό μ‹ ν˜Έλ‘œ fetch μš”μ²­μ„ λ³΄λƒ…λ‹ˆλ‹€. +fetch('https://jsonplaceholder.typicode.com/todos', { signal }) + .then((response) => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then((data) => { + console.log('Data received:', data); + }) + .catch((error) => { + // 였λ₯˜κ°€ μš”μ²­μ΄ μ€‘λ‹¨λœ 것 λ•Œλ¬ΈμΈμ§€ ν™•μΈν•©λ‹ˆλ‹€. + if (error.name === 'AbortError') { + console.error('Request timed out'); + } else { + console.error('Error fetching data:', error.message); + } + }) + .finally(() => { + // μš”μ²­μ΄ μ™„λ£Œλœ 후에 νƒ€μž„μ•„μ›ƒμ΄ λ°œμƒν•˜μ§€ μ•Šλ„λ‘ νƒ€μž„μ•„μ›ƒμ„ ν•΄μ œν•©λ‹ˆλ‹€. + clearTimeout(timeoutId); + }); +``` + +5초 νƒ€μž„μ•„μ›ƒμ΄ fetch μš”μ²­μ— μ„€μ •λ˜λ©°, 이 μ œν•œ μ‹œκ°„μ„ μ΄ˆκ³Όν•  경우 μš”μ²­μ„ μ·¨μ†Œν•˜κΈ° μœ„ν•΄ `AbortController`κ°€ μƒμ„±λ©λ‹ˆλ‹€. `setTimeout`을 μ‚¬μš©ν•˜μ—¬ 이 기간이 μ§€λ‚˜λ©΄ μš”μ²­μ„ μ€‘λ‹¨μ‹œν‚€λŠ” 타이머가 μ‹œμž‘λ©λ‹ˆλ‹€. 그런 λ‹€μŒ fetch μš”μ²­μ΄ μ „μ†‘λ˜λ©°, 쀑단 μ‹ ν˜Έκ°€ ν¬ν•¨λ©λ‹ˆλ‹€. 응닡이 λ„μ°©ν•˜λ©΄ 성곡 μ—¬λΆ€λ₯Ό ν™•μΈν•˜κ³  데이터λ₯Ό νŒŒμ‹±ν•©λ‹ˆλ‹€. `timeouts`κ³Ό 같은 였λ₯˜λŠ” μ μ ˆν•˜κ²Œ μ²˜λ¦¬λ©λ‹ˆλ‹€. λ§ˆμ§€λ§‰μœΌλ‘œ, μš”μ²­μ΄ μ™„λ£Œλœ ν›„ λΆˆν•„μš”ν•œ 지연을 ν”Όν•˜κΈ° μœ„ν•΄ νƒ€μž„μ•„μ›ƒμ΄ ν•΄μ œλ©λ‹ˆλ‹€. + +### λ™μ‹œ μš”μ²­ + +Fetch와 Axiosλ₯Ό 비ꡐ할 λ•Œ 또 λ‹€λ₯Έ μ€‘μš”ν•œ μ˜μ—­μ€ λ™μ‹œ μš”μ²­ λ˜λŠ” μ—¬λŸ¬ μš”μ²­μ„ λ™μ‹œμ— ν•  수 μžˆλŠ” κΈ°λŠ₯μž…λ‹ˆλ‹€. 이 κΈ°λŠ₯은 μ„±λŠ₯κ³Ό λ°˜μ‘μ„±μ΄ μ€‘μš”ν•œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ 특히 μ€‘μš”ν•©λ‹ˆλ‹€. + +AxiosλŠ” `axios.all()` λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•˜μ—¬ μ—¬λŸ¬ μš”μ²­μ„ λ™μ‹œμ— ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 λ©”μ„œλ“œμ— μš”μ²­ 배열을 μ „λ‹¬ν•œ ν›„ `axios.spread()`λ₯Ό μ‚¬μš©ν•˜μ—¬ 응닡을 κ°œλ³„ 인수둜 펼칠 수 μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 각 응닡을 κ°œλ³„μ μœΌλ‘œ μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€. + +λ‹€μŒμ€ Axiosλ₯Ό μ‚¬μš©ν•˜μ—¬ λ™μ‹œμ— HTTP μš”μ²­μ„ λ³΄λ‚΄λŠ” λ°©λ²•μž…λ‹ˆλ‹€: + +```jsx +const axios = require('axios'); + +// μš”μ²­μ˜ κΈ°λ³Έ URL μ •μ˜ +const baseURL = 'https://jsonplaceholder.typicode.com/todos'; + +// μš”μ²­μ„ μœ„ν•œ URL μ •μ˜ +const urls = [`${baseURL}/1`, `${baseURL}/2`, `${baseURL}/3`]; + +// Axios μš”μ²­ ν”„λΌλ―ΈμŠ€ λ°°μ—΄ 생성 +const axiosRequests = urls.map((url) => axios.get(url)); + +// `axios.all()`을 μ‚¬μš©ν•˜μ—¬ μ—¬λŸ¬ μš”μ²­μ„ λ™μ‹œμ— 전솑 +axios + .all(axiosRequests) + .then( + axios.spread((...responses) => { + // λͺ¨λ“  μš”μ²­μ˜ 응닡 처리 + responses.forEach((response, index) => { + console.log(`Response from ${urls[index]}:`, response.data); + }); + }) + ) + .catch((error) => { + console.error('Error fetching data:', error.message); + }); +``` + +Fetchλ₯Ό μ‚¬μš©ν•˜μ—¬ λ™μΌν•œ κ²°κ³Όλ₯Ό μ–»κΈ° μœ„ν•΄μ„œλŠ” λ‚΄μž₯된 `Promise.all()` λ©”μ„œλ“œμ— λͺ¨λ“  fetch μš”μ²­μ„ λ°°μ—΄λ‘œ 전달해야 ν•©λ‹ˆλ‹€. 그런 λ‹€μŒ async ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 응닡을 μ²˜λ¦¬ν•©λ‹ˆλ‹€. + +λ‹€μŒμ€ Fetchλ₯Ό μ‚¬μš©ν•˜μ—¬ λ™μ‹œμ— HTTP μš”μ²­μ„ λ³΄λ‚΄λŠ” λ°©λ²•μž…λ‹ˆλ‹€: + +```jsx +// μš”μ²­ν•  base URL μ •μ˜ +const baseURL = 'https://jsonplaceholder.typicode.com/todos'; + +// μš”μ²­ν•  URLs μ •μ˜ +const urls = [`${baseURL}/1`, `${baseURL}/2`, `${baseURL}/3`]; + +// fetch μš”μ²­μ˜ ν”„λ‘œλ―ΈμŠ€λ₯Ό μ €μž₯ν•  λ°°μ—΄ 생성 +const fetchRequests = urls.map((url) => fetch(url)); + +// `Promise.all()`을 μ‚¬μš©ν•˜μ—¬ μ—¬λŸ¬ μš”μ²­μ„ λ™μ‹œμ— 보냄 +Promise.all(fetchRequests) + .then((responses) => { + // λͺ¨λ“  μš”μ²­μ˜ 응닡을 처리 + responses.forEach((response, index) => { + if (!response.ok) { + throw new Error(`Request ${urls[index]} failed with status ${response.status}`); + } + response.json().then((data) => { + console.log(`Response from ${urls[index]}:`, data); + }); + }); + }) + .catch((error) => { + console.error('Error fetching data:', error.message); + }); +``` + +이 μ ‘κ·Ό 방식은 μ‹€ν–‰ κ°€λŠ₯ν•˜μ§€λ§Œ, 비동기 ν”„λ‘œκ·Έλž˜λ° κ°œλ…μ— μ΅μˆ™ν•˜μ§€ μ•Šμ€ κ°œλ°œμžλ“€μ—κ²ŒλŠ” 좔가적인 λ³΅μž‘μ„±κ³Ό μ˜€λ²„ν—€λ“œλ₯Ό μ΄ˆλž˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. + +### ν•˜μœ„ ν˜Έν™˜μ„± + +ν•˜μœ„ ν˜Έν™˜μ„±μ€ μ†Œν”„νŠΈμ›¨μ–΄ μ‹œμŠ€ν…œμ΄λ‚˜ μ œν’ˆμ΄ μ’…μ†μ„±μ˜ 이전 버전과 ν•¨κ»˜ μ‚¬μš©λ˜κ±°λ‚˜ 이전 ν™˜κ²½μ—μ„œ μ‚¬μš©λ  λ•Œμ—λ„ μ˜¬λ°”λ₯΄κ²Œ λ˜λŠ” 효과적으둜 μž‘λ™ν•  수 μžˆλŠ” λŠ₯λ ₯을 λ§ν•©λ‹ˆλ‹€. + +AxiosλŠ” 기본적으둜 더 λ‚˜μ€ ν•˜μœ„ ν˜Έν™˜μ„±μ„ μ œκ³΅ν•˜λ©°, 이전 μ‹œμŠ€ν…œμ΄λ‚˜ μ½”λ“œλ² μ΄μŠ€μ™€μ˜ ν˜Έν™˜μ„±μ„ μš©μ΄ν•˜κ²Œ ν•˜λŠ” μΆ”κ°€ κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€. Axios의 μ£Όμš” μž₯점 쀑 ν•˜λ‚˜λŠ” XMLHttpRequestλ₯Ό 기반으둜 ν•˜μ—¬ IE11κ³Ό 같은 였래된 λΈŒλΌμš°μ €λ₯Ό ν¬ν•¨ν•œ κ΄‘λ²”μœ„ν•œ λΈŒλΌμš°μ €λ₯Ό μ§€μ›ν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. + +λ°˜λ©΄μ— FetchλŠ” Chrome, Firefox, Edge, Safari와 같은 ν˜„λŒ€ λΈŒλΌμš°μ €λ₯Ό 주둜 λŒ€μƒμœΌλ‘œ ν•˜λŠ” 더 μ œν•œλœ λΈŒλΌμš°μ € 지원을 μ œκ³΅ν•©λ‹ˆλ‹€. Fetch의 κΈ°λŠ₯이 μ§€μ›λ˜μ§€ μ•ŠλŠ” λΈŒλΌμš°μ €μ—μ„œ ν”„λ‘œμ νŠΈλ₯Ό 진행해야 ν•˜λŠ” 경우 'whatwg-fetch'와 같은 polyfill을 ν†΅ν•©ν•˜μ—¬ 격차λ₯Ό ν•΄μ†Œν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 폴리필은 Fetch 지원을 였래된 λΈŒλΌμš°μ €λ‘œ ν™•μž₯ν•˜μ—¬ ν˜Έν™˜μ„±μ„ 보μž₯ν•©λ‹ˆλ‹€. + +μ‚¬μš©ν•˜λ €λ©΄ npm λͺ…령을 μ‚¬μš©ν•˜μ—¬ μ„€μΉ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€: + +```bash +npm install whatwg-fetch - save +``` + +κ·Έλ‹€μŒμ—λŠ” λ‹€μŒκ³Ό 같이 μš”μ²­μ„ 보낼 수 μžˆμŠ΅λ‹ˆλ‹€: + +```jsx +import 'whatwg-fetch' + +window.fetch(…) +``` + +일뢀 였래된 λΈŒλΌμš°μ €μ—μ„œλŠ” promise polyfill이 ν•„μš”ν•  μˆ˜λ„ μžˆλ‹€λŠ” 점을 μœ μ˜ν•΄ μ£Όμ„Έμš”. + +### κ²°λ‘  + +AxiosλŠ” 간결함, 견고함, κ΄‘λ²”μœ„ν•œ λΈŒλΌμš°μ € μ§€μ›μœΌλ‘œ 인해 였래된 λΈŒλΌμš°μ €μ™€μ˜ ν•˜μœ„ ν˜Έν™˜μ„±μ΄ ν•„μš”ν•œ ν”„λ‘œμ νŠΈμ— 이상적인 μ„ νƒμž…λ‹ˆλ‹€. λ°˜λ©΄μ— FetchλŠ” 슀트리밍 κΈ°λŠ₯κ³Ό λ‹€λ₯Έ μ›Ή ν”Œλž«νΌ API와 μ›ν™œν•˜κ²Œ μž‘μ—…ν•  수 μžˆλŠ” κΈ°λŠ₯을 μ§€μ›ν•˜λŠ” λΈŒλΌμš°μ €μ— 직접 λ‚΄μž₯된 보닀 λ„€μ΄ν‹°λΈŒν•œ μ ‘κ·Ό 방식을 μ œκ³΅ν•©λ‹ˆλ‹€. + +Axios와 Fetch μ€‘μ—μ„œ 선택할 λ•Œ κ°œλ°œμžλŠ” μ‚¬μš© νŽΈμ˜μ„±, μ„±λŠ₯ 고렀사항, λΈŒλΌμš°μ € ν˜Έν™˜μ„± 및 ν•„μš”ν•œ μΆ”κ°€ κΈ°λŠ₯ λ“± ν”„λ‘œμ νŠΈ μš”κ΅¬ 사항을 μ‹ μ€‘ν•˜κ²Œ 평가해야 ν•©λ‹ˆλ‹€.