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๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹์€ ์„ธ ๊ฐ€์ง€์˜ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

  1. Preflight Request

    1. ์˜ˆ๋น„ ์š”์ฒญ๊ณผ ๋ณธ ์š”์ฒญ์„ ๋‚˜๋ˆ„์–ด์„œ ์„œ๋ฒ„์— ์ „์†กํ•œ๋‹ค.

    2. OPTIONS ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์˜ˆ๋น„ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋˜๋Š”๋ฐ ์ด๋•Œ CORS ์ •์ฑ…์„ ์œ„๋ฐ˜ํ–ˆ๋Š”์ง€ ํŒ๋‹จํ•œ๋‹ค.

  2. Simple Request

    1. ์˜ˆ๋น„ ์š”์ฒญ์„ ๋ณด๋‚ด์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์ด๋‹ค.

    2. ํŠน์ • ์ƒํ™ฉ์—์„œ๋งŒ ๋ฐœ์ƒํ•˜๊ณ , ์กฐ๊ฑด์ด ๋งค์šฐ ๊นŒ๋‹ค๋กญ๋‹ค.

  3. Credentialed Request

    1. ์ฟ ํ‚ค์™€ ๊ฐ™์€ ์ธ์ฆ ์ •๋ณด๋ฅผ ํ—ค๋”์— ํฌํ•จํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

    2. credentials ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ด๋•Œ ์„œ๋ฒ„์—์„œ๋„ ์ด์— ๋งž๋Š” ์„ค์ •์„ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

CORS๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํฌ๊ฒŒ 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

  1. ๋จผ์ € ์„œ๋ฒ„์—์„œ Access-Control-Allow-Origin ์„ธํŒ…์„ ํ•ด์ค€๋‹ค. Node.js ๊ธฐ๋ฐ˜ ์„œ๋ฒ„ ํ”„๋ ˆ์ž„์›Œํฌ(Express, NestJS๋“ฑ)์—์„œ๋Š” Cors ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•œ๋‹ค.

  2. ํ”„๋ก ํŠธ๋‹จ์—์„œ ํ”„๋ก์‹œ ์„œ๋ฒ„๋ฅผ ๋‘”๋‹ค.

Last updated