ํน์ ์ ๋ณด๊ฐ ํ์ํ ๋ ํด๋ผ์ด์ธํธ๋ ์๋ฒ์ HTTP ํต์ ์ผ๋ก ์์ฒญ(request)์ ๋ณด๋ด๊ณ , ์ ๋ณด๋ฅผ ์๋ต(response) ๋ฐ์ ์ ์๋ค.
์ด๋ ์ฌ์ฉ๋๋ ๋ฉ์๋๊ฐ fetch ๋ฉ์๋์ด๋ค.
ํด๋ผ์ด์ธํธ๋ fetch ๋ฉ์๋๋ก ์๋ฒ๋ก ๋ฐ์ดํฐ๋ฅผ ์์ฒญํด์ ๋ฐ์ ์๋ ์๊ณ , ๋ฐ์ดํฐ๋ฅผ ์์ฑ, ์์ , ์ญ์ ํ ์ ์๋ค.
fetch ๋ฉ์๋๋ฅผ ํธ์ถํ ๋, ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ API ์ฃผ์์ ์ ๋ณด๋ฅผ ๋ฌ๋ผ๊ณ ์์ฒญํ๊ณ ์๋ต์ ๋ฐ๋๋ค.
์๋์ ํํ๊ฐ fetch ๋ฉ์๋์ ๊ธฐ๋ณธ ๊ตฌ์กฐ์ด๋ค.
// fetch ์ ๋ฌธ ์์
fetch('api์ฃผ์', {
method: '...',
headers: { 'key': 'value' },
body: JSON.stringify({ 'key': 'value' }),
}) //์์ฒญ
.then((response) => response.json())
.then((data) => console.log(data));
//์๋ต
fetch ๋ฉ์๋๋ฅผ ํธ์ถํ ๋. ์ธ์ 2๊ฐ๋ฅผ ์ ๋ฌํ ์ ์๋ค. ์ฒซ ๋ฒ์งธ ์ธ์ ์๋ฆฌ์๋ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ API ์ฃผ์๋ฅผ ํ์๋ก ๋ฃ๋๋ค. ๋ ๋ฒ์งธ ์ธ์๋ ์์ฒญ์ ์ต์
๊ฐ๋ค๋ก ํ์์ ๋ฐ๋ผ ๊ฐ์ฒด ํํ๋ก ๋ฃ์ ์ ์๋๋ฐ, method, headers, body, mode, credentials, omit, same-origin, include, cache, redirect, referrer, referrerPolicy, integrity, keepalive, signal๋ฑ์ key์ ๊ฐ๊ฐ ํด๋นํ๋ value๋ฅผ ๋ฃ์ ์ ์๋ค.
์ฌ๊ธฐ์์ ์ค์ํ ๊ฑด, ํด๋ผ์ด์ธํธ์ ์
์ฅ์์ ์๋ฒ์๊ฒ ์์ฒญํ๋ ๊ฒ์ด๋ค.์ด๋์์ ์์ฒญํ๊ณ , ์ด๋์์ ์๋ต๋ฐ๋์ง ๋ฐฉํฅ์ด ํผ๋๋๋ฉด ๊ฐ๋
์ ๋ฆฝ์ ์ข ๋ ๋ง์ ์๊ฐ์ด ํ ์ ๋ ์ ์๋ค.
fetch๋ ํฌ๊ฒ ์์ฒญ๊ณผ ์๋ต ๋ถ๋ถ์ผ๋ก ๋๋ ์ ์๋๋ฐ ์ฌ๊ธฐ์๋ ๋ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ๋ ๊ฐ์ฒด์ key์ค ์์ฃผ ์ฌ์ฉํ๋ method, headers, ๊ทธ๋ฆฌ๊ณ body๊ฐ ์๋ ์์ฒญ๊ณผ body๊ฐ ์๋ ์์ฒญ์ผ๋ก ๋๋ ์ ์๋ค.
fetch()์ฒซ ๋ฒ์งธ ์ธ์ ์๋ฆฌ์ ์ ๋ณด๋ฅผ ์์ฒญํ API ์ฃผ์๋ฅผ ์
๋ ฅํ๋ค. API ์ฃผ์๋ ์๋ฒ์์ ๋ฐ์์ผ ํ๋ค.
API ์ฃผ์๋ http:// ํน์ https://, IP ์ฃผ์(with ํฌํธ๋ฒํธ) ํน์ ๋๋ฉ์ธ ์ฃผ์, ์๋ ํฌ์ธํธ๋ก ๊ตฌ์ฑ๋ผ์๋ค.
// ์ฒซ๋ฒ์งธ ์ธ์ ์์
fetch('http://10.58.113.116:8000/sign-in');
fetch('https://jsonplaceholder.typicode.com/posts');
์ด๋ค method๋ก ์์ฒญํ ์ง ์ ๋๋ค.
(GET, POST, PUT, PATCH, DELETE ...)
// method ์์
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
});
headers ๋ ์๋ฒ์ ์์ฒญํ ๋ ๋ณด๋ผ ๋ถ๊ฐ์ ์ธ ์ ๋ณด๋ฅผ ๋ด๋๋ค.
(HOST, user-Agent, Authorization, Content-Type ...)
// headers ์์
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8',
},
});
body์๋ ์๋ฒ์ ์์ฒญํ ๋ ๋ณด๋ผ ์ค์ง์ ์ธ ์ ๋ณด๋ฅผ ๋ด๋๋ค.
์ฌ๊ธฐ์์ ์์ฒญ body๊ฐ ์๋ ๊ฒฝ์ฐ์ ์๋ ๊ฒฝ์ฐ๋ก ๋๋ ์ ์๋ค.
์๋ฒ์ ๋ณด๋ผ ์ ๋ณด๊ฐ ์๋ ๊ฒฝ์ฐ, ์์ฒญ body์ ๋ด์์ ๋ณด๋ธ๋ค. ๊ทธ๋ฐ๋ฐ body value๋ฅผ ๋ณด๋ฉด JSON.stringify๋ผ๋ ๋ฉ์๋์ ๋ด์์ ๋ณด๋ด๊ณ ์๋ค.
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8',
},
body: JSON.stringify({
title: 'update title',
content: '์๋ฒ์ ์์ฒญํ ๋ ๋ด์์ ๋ณด๋ด๋ ์ ๋ณด',
}),
});
body์ ๋ด๊ธด ์ ๋ณด๋ฅผ ์๋ฒ๋ก ๋ณด๋ผ ๋ ๋ฐ์ดํฐ ํํ๋ฅผ JSON ํํ๋ก ๋ณด๋ด๊ณ ๋ฐ์์ผ ํ๋๋ฐ, JSON์ผ๋ก ํ ๋ณํ์ ํด์ฃผ๋ ๋ฉ์๋๊ฐ JSON.stringify์ด๋ค.
๐ก์ JSON์ผ๊น ?
ํต์ ๊ฐ, ์๋ฒ์ ํด๋ผ์ด์ธํธ๋ ๊ฐ์ ์ธ์ด์ผ ์๋ ์๊ณ , ๋ค๋ฅธ ์ธ์ด์ผ ์๋ ์๋ค. ๊ฐ์ ์ธ์ด๋ผ๋ฉด ๋ฌธ์ ๊ฐ ์๊ฒ ์ง๋ง ๋ค๋ฅธ ์ธ์ด๋ผ๋ฉด ์ฃผ๊ณ ๋ฐ์ ์๊ฐ ์๋ค.
JSON ํํ๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ค ์ธ์ด์์๋ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ์ ์๋ค. JSON์ ํํ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ฐ์ฒด์ ์ ์ฌํ์ง๋ง, javascript๊ฐ ์๋๋๋ผ๋ JSON์ ์ฝ๊ณ ์ธ ์ ์๋ ๊ธฐ๋ฅ์ด ๋๋ถ๋ถ ์ธ์ด์์ ์ ๊ณต๋๋ค.
๊ทธ๋์ JSON ํํ๋ก ํต์ ์ ์ฃผ๊ณ ๋ฐ์์ผ ํ๋ค. ๋ฉ์๋ ์ฌ์ฉ ๋ฐฉ๋ฒ์ JSON.stringify ๋ฉ์๋ ์ธ์์ ๋ฐ์ดํฐ๋ฅผ ๋ด์ผ๋ฉด, JSON๋ฌธ์์ด๋ก ๋ฐํ๋๋ค.
//JSON.stringify๋ก ๋ณํ๋ body ํํ ์์
// object
{
title: 'update title',
content: '์๋ฒ์ ์์ฒญํ ๋ ๋ด์์ ๋ณด๋ด๋ ์ ๋ณด',
};
// JSON
{ "title": "update title", "content": "์๋ฒ์ ์์ฒญํ ๋ ๋ด์์ ๋ณด๋ด๋ ์ ๋ณด" }
// JSON.stringify ํ ๋ณํ ์์
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""
์์ฒญ body๊ฐ ์๋ ๊ฒฝ์ฐ๋ ์๋ฒ์ ์ ๋ฌํด ์ค ์ ๋ณด ์์ด ์ ๋ณด๋ง ๋ฌ๋ผ๊ณ ์์ฒญ๋ง ํ๋ค.
//body๊ฐ ์๋ ์์ฒญ ์์
fetch('https://jsonplaceholder.typicode.com/users/1', { method: 'GET' });
console.log(1);
console.log(2);
setTimeout(() => console.log(3), 3000);
console.log(4);
//output
1
2
4
3
์์ ์ฝ๋๋ฅผ ๋ณด๋ฉด 1,2,3,4 ๋ก ์ถ๋ ฅ๋๋ ๊ฒ์ด ์๋๋ผ 1,2,4,3์ผ๋ก ์ถ๋ ฅ์ด ๋๋ค.
์ด์ ๋ setTimeout ๋ฉ์๋๊ฐ ๋น๋๊ธฐ ํจ์์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๋๊ธฐ(synchronous)์ ์ธ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ด์ ์ ์์
์ด ๋๋์ผ ๋ค์ ์์
์ผ๋ก ์ด์ด์ง๋ ์ฒ๋ฆฌ ๋ฐฉ์์ด๋ค.
์ด ๋ฐฉ์์ ์ค๊ณ๊ฐ ๋น๊ต์ ๊ฐ๋จํ๊ณ ์ฒ๋ฆฌ์ ์์๋ฅผ ํ์
ํ๊ธฐ ์ฉ์ดํ๋ค.
๋ค๋ง, ์ด์ ์ฒ๋ฆฌ๊ฐ ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํด์ ์ฐ์ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๊ฑฐ๋, ์ธ์ ์ข
๋ฃ๋ ์ง ๋ชจ๋ฅด๋ ์์ธก ๋ถ๊ฐ๋ฅํ ์ฒ๋ฆฌ ๋ฐฉ์์๋ ์๋ฌด๊ฒ๋ ๋ชปํ๊ณ ๊ธฐ๋ค๋ ค์ผ๋ง ํ๋ ๋จ์ ์ด ์๋ค.
๋น๋๊ธฐ(asynchronous)์ ์ธ ์ฒ๋ฆฌ๋ฐฉ์์ ์ด์ ์์ ์ ์ข ๋ฃ ์ฌ๋ถ์ ์๊ด์์ด ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋ค๋ฅธ ์์ ์ ํ ์ ์๋ค. ๋๊ธฐ์ ์ธ ๋ฐฉ์๋ณด๋ค๋ ๋ณต์กํ๋ค๋ ๋จ์ ์ด ์๋ค.
๊ทธ๋์ ํต์ ์ ์ค๊ฐ์ ์ธํฐ๋ท ์ฐ๊ฒฐ์ด ๋๊ธด๋ค๊ฑฐ๋, ์๋๊ฐ ๋๋ ค ์ธ์ ํต์ ์ด ๋๋ ์ง ์์ธกํ๊ธฐ ์ด๋ ต๋ค.
๊ทธ๋์ ํต์ ์ ๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ฉด ํ๋ฉด์ ์๋ฌด๊ฒ๋ ์ถ๋ ฅ๋์ง ์์ ์ฑ ๋ง๋ฅ ๊ธฐ๋ค๋ ค์ผ ํ ์๋ ์๊ณ , ์๋ฌ ํ๋ฉด์ด ๋์ค๋ฉด์ ์ ์์ ์ธ ์ ๊ทผ์ด ์ด๋ ค์ธ ์๋ ์๋ค.
๊ทธ๋์ ํต์ ๊ณผ์ ์ ๋๊ธฐ์ ์ธ ์ฒ๋ฆฌ ์์์ ์ํฅ์ ์ฃผ์ง ์๋๋ก ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํด์ผ ํ๊ณ , fetch ํจ์๋ ๊ทธ๋์ ๋น๋๊ธฐ์ ์ผ๋ก ๋์ํ๋๋ก ์ค๊ณ๋์ด ์๋ค.
.then() ๋ฉ์๋๋ Promise๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ๋ฉ์๋์ด๋ค.
.then()์ Promise๋ฅผ ๋ฆฌํดํ๊ณ ๋ ๊ฐ์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ๋๋ค. ํ๋๋ Promise๊ฐ ์ดํ๋ฌ์ ๋, ๋ค๋ฅธ ํ๋๋ ๊ฑฐ๋ถํ์ ๋๋ฅผ ์ํ ์ฝ๋ฐฑ ํจ์์ด๋ค.
.then() ๋ฉ์๋๋ Promise๋ฅผ ๋ฆฌํด ํ๊ธฐ ๋๋ฌธ์ ์ฒซ๋ฒ์งธ .then()์์ ๋ฐํ๋ ๊ฐ์ ๋๋ฒ์งธ .then()์ ์ด์ด์ ์ฒ๋ฆฌํ ์ ์๋ ๋ฉ์๋ ์ฒด์ด๋(chaning)์ด ๊ฐ๋ฅํ๋ค.
.then() ๋ฉ์๋ ๋ฌธ๋ฒ
.then(function onFullfilled, [function onRejected]
์์ฒญ์ ํ์ผ๋ฉด ์๋ต์ ๋ฐ์ ์ฐจ๋ก์ด๋ค.
์๋์ ์ฝ๋๋ฅผ ๋ณด๋ฉด .then() ๋ฉ์๋๊ฐ 2๋ฒ ๋์จ๋ค.
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8',
},
body: JSON.stringify({
title: 'update title',
content: '์๋ฒ์ ์์ฒญํ ๋ ๋ด์์ ๋ณด๋ด๋ ์ ๋ณด',
}),
})
//์์ฒญ
.then((response) => response.json())
.then((data) => console.log(data));
//์๋ต
์ฒซ ๋ฒ์งธ ์๋ต์ ๋ฐํํ๋ then์ ์ฝ๋ฐฑ์ response๋ผ๋ ๋งค๊ฐ๋ณ์๋ฅผ console.log๋ก ์คํํด ๋ณด๋ฉด ์๋์ ๊ฐ์ด ๋ฐํ๋๋ค.
์๋๋ response๋ฅผ console๋ก ์ถ๋ ฅํ ์ฝ๋์ด๋ค. response ๊ฐ์ฒด์ ์ฌ๋ฌ๊ฐ์ง key๊ฐ ๋ฐํ๋๋๋ฐ, ์ฌ๊ธฐ์ ๋ฐํ๋ key๋ฅผ ํ์ฉํด ๊ทธ ๋ค์ ์ฒ๋ฆฌ ๋ฐฉ๋ฒ์ ํ๋จํ ์ ์๋ค.
-์์ฒญ ์ฑ๊ณต-
-์์ฒญ ์คํจ-
ํต์ ์ ์ฑ๊ณต, ์คํจ ์ฌ๋ถ๋ฅผ ํ๋จํ๋ ๊ธฐ์ค์ status์ด๋ค. status๋ statuscode๋ฅผ ์๋ฏธํ๋ค. ํต์ ์ฑ๊ณต์ 200 - 299์ผ ๋ ok๊ฐ์ด true์ด๊ณ , ํต์ ์ด ์คํจํ ๊ฒฝ์ฐ statuscode๊ฐ 400 - 499 | 500 - 599์ด๊ณ ok ๊ฐ์ false๋ก ๋ฐํ๋๋ค.
//์ฒซ๋ฒ์งธ ์๋ต ๋ถ๊ธฐ์ฒ๋ฆฌ ์์
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8',
},
body: JSON.stringify({
title: 'update title',
content: '์๋ฒ์ ์์ฒญํ ๋ ๋ด์์ ๋ณด๋ด๋ ์ ๋ณด',
}),
})
.then((response) => {
if (response.ok === true) {
return response.json();
}
throw new Error('์๋ฌ ๋ฐ์!'); //reponse.ok๊ฐ true๊ฐ ์๋ ๊ฒฝ์ฐ error๋ฅผ throw
})
.catch((error) => console.log(error)); //throw๋ error๋ฅผ ๋ฐ์์ console์ ์ถ๋ ฅ
ํต์ ์ ์ฑ๊ณต๊ณผ ์คํจ ์ฌ๋ถ๋ฅผ ์์ธกํ๊ธฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ์ฒซ ๋ฒ์งธ ์๋ต๋ฐ์ status ์ฝ๋์ ๋ฐ๋ผ ์ฒ๋ฆฌ ๋ฐฉ๋ฒ์ ๋๋ ์ ์๋ค. ํต์ ์ ์ฑ๊ณตํ๋ฉด response์ body๋ฅผ ๊ฐ์ฒด๋ก ๋ง๋๋ ๋ฉ์๋๋ฅผ ํธ์ถํ๊ณ , ํต์ ์ ์คํจํ๋ฉด console์ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ ์์์ด๋ค. ๋ง์ฝ ์คํจํ๋ฉด ์์ธ์ ์ฐพ์ ์์ ํ๋ค.
์ฌ๊ธฐ์ ํต์ ์ ์ฑ๊ณตํ๋ฉด ์๋ต๋ฐ์ response ๊ฐ์ฒด ์ค body์ ๊ฐ์ JSON ํํ์ด๋ค.
JSON์ ์๋ฐ์คํธ๋ฆฝใ
ํธ์ ๋ฌธ๋ฒ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐ์ดํฐ ํ์
์ผ๋ก ๋ง๋ค์ด์ผ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํ ์ ์๋ค.
์ฒซ ๋ฒ์งธ then์์ response.json()๋ฉ์๋๊ฐ JSON ํํ๋ฅผ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๋ก ๋ณํํด์ฃผ๋ ๋ฉ์๋์ด๋ค. ์ด๋ ๊ฒ ์ฒซ๋ฒ์งธ then์์ JSON์์ ๊ฐ์ฒด๋ก ๋ณํ๊ณ , ๋ฆฌํด๋ ๊ฐ์ฒด๋ ๋๋ฒ์งธ then() ๋ฉ์๋๋ก ๋๊ฒจ์ง๋ค.
ํต์ ์ ์ฑ๊ณตํด์ JSON์ ๊ฐ์ฒด๋ก ๋ณํํ๋ค๋ฉด, ๋ณํ๋ ๊ฐ์ฒด๋ฅผ ํ์ฉํด์ ๋ถ๊ธฐ ์ฒ๋ฆฌํ ์ ์๋ค.
//๋๋ฒ์งธ ์๋ต ๋ถ๊ธฐ์ฒ๋ฆฌ ์์
fetch('๋ก๊ทธ์ธ API', {
method: 'post',
body: JSON.stringify({
id: 'qawsedrf',
password: '123456',
}),
})
.then((response) => {
if (response.ok === true) {
return response.json();
}
throw new Error('์๋ฌ ๋ฐ์!');
})
.catch((error) => console.log(error))
.then((data) => {
if (data.message === 'login success') {
localStorage.setItem('TOKEN', data.token);
alert('๋ก๊ทธ์ธ ์ฑ๊ณต');
} else {
alert('๋ก๊ทธ์ธ ์คํจ');
}
});
//data ์์
data: {
message: 'login success',
token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo1fQ.Dy3PPHIOFFe3ScGTb8x3hewItnpOcgC9YDdW7v27XHg',
},