2. Fetch API & CORS

keyword

  • Fetch API๋ž€?

  • Promise

  • ReableStream

  • Unicode

  • CORS๋ž€?

Fetch API๋ž€?

๊ณผ๊ฑฐ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์—์„  XMLHttpRequest ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด ํŽ˜์ด์ง€์˜ ์ƒˆ๋กœ๊ณ ์นจ ์—†์ด(์ƒˆ๋กœ๊ณ ์นจ์œผ๋กœ ์ธํ•œ ํ™”์ดํŠธ ์Šคํฌ๋ฆฐ ์–ต์ œ) ์„œ๋ฒ„๋กœ ๋น„๋™๊ธฐ ์š”์ฒญ์„ ๋ณด๋ƒˆ์—ˆ์ง€๋งŒ, Fetch API๋ฅผ ํ†ตํ•ด ๋ณด๋‹ค ๊ฐ•๋ ฅํ•˜๊ณ  ์œ ์—ฐํ•œ ๋ฐ์ดํ„ฐ ํ†ต์‹ ์„ ์ œ๊ณตํ•œ๋‹ค. Promise ๊ธฐ๋ฐ˜์˜ ๋น„๋™๊ธฐ ์ฝ”๋“œ ์ž‘์„ฑ์„ ํ†ตํ•ด ๋” ๊น”๋”ํ•˜๊ณ  ๊ฐ„๊ฒฐํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.


Promise

Event Loop

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์‹ฑ๊ธ€ ์“ฐ๋ ˆ๋“œ ๊ธฐ๋ฐ˜ ์–ธ์–ด๋กœ ๋‹จ์ผ ์ฝœ์Šคํƒ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์ž‘์—…๋งŒ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿผ์—๋„ ๋™์‹œ์— ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ํ†ตํ•ด ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ์ž‘์—…์˜ ๋™์‹œ์„ฑ์„ ๋ณด์žฅํ•˜๋ฉฐ ์ด๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋Ÿฐํƒ€์ž„์ธ ๋ธŒ๋ผ์šฐ์ € ๋˜๋Š” Node.js๊ฐ€ ๋‹ด๋‹นํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ๋น„๋™๊ธฐ ์ž‘์—…์€ callback ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด Node.js๋‚˜ Web API์— ์ „๋‹ฌํ•˜๋Š”๋ฐ ์ž‘์—…์ด ๋๋‚œ ์ˆœ์„œ๋Œ€๋กœ callback ํ•จ์ˆ˜๋ฅผ ํƒœ์Šคํฌ ํ์— ์ „๋‹ฌํ•˜๋ฉฐ ์ด๋ฒคํŠธ ๋ฃจํ”„๋Š” ์ฝœ ์Šคํƒ์ด ๋น„์›Œ์ ธ์žˆ๋‹ค๋ฉด ํƒœ์Šคํฌ ํ์˜ ์ฒซ๋ฒˆ์งธ ํ•จ์ˆ˜๋ฅผ ๊บผ๋‚ด ์ฝœ ์Šคํƒ์— ์ถ”๊ฐ€ํ•œ๋‹ค.

Callback Hell

Callback์„ ์ด์šฉํ•œ ๋น„๋™๊ธฐ ์ž‘์—…์€ ์ฒ˜๋ฆฌ ์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋™๊ธฐ์ ์ธ ์ˆ˜ํ–‰์„ ์œ„ํ•ด์„  Callback์„ ์ค‘์ฒฉํ•ด์„œ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์ด๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค๊ณ  ์œ ์ง€๋ณด์ˆ˜๋ฅผ ์–ด๋ ต๊ฒŒ ํ•œ๋‹ค.

Promsie

Promise๋Š” Javascript์—์„œ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด๋กœ ๋™๊ธฐ์  ์ˆ˜ํ–‰์„ ํ•˜๊ธฐ ์œ„ํ•ด ์ค‘์ฒฉ๋œ ์ฝœ๋ฐฑ ์ง€์˜ฅ์„ .then() ์ฒด์ด๋‹์„ ํ†ตํ•ด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. Promise๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋Š” Promise ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • Promise ๊ฐ์ฒด๋Š” (resolve, reject)๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํ•˜๋Š” Callback ํ•จ์ˆ˜๋กœ ์ƒ์„ฑํ•œ๋‹ค.

  • pending, fulfilled, rejected 3๊ฐ€์ง€ ์ƒํƒœ๋ฅผ ๊ฐ€์ง„๋‹ค.

    • Promise ๊ฐ์ฒด์˜ ์ดˆ๊ธฐ ์ƒํƒœ๋Š” pending

    • resolve ํ˜ธ์ถœ -> fulfilled

    • reject ํ˜ธ์ถœ -> rejected

  • Promise.then() ํ•จ์ˆ˜๋กœ fulfilled, rejected ์ƒํƒœ์— ๋Œ€ํ•œ callback์„ ๋“ฑ๋กํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Promise.catch() ํ•จ์ˆ˜๋กœ rejected ์ƒํƒœ์— ๋Œ€ํ•œ callback์„ ๋“ฑ๋กํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋™์ž‘์ด ์ˆ˜ํ–‰(fulfilled)๋˜๋ฉด resolve ํ•จ์ˆ˜๋ฅผ, ์ทจ์†Œ(rejected)๋˜๋ฉด rejectํ•จ์ˆ˜๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = { message: "Data fetched successfully" };
      resolve(data);
    }, 1000);
  });
}

fetchData()
  .then(result => {
    // result = { message: "Data fetched successfully" }
    console.log("First .then() result:", result);
    return "Additional data";
  })
  .then(data => {
    // data = Additional data
    console.log("Second .then() data:", data);
    return 42;
  })
  .then(value => {
    // value = 42
    console.log("Third .then() value:", value);
  });

๊ฐ .then() .catch() ํ•จ์ˆ˜๋Š” Promise ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜ ์ฒด์ด๋‹์ด ๊ฐ€๋Šฅํ•˜๋‹ค.


ReadableStream

fetct API์˜ response ๊ฐ์ฒด์˜ body ์†์„ฑ์€ ReadableStream์˜ ๊ตฌ์ฒด์ ์ธ ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

์ •๋ฆฌํ•˜์ž๋ฉด ReadableStream์€ ์›น ํ”Œ๋žซํผ์—์„œ ์‚ฌ์šฉ๋˜๋Š” Streams API๋กœ ๋Œ€์šฉ๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ž‘์€ ์กฐ๊ฐ(chunk)๋กœ ๋‚˜๋ˆ„์–ด ์ „์†กํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ํ•„์š”ํ•œ๋งŒํผ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฝ์„ ์ˆ˜ ์žˆ์–ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ŠคํŠธ๋ฆฌ๋ฐ์ด๋ž€ ๋‹จ์–ด๋ฅผ ๋ณด๋‹ˆ UDP๊ฐ€ ๋– ์˜ค๋ฅด๋Š”๋ฐ ๋น ๋ฅด๊ณ  ๊ฐ€๋ณ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ์ „์†ก ๊ณ„์ธต ํ”„๋กœํ† ์ฝœ์ด ๋– ์˜ค๋ฅธ๋‹ค. ๊ฐ€๋ณ๋‹ค๋ผ๋Š” ์œ ์‚ฌ์„ฑ์ด ๋ณด์ด๊ธด ํ•˜์ง€๋งŒ, ๋‘ ๊ฐœ๋…์˜ ์ง์ ‘์ ์ธ ์—ฐ๊ด€์„ฑ์€ ๋”ฑํžˆ ์—†์–ด๋ณด์ธ๋‹ค.

stream

์ŠคํŠธ๋ฆผ์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ž‘์€ ์กฐ๊ฐ(chunk)์œผ๋กœ ๋‚˜๋ˆ„์–ด ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์„ ๋งํ•œ๋‹ค.

Unicode

๋ฌธ์ž ์ธ์ฝ”๋”ฉ

์ปดํ“จํ„ฐ๋Š” 0๊ณผ 1๋กœ ์ด๋ฃจ์–ด์ง„ Binary(์ด์ง„) ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ, ๋ฌธ์ž๋ฅผ ์ปดํ“จํ„ฐ๊ฐ€ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ์‹ ํ˜ธ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ €์žฅํ•˜๊ณ  ์ „์†กํ•œ๋‹ค. ์ด ์‹ ํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋Š” ์ธ์ฝ”๋”ฉ๊ณผ ๋ฌธ์ž๋ฅผ ํ•ด๋…ํ•˜๋Š” ๋””์ฝ”๋”ฉ์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฏธ๋ฆฌ ์ •ํ•ด์ง„ ๊ธฐ์ค€์„ ๋ฐ”ํƒ•์œผ๋กœ ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•˜๋Š”๋ฐ, ์ด๋ฅผ ๋ฌธ์ž์—ด ์„ธํŠธ, ๋ฌธ์ž์…‹์ด๋ผ๊ณ  ํ•œ๋‹ค.

ASCII(์•„์Šคํ‚ค) ์ฝ”๋“œ

์•„์Šคํ‚ค ์ฝ”๋“œ๋Š” ์ดˆ๊ธฐ ๋ณด๊ธ‰ํ˜• ์ปดํ“จํ„ฐ์˜ ๋ฌธ์ž์—ด ์„ธํŠธ๋กœ ์•„์Šคํ‚ค ์ฝ”๋“œ๋Š” 7bit๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์œผ๋ฉฐ, 0๋ถ€ํ„ฐ 127๊นŒ์ง€ ์ด 128๊ฐœ์˜ ๋ฌธ์ž(์•ŒํŒŒ๋ฒณ, ์ˆซ์ž, ํŠน์ˆ˜ ๋ฌธ์ž ๋“ฑ)๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ์ž ์ธ์ฝ”๋”ฉ์ด๋‹ค.

Unicode

์•„์Šคํ‚ค ์ฝ”๋“œ๋Š” ์•ŒํŒŒ๋ฒณ๊ณผ ์ˆซ์ž๋งŒ์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์–‘ํ•œ ์–ธ์–ด์™€ ๋ฌธ์ž ์ฒด๊ณ„๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ์— ํ•œ๊ณ„๊ฐ€ ์žˆ์–ด ํ‘œ์ค€ ๋ฌธ์ž์…‹์ด ํ•„์š”ํ•ด์กŒ๊ณ , ์ดํ›„ ์ „ ์„ธ๊ณ„์˜ ๋ชจ๋“  ๋ฌธ์ž์™€ ๊ธฐํ˜ธ๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๊ตญ์ œ ํ‘œ์ค€ ๋ฌธ์ž ์ธ์ฝ”๋“œ ๋ฐฉ์‹์ธ ์œ ๋‹ˆ์ฝ”๋“œ๊ฐ€ ๊ฐœ๋ฐœ๋˜์—ˆ๋‹ค.

UTF-8

UTF-8์€ ์œ ๋‹ˆ์ฝ”๋“œ ๋ฌธ์ž์—ด ์„ธํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์ธ์ฝ”๋”ฉ ํ•˜๋Š” ๋ฐฉ์‹ ์ค‘ ํ•˜๋‚˜๋กœ ์•„์Šคํ‚ค ๋ฌธ์ž๋Š” 1๋ฐ”์ดํŠธ๋กœ, ๋‹ค๊ตญ์–ด ๋ฌธ์ž๋Š” 2๋ฐ”์ดํŠธ๋กœ ํ‘œํ˜„๋œ๋‹ค.

URL Encoding

URL์€ ์•„์Šคํ‚ค ์ฝ”๋“œ์˜ ๋ฌธ์ž ์ง‘ํ•ฉ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด, ํ•œ๊ธ€๊ณผ ๊ฐ™์€ ๋ฌธ์ž์—ด์„ URL์— ์‚ฝ์ž…ํ•  ๊ฒฝ์šฐ URL Encoding์œผ๋กœ ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. ์ด ๋•Œ ๋ณ€ํ™˜ํ•˜๋Š” ๊ทœ์น™์€ UTF-8์„ ๋”ฐ๋ฅด๋ฉฐ, ํ•œ๊ธ€ ๋ฌธ์ž 1๊ฐœ๋Š” 3๋ฐ”์ดํŠธ๋กœ ์ธ์ฝ”๋”ฉ ๋œ๋‹ค.


CORS๋ž€?

๋ธŒ๋ผ์šฐ์ €๋Š” ์›น ๋ณด์•ˆ ์ •์ฑ… SOP์— ์˜ํ•ด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ์„ ์ œํ•œํ•œ๋‹ค. ๋•Œ๋ฌธ์— ์„œ๋กœ ๋‹ค๋ฅธ ์ถœ์ฒ˜๊ฐ„์˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ ๋ฅผ ํ—ˆ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ CORS ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ†ตํ•ด ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” ์ถœ์ฒ˜๋ž€ ์ถœ์ฒ˜(origin) = Protocol(schema) + Host(domain) + Port ์ด๊ฒƒ๋“ค์„ ํ•ฉ์นœ URL์„ ์˜๋ฏธํ•œ๋‹ค.

์š”์ฒญ ๋ฐฉ์‹์— ๋”ฐ๋ฅธ CORS ๋ฐœ์ƒ

  1. <img>, <video>, <script>, <link> ํƒœ๊ทธ๋กœ ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ

  2. XMLHttpRequest, Fetch API ์„œ๋ฒ„ ๋น„๋™๊ธฐ ํ†ต์‹ 

CORS Error ํ•ด๊ฒฐํ•˜๊ธฐ

์„œ๋ฒ„์—์„œ cors ๋ฏธ๋“ค์›จ์–ด ์‚ฌ์šฉ ๋˜๋Š” response Headers์— โ€œAccess-Control-Allow-Originโ€ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

const express = require('express');
const cors = require('cors');

const app = express();

// ๋ชจ๋“  ์ถœ์ฒ˜์— ๋Œ€ํ•ด CORS ํ—ˆ์šฉ ์„ค์ •
app.use(cors());

// ...

SOP (๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…)

๋™์ผ ์ถœ์ฒ˜์— ๋Œ€ํ•ด์„œ๋งŒ ๋ฆฌ์†Œ์Šค ๊ณต์œ ๋ฅผ ํ—ˆ์šฉํ•œ๋‹ค๋Š” ์›น ๋ณด์•ˆ ์ •์ฑ…, ์„œ๋กœ ๋‹ค๋ฅธ ์ถœ์ฒ˜๊ฐ„์˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ ๋ฅผ ์ œํ•œํ•œ๋‹ค.

SOP์˜ ํ•„์š”์„ฑ

ํ•ด์ปค์˜ CSRF(์š”์ฒญ ์œ„์กฐ), XSS(์Šคํฌ๋ฆฝํŠธ ์‚ฝ์ž…) ๊ณต๊ฒฉ ์ฐจ๋‹จ

์ถ”๊ฐ€ ํ‚ค์›Œ๋“œ

  • CORS์— ๋”ฐ๋ฅธ ์š”์ฒญ๋ฐฉ์‹ 3๊ฐ€์ง€(Simple, Preflight, Credentialed request)

Last updated