2. Fetch API & CORS
Fetch API ๋
Promise
ReadableStream
Unicode
CORS ๋
๊ฐ์ ์ ๋ฆฌ
Fetch API๋
์น ๋ธ๋ผ์ฐ์ ์์ ์ฐ๋ ๊ฒ
XMLHttpRequests๋ฅผ ์ถ์ํ ์์ผ๋์ ๊ฒ์ด axios๋ค. Fetch๋ฅผ ์ถ์ํ ์์ผ ๋์ ๊ฒ์ ky์ด๋ค.
http client๋ก ์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์ข์๊น? ๊ณ ๋ฏผ์ ํด๋ณด๋ฉด ์ฌ๋ฐ์ ๊ฒ ๊ฐ๋ค. toss์์๋ @toss/ky๋ฅผ ์คํ์์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋ฐํํ๋๋ฐ ์ ky๋ฅผ ์ ํํ์๊น?
Fetch๋ ์๋ฒ์ ํต์ ์ ํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๊ทธ๋๋ก ์ฌ์ฉํ๋ฉด Promise ๊ฐ์ฒด๊ฐ pending์ธ ์ํ๋ผ์ ๊ฐ์ ๋ฐ๋ก ๋ฐ์์ฌ ์ ์๋ค. then ๋ฉ์๋ ํน์ async/await ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ๋๋ ํ์ ๊ฐ์ ๋ฐ์์์ผ ํ๋ค.
// response์ body์๋ ReadableStream ํํ์ ๊ฐ์ด ๋ค์ด์๋ค.
const response = await fetch('http://localhost:3000/products');
// reader๋ฅผ ์ป๋๋ค.
const reader = response.body.getReader();
// chunk์ value๊ฐ์๋ Uint8Array ํ์์ ๋ฐ์ดํธ ๊ฐ์ด ๋ค์ด์๋ค.
// chunk๋ value์ done์ key๋ก ๊ฐ๊ณ ์๋ ๊ฐ์ฒด์ธ๋ฐ, done์ด true๊ฐ ๋ ๋๊น์ง ์ฝ์ด์ผ ํ๋ค.
// ๋ด๋ถ์ ์ผ๋ก Generator๋ก ๊ตฌํ์ด ๋์ด ์๋ ๊ฒ ๊ฐ๋ค.
const chunk = await reader.read();
// chunk์ value๋ byte array๊ธฐ ๋๋ฌธ์ string์ผ๋ก ๋ฐ๊ฟ์ฃผ๊ณ ์ถ๋ค.
// decode๋ฅผ ํ ๊ฒ์ JSON.parse ํด์ฃผ๋ฉด ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ฐ์ด ๋ค์ด์ค๊ฒ ๋๋ค.
JSON.parse(new TextDecoder().decode(chunk.value));
์ค์ ๋ก๋ JSON์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ๊ธฐ ๋๋ฌธ์ ๋ณต์กํ๊ฒ ํ์ง ์์๋ ๋๋ค.
const response = await fetch('http://localhost:3000/products');
const data = await response.json();
๊ธฐ๋ณธ์ ์ผ๋ก fetch์ ์ฒซ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ก url๋ง ๋ฃ๊ฒ ๋๋ฉด GET ์์ฒญ์ ํ๊ฒ ๋๋ค. ๋ค๋ฅธ HTTP Method๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ผ๋ฉด option์ ์ง์ ํด์ค๋ค.
const response = fetch(url, {
method: 'POST',
});
React์์ fetch ์ฌ์ฉํ๊ธฐ
const url = 'http://localhost:3000/products';
const response = await fetch(url);
const data = await response.json();
const { products } = data;
CORS(Cross-Origin Resource Sharing) ์๋ฌ๊ฐ ๋ฐ์ํ๋ค. ์น ๋ธ๋ผ์ฐ์ ๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ์ง๊ณ ์๋ ๋ณด์ ์ ์ฑ ์ด๋ค. SOP(same-origin policy)๋ ๋์ผํ ์ถ์ฒ์์๋ง, ๊ฐ์ ๊ณณ์์ ์ป์ด์ง๋ ๊ฒ๋ง ์ฌ์ฉํด์ผ ํ๋ค๋ ์์น์ด๋ค. ์๋ก ๋ค๋ฅธ ์ถ์ฒ์ผ ๋, ์๋ฒ์์ ์ป์ ์ ๋ณด๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋ง๋๋ค.
์ฃผ์ํ ์ ์ ์๋ฒ์ ์์ฒญ์ด ๊ฐ๊ณ , ์๋ฒ๊ฐ ์๋ต์ ํด์คฌ์ง๋ง ๋ธ๋ผ์ฐ์ ์์ ๋์ผ ์ถ์ฒ๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ๋ง๋ ๊ฒ์ด๋ค. ์์ฑ์ ํ๊ฑฐ๋ ์ ๋ฐ์ดํธ๋ฅผ ํ๋ฉด CORS์๋ฌ๊ฐ ๋จ๋๋ผ๋ ์งํ์ด ๋ ๊ฒ์ด๋ค.
REST API ์๋ฒ์์ Headers์ 'Access-Control-Allow-Origin' ์์ฑ์ ์ถ๊ฐํ๋ฉด ๋๋ค. ์ค์ ๋ก CORS ์ค์ ์ ๋ณต์กํ๊ฒ ํ ์ ์์ง๋ง, *์ ์ด์ฉํ์ฌ ๊ธฐ๋ณธ์ ์ผ๋ก๋ง ์ค์ ํ ๊ฒ. cors ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ์ฌ Express ์ฑ์์ CORS ์ธํ ์ ํ๋ค.
app.use(cors());
๋ฐฑ์๋ api ํ์์ ์กฐ๊ธ ์์ ํ๊ณ ์ถ๋ค๊ฑฐ๋, ์ค์ผ์ฅด์ ๋ฌธ์ ๋ก ์์ง api๊ฐ ๋์ค์ง ์์๋ค๋ฉด ๊ธฐ๋ค๋ฆฌ์ง ๋ง๊ณ ์ ์ ์ธ ๊ฒ๋ ๊ด์ฐฎ์ผ๋ ๊ฐ๋จํ๊ฒ ๊ตฌ์ฑํด์ ์งํํ ์๋ ์๋ค. ์ค์ ๋ก Express๋ฅผ ์ด์ฉํด์ ๋ก์ปฌ์์ ์๋ฒ๋ฅผ ๊ตฌ์ฑํ๋ฉด ์กฐ๊ธ ๋น์ฉ์ด ๋ค ๊ฒ ๊ฐ๊ณ ๋๋ฏธ ๋ฐ์ดํฐ๋ MSW๋ฅผ ์ด์ฉํ๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
CORS
๊ฐ์ ์ถ์ฒ์ธ์ง ๋ค๋ฅธ ์ถ์ฒ์ธ์ง ๊ตฌ๋ถํ๋ ์กฐ๊ฑด์ 3๊ฐ์ง ์์๋ค.
Scheme, Host, Port
https://megaptera.kr
๋ฅผ ์๋ก ๋ค๋ฉด,
Scheme์ https:// Host๋ megaptera.kr
Port๋ https์ด๊ธฐ ๋๋ฌธ์ 443์ด๋ค
CORS๊ฐ ๋์ํ๋ ๋ฐฉ์์ ์ธ ๊ฐ์ง์ ๊ฒฝ์ฐ๊ฐ ์๋ค.
Preflight Request
์๋น ์์ฒญ๊ณผ ๋ณธ ์์ฒญ์ ๋๋์ด์ ์๋ฒ์ ์ ์กํ๋ค.
OPTIONS ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ ์๋น ์์ฒญ์ ๋ณด๋ด๊ฒ ๋๋๋ฐ ์ด๋ CORS ์ ์ฑ ์ ์๋ฐํ๋์ง ํ๋จํ๋ค.
Simple Request
์๋น ์์ฒญ์ ๋ณด๋ด์ง ์๊ณ ๋ฐ๋ก ์๋ฒ์ ์์ฒญ์ ๋ณด๋ด๋ ๋ฐฉ์์ด๋ค.
ํน์ ์ํฉ์์๋ง ๋ฐ์ํ๊ณ , ์กฐ๊ฑด์ด ๋งค์ฐ ๊น๋ค๋กญ๋ค.
Credentialed Request
์ฟ ํค์ ๊ฐ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ํค๋์ ํฌํจํ๋ ๋ฐฉ์์ด๋ค.
credentials ์ต์ ์ ์ฌ์ฉํ๋๋ฐ, ์ด๋ ์๋ฒ์์๋ ์ด์ ๋ง๋ ์ค์ ์ ํด์ค์ผ ํ๋ค.
CORS๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์๋ ํฌ๊ฒ 2๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค.
๋จผ์ ์๋ฒ์์ Access-Control-Allow-Origin ์ธํ ์ ํด์ค๋ค. Node.js ๊ธฐ๋ฐ ์๋ฒ ํ๋ ์์ํฌ(Express, NestJS๋ฑ)์์๋ Cors ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ๋ค.
ํ๋ก ํธ๋จ์์ ํ๋ก์ ์๋ฒ๋ฅผ ๋๋ค.
Last updated