2.Fetch API & Cors

Fetch API ๋ž€

Fetch API๋Š” ์„œ๋ฒ„์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ์ตœ์‹  JavaScript ์ธํ„ฐํŽ˜์ด์Šค๋‹ค. ์ด์ „ XMLHttpRequest(XHR) API๋ณด๋‹ค HTTP ์š”์ฒญ์„ ๋งŒ๋“ค๊ณ  ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋” ๊ฐ„๋‹จํ•˜๊ณ  ์œ ์—ฐํ•˜๋ฉฐ ๊ฐ•๋ ฅํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค.

Fetch API๋Š” URL์„ ๊ฐ€์ ธ์™€ ์š”์ฒญ์— ๋Œ€ํ•œ ์„œ๋ฒ„์˜ ์‘๋‹ต์„ ๋‚˜ํƒ€๋‚ด๋Š” Response ๊ฐ์ฒด๋กœ ํ™•์ธ๋˜๋Š” Promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” fetch() ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. Response ๊ฐœ์ฒด๋Š” ์‘๋‹ต ํ—ค๋”, ๋ณธ๋ฌธ ๋ฐ ์ƒํƒœ๋ฅผ ๊ฒ€์‚ฌํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. Response ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Blob ๋ฐ JSON ๊ฐœ์ฒด์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ์œ ์šฉํ•œ ๊ฐœ์ฒด๋ฅผ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ๋‹ค.

fetch('https://example.com/data.json')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));

์ด ์˜ˆ์ œ์—์„œ๋Š” fetch() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ URL 'https://example.com/data.json'์—์„œ JSON ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ fetch()์— ์˜ํ•ด ๋ฐ˜ํ™˜๋œ Promise๋Š” ์‘๋‹ต ๊ฐ์ฒด์˜ json() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์—ฐ๊ฒฐ๋˜์–ด ์‘๋‹ต ๋ณธ๋ฌธ์„ JSON์œผ๋กœ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๊ณ  ๋‹ค๋ฅธ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋งˆ์ง€๋ง‰ then() ๋ฉ”์„œ๋“œ๋Š” JSON ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ˜์†”์— ๊ธฐ๋กํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ catch() ๋ฉ”์„œ๋“œ๋Š” ๊ฐ€์ ธ์˜ค๊ธฐ ์ž‘์—… ์ค‘์— ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.

Fetch API๋Š” ํ—ค๋”, ๋ฉ”์„œ๋“œ ๋ฐ ๋ณธ๋ฌธ๊ณผ ๊ฐ™์€ ์š”์ฒญ์„ ์‚ฌ์šฉ์ž ์ง€์ •ํ•˜๋Š” ์˜ต์…˜๋„ ์ œ๊ณตํ•œ๋‹ค.

fetch('https://example.com/api/data', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ key1: 'value1', key2: 'value2' })
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));

์ด ์˜ˆ์ œ์—์„œ๋Š” JSON ํŽ˜์ด๋กœ๋“œ์™€ ํ•จ๊ป˜ URL 'https://example.com/api/data'์— POST ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐ fetch() ๋ฉ”์„œ๋“œ๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค. headers ์˜ต์…˜์€ ํŽ˜์ด๋กœ๋“œ์˜ ์ฝ˜ํ…์ธ  ์œ ํ˜•์„ ์ง€์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๊ณ  body ์˜ต์…˜์€ JSON ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์„œ๋ฒ„๋Š” ์š”์ฒญ ๋ณธ๋ฌธ์—์„œ JSON ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ „๋ฐ˜์ ์œผ๋กœ Fetch API๋Š” ์ตœ์‹  ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ HTTP ์š”์ฒญ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๊ฐ•๋ ฅํ•˜๊ณ  ์œ ์—ฐํ•œ ๋„๊ตฌ์ด๋‹ค. ์š”์ฒญ์„ ๋งŒ๋“ค๊ณ  ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋ฅผ ๋‹จ์ˆœํ™”ํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ๊น”๋”ํ•œ Promise ๊ธฐ๋ฐ˜ API๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

Blob

Blob(Binary Large Object)์€ ์ด๋ฏธ์ง€, ์˜ค๋””์˜ค ๋˜๋Š” ๋น„๋””์˜ค ํŒŒ์ผ๊ณผ ๊ฐ™์€ ์ด์ง„ ๋ฐ์ดํ„ฐ ์ฒญํฌ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” JavaScript์˜ ๋ฐ์ดํ„ฐ ์œ ํ˜•์ด๋‹ค. Blob์€ ์„œ๋ฒ„์—์„œ ๋ณด๋‚ด๊ฑฐ๋‚˜ ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์•ผ ํ•˜๋Š” ์ด์ง„ ๋ฐ์ดํ„ฐ๋กœ ์ž‘์—…ํ•  ๋•Œ ์›น ๊ฐœ๋ฐœ์— ์œ ์šฉํ•˜๋‹ค.

Blob ๊ฐœ์ฒด๋Š” ์‹ค์ œ ์ด์ง„ ๋ฐ์ดํ„ฐ์™€ ๋ฐ์ดํ„ฐ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ง‘ํ•ฉ(์˜ˆ: MIME ์œ ํ˜• ๋ฐ ํŒŒ์ผ ์ด๋ฆ„)์˜ ๋‘ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. ์ด์ง„ ๋ฐ์ดํ„ฐ๋Š” ํ…์ŠคํŠธ, ์ด๋ฏธ์ง€, ์˜ค๋””์˜ค ๋˜๋Š” ๋น„๋””์˜ค๋ฅผ ํฌํ•จํ•œ ๋ชจ๋“  ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.

์›น ๊ฐœ๋ฐœ์—์„œ Blob์˜ ์ผ๋ฐ˜์ ์ธ ์šฉ๋„ ์ค‘ ํ•˜๋‚˜๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ํŒŒ์ผ์„ ์„œ๋ฒ„์— ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. Blob API๋Š” ํŒŒ์ผ ์ž…๋ ฅ ์š”์†Œ์—์„œ ์ƒˆ Blob ๊ฐœ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋ฉฐ, ๊ทธ๋Ÿฐ ๋‹ค์Œ Fetch API ๋˜๋Š” XHR์„ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

Promise

JavaScript์—์„œ Promise๋Š” ์•„์ง ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์ง€๋งŒ ๋ฏธ๋ž˜์˜ ์–ด๋Š ์‹œ์ ์— ์žˆ์„ ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋‚ด์žฅ ๊ฐœ์ฒด๋‹ค. Promise๋Š” ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋ฅผ ๋‹จ์ˆœํ™”ํ•˜๋ฏ€๋กœ ํ˜„๋Œ€ ์›น ๊ฐœ๋ฐœ์˜ ๊ธฐ๋ณธ ๋„๊ตฌ๋‹ค.

Promise ๊ฐ์ฒด์—๋Š” ๋ณด๋ฅ˜, ์ดํ–‰ ๋ฐ ๊ฑฐ๋ถ€์˜ ์„ธ ๊ฐ€์ง€ ์ƒํƒœ๊ฐ€ ์žˆ๋‹ค. Promise๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด ๋Œ€๊ธฐ ์ค‘ ์ƒํƒœ๊ฐ€ ๋œ๋‹ค. ์ด๋Š” Promise๊ฐ€ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ’์„ ์•„์ง ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ์„ ์˜๋ฏธํ•œ๋‹ค. Promise๊ฐ€ ์ดํ–‰๋˜๋ฉด ์ดํ–‰ ์ƒํƒœ๊ฐ€ ๋˜๊ณ  Promise๊ฐ€ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ’์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์‹คํ–‰ ์ค‘์— Promise์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด Promise๋Š” ๊ฑฐ๋ถ€๋œ ์ƒํƒœ๊ฐ€ ๋˜๊ณ  ์˜ค๋ฅ˜ ๊ฐœ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

Promise์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๊ธฐ๋ณธ ๊ตฌ๋ฌธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

const promise = new Promise((resolve, reject) => {
  // ๋น„๋™๊ธฐ ์ฝ”๋“œ ์ž‘์„ฑ
  if (/* ๋น„๋™๊ธฐ ์ž‘์—… ์„ฑ๊ณต */) {
    resolve(/* ๋ฐ˜ํ™˜ํ•  ๊ฐ’ */);
  } else {
    reject(/* ์—๋Ÿฌ */);
  }
});

์ด ์˜ˆ์—์„œ๋Š” resolve ๋ฐ reject๋ผ๋Š” ๋‘ ๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ Promise๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ํ•จ์ˆ˜์—๋Š” ๊ฒฐ๊ตญ Promise๋ฅผ ํ•ด๊ฒฐํ•˜๊ฑฐ๋‚˜ ๊ฑฐ๋ถ€ํ•  ๋น„๋™๊ธฐ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค. ์ž‘์—…์ด ์„ฑ๊ณตํ•˜๋ฉด ๋ฐ˜ํ™˜ํ•  ๊ฐ’๊ณผ ํ•จ๊ป˜ resolve ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ์‹คํŒจํ•˜๋ฉด ์˜ค๋ฅ˜ ๊ฐœ์ฒด์™€ ํ•จ๊ป˜ ๊ฑฐ๋ถ€ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

Promise๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด then() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ดํ–‰๋œ ์ƒํƒœ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ catch() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ฑฐ๋ถ€๋œ ์ƒํƒœ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

promise
  .then(value => {
    // ์™„๋ฃŒ ์ƒํƒœ ์ฒ˜๋ฆฌ
  })
  .catch(error => {
    // ๊ฑฐ๋ถ€๋œ ์ƒํƒœ ์ฒ˜๋ฆฌ
  });

์ด ์˜ˆ์—์„œ then() ๋ฉ”์„œ๋“œ๋Š” Promise์˜ ์ดํ–‰ ์ƒํƒœ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๊ณ  catch() ๋ฉ”์„œ๋“œ๋Š” ๊ฑฐ๋ถ€๋œ ์ƒํƒœ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌ๋œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ๊ฐ๊ฐ Promise์—์„œ ๋ฐ˜ํ™˜๋œ ๊ฐ’ ๋˜๋Š” ์˜ค๋ฅ˜ ๊ฐœ์ฒด๋ฅผ ๋ฐ›๋‹ค.

Promise๋Š” then() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—ฐ๊ฒฐ๋  ์ˆ˜๋„ ์žˆ์œผ๋ฏ€๋กœ ๋ณด๋‹ค ๋ณต์žกํ•œ ์ž‘์—…์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค๋ฅธ Promise๊ฐ€ ์ดํ–‰๋œ ํ›„ Promise๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋‘ Promise๋ฅผ ํ•จ๊ป˜ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

const promise1 = new Promise((resolve, reject) => {
  // Asynchronous code here
});

const promise2 = promise1.then(value => {
  // Handle fulfilled state of promise1
  return /* value or new Promise */;
});

promise2
  .then(value => {
    // Handle fulfilled state of promise2
  })
  .catch(error => {
    // Handle rejected state of either promise1 or promise2
  });

์ด ์˜ˆ์—์„œ promise2๋Š” then() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ promise1์— ์—ฐ๊ฒฐ๋˜์–ด promise1์ด ์ดํ–‰๋œ ํ›„ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋‹ค. then()์— ์ „๋‹ฌ๋œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” ์ฒด์ธ์˜ ๋‹ค์Œ then() ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌ๋˜๋Š” ์ƒˆ ๊ฐ’ ๋˜๋Š” Promise๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

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

ReadableStream

ReadableStream์€ ์ตœ์‹  ์›น ๋ธŒ๋ผ์šฐ์ €์™€ Node.js์— ๋‚ด์žฅ๋œ ๊ฐ์ฒด๋กœ, ๋ฐ์ดํ„ฐ ์†Œ์Šค์—์„œ ์†Œ๋น„์ž๋กœ ๋ฐ์ดํ„ฐ, ํŠนํžˆ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ์„ธํŠธ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ŠคํŠธ๋ฆฌ๋ฐํ•  ์ˆ˜ ์žˆ๋‹ค. ReadableStream์€ ์ œ์–ด๋˜๊ณ  ํšจ์œจ์ ์ธ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์„ ๋น„๋™๊ธฐ์‹์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ œ๊ณตํ•˜์—ฌ ์†Œ๋น„์ž๊ฐ€ ์ „์ฒด ๋ฐ์ดํ„ฐ ์„ธํŠธ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ๊ฐ€ ๋„์ฐฉํ•˜๋Š” ๋Œ€๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

ReadableStream์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์†Œ์Šค์™€ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋Š” ์†Œ๋น„์ž๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. ์†Œ์Šค๋Š” ํŒŒ์ผ, ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ ๋˜๋Š” ์ƒ์„ฑ๋œ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ๊ณผ ๊ฐ™์€ ๋ชจ๋“  ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค. ์†Œ๋น„์ž๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์ผ์— ์“ฐ๊ฑฐ๋‚˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ UI์— ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ชจ๋“  ์œ ํ˜•์˜ ์ž‘์—…์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

ReadableStream์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ณธ ๊ตฌ๋ฌธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

const stream = new ReadableStream({
  start(controller) {
    // ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ์ฝ”๋“œ ์ž‘์„ฑ
  },
  cancel() {
    // ์„ ํƒ์ ์œผ๋กœ ์ •๋ฆฌ ์ฝ”๋“œ ์ž‘์„ฑ
  }
});

์ด ์˜ˆ์ œ์—์„œ๋Š” start() ๋ฐ cancel()์ด๋ผ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฉ”์„œ๋“œ๊ฐ€ ํฌํ•จ๋œ ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ ReadableStream์„ ๋งŒ๋“ ๋‹ค. start() ๋ฉ”์„œ๋“œ์—๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉฐ ์ŠคํŠธ๋ฆผ ์ œ์–ด๋ฅผ ์œ„ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ ๊ฐœ์ฒด๊ฐ€ ์ „๋‹ฌ๋œ๋‹ค. cancel() ๋ฉ”์„œ๋“œ๋Š” ์„ ํƒ ์‚ฌํ•ญ์ด๋ฉฐ ์†Œ๋น„์ž๊ฐ€ ์ŠคํŠธ๋ฆผ์„ ์ทจ์†Œํ•œ ๊ฒฝ์šฐ ์‹คํ–‰๋˜๋Š” ์ •๋ฆฌ ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•œ๋‹ค.

ReadableStream์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ํŒ๋…๊ธฐ ๊ฐœ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ํ•ด๋‹น read() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ ์ฒญํฌ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

const reader = stream.getReader();

function readData() {
  reader.read().then(({ done, value }) => {
    if (done) {
      console.log('End of stream');
      return;
    }

    console.log(`Data chunk: ${value}`);
    readData();
  });
}

readData();

์ด ์˜ˆ์ œ์—์„œ๋Š” ReadableStream ๊ฐœ์ฒด์˜ getReader() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŒ๋…๊ธฐ ๊ฐœ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ readData() ํ•จ์ˆ˜๋Š” read() ๋ฉ”์„œ๋“œ์—์„œ ๋ฐ˜ํ™˜๋œ Promise๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœ๋œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ์ŠคํŠธ๋ฆผ์ด ์ข…๋ฃŒ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ถ€์šธ ๊ฐ’๊ณผ ๋ฐ์ดํ„ฐ ๋ฉ์–ด๋ฆฌ๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฐ์ฒด๋กœ ํ™•์ธ๋œ๋‹ค.

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

Unicode

Unicode๋Š” ์ „ ์„ธ๊ณ„ ์–ธ์–ด์˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํฌํ•จํ•˜์—ฌ ์ธ๊ฐ„ ์–ธ์–ด์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ฐ ๋ฌธ์ž์— ๊ณ ์œ ํ•œ ์ˆซ์ž ๊ฐ’(์ฝ”๋“œ ํฌ์ธํŠธ)์„ ํ• ๋‹นํ•˜๋Š” ๋ฒ”์šฉ ๋ฌธ์ž ์ธ์ฝ”๋”ฉ ํ‘œ์ค€์ด๋‹ค. Unicode์˜ ๋ชฉํ‘œ๋Š” ์ •๋ณด ์†์‹ค ์—†์ด ๋‹ค์–‘ํ•œ ํ”Œ๋žซํผ, ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ๋ฐ ์žฅ์น˜ ๊ฐ„์— ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตํ™˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ชจ๋“  ์–ธ์–ด ๋˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋กœ ํ…์ŠคํŠธ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ผ๊ด€๋œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

Unicode๋Š” ๋ฌธ์ž, ์ˆซ์ž, ๋ฌธ์žฅ ๋ถ€ํ˜ธ, ๊ธฐํ˜ธ ๋ฐ ์ œ์–ด ๋ฌธ์ž๋ฅผ ํฌํ•จํ•˜์—ฌ 143,000๊ฐœ ์ด์ƒ์˜ ๋ฌธ์ž๋ฅผ ํฌํ•จํ•˜๋Š” ํฌ๊ณ  ๋ณต์žกํ•œ ํ‘œ์ค€์ด๋‹ค. ๊ฐ ๋ฌธ์ž๋Š” 0x000000์—์„œ 0x10FFFF๊นŒ์ง€์˜ 32๋น„ํŠธ ์ •์ˆ˜์ธ ๊ณ ์œ ํ•œ ์ฝ”๋“œ ํฌ์ธํŠธ๋กœ ์‹๋ณ„๋œ๋‹ค.

Unicode ํ‘œ์ค€์€ UTF-8, UTF-16 ๋ฐ UTF-32๋ฅผ ํฌํ•จํ•˜์—ฌ Unicode ๋ฌธ์ž๋ฅผ ์ด์ง„ ํ˜•์‹์œผ๋กœ ๋‚˜ํƒ€๋‚ด๋Š” ์—ฌ๋Ÿฌ ์ธ์ฝ”๋”ฉ ์ฒด๊ณ„๋ฅผ ์ •์˜ํ•œ๋‹ค. ๊ฐ ์ธ์ฝ”๋”ฉ ์ฒด๊ณ„๋Š” Unicode ์ฝ”๋“œ ํฌ์ธํŠธ๋ฅผ ์ปดํ“จํ„ฐ์—์„œ ์ €์žฅ, ์ „์†ก ๋ฐ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ผ๋ จ์˜ ๋ฐ”์ดํŠธ์— ๋งคํ•‘ํ•œ๋‹ค.

UTF-8์€ ๊ฐ€์žฅ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ์ธ์ฝ”๋”ฉ ์ฒด๊ณ„์ด๋ฉฐ ์˜์–ด์˜ ์›๋ž˜ 7๋น„ํŠธ ๋ฌธ์ž ์ธ์ฝ”๋”ฉ ํ‘œ์ค€์ธ ASCII์™€์˜ ํ•˜์œ„ ํ˜ธํ™˜์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค. UTF-8์€ ๋‹จ์ผ ๋ฐ”์ดํŠธ๋กœ ์ธ์ฝ”๋”ฉ๋œ ASCII ๋ฌธ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”๋“œ ํฌ์ธํŠธ์˜ ๊ฐ’์— ๋”ฐ๋ผ ๊ฐ Unicode ์ฝ”๋“œ ํฌ์ธํŠธ๋ฅผ 1~4๋ฐ”์ดํŠธ๋กœ ์ธ์ฝ”๋”ฉํ•œ๋‹ค. UTF-16์€ ๊ฐ Unicode ์ฝ”๋“œ ํฌ์ธํŠธ๋ฅผ ํ•˜๋‚˜ ๋˜๋Š” ๋‘ ๊ฐœ์˜ 16๋น„ํŠธ ์ฝ”๋“œ ๋‹จ์œ„๋กœ ์ธ์ฝ”๋”ฉํ•˜๊ณ  UTF-32๋Š” ๊ฐ ์ฝ”๋“œ ํฌ์ธํŠธ๋ฅผ ๋‹จ์ผ 32๋น„ํŠธ ์ฝ”๋“œ ๋‹จ์œ„๋กœ ์ธ์ฝ”๋”ฉํ•œ๋‹ค.

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

์š”์•ฝํ•˜๋ฉด Unicode๋Š” ๊ฐ ๋ฌธ์ž์— ํ• ๋‹น๋œ ๊ณ ์œ ํ•œ ์ฝ”๋“œ ํฌ์ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ์–ธ์–ด ๋˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋กœ ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ‘œ์ค€ํ™”๋œ ๋ฐฉ๋ฒ•์ด๋‹ค. UTF-8, UTF-16 ๋ฐ UTF-32์™€ ๊ฐ™์€ Unicode ์ธ์ฝ”๋”ฉ ์ฒด๊ณ„๋Š” ์ปดํ“จํ„ฐ์—์„œ ์ €์žฅ, ์ „์†ก ๋ฐ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” Unicode ๋ฌธ์ž์˜ ์ด์ง„ ํ‘œํ˜„์„ ์ œ๊ณตํ•œ๋‹ค.

CORS ๋ž€

CORS๋Š” Cross-Origin Resource Sharing์˜ ์•ฝ์ž๋กœ, ์›น ํŽ˜์ด์ง€๊ฐ€ ์ œ๊ณต๋œ ๋„๋ฉ”์ธ์ด๋‚˜ ํฌํŠธ๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์ด๋‚˜ ํฌํŠธ์— ๋Œ€ํ•œ ์š”์ฒญ์„ ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ์›น ํŽ˜์ด์ง€๋ฅผ ์ œํ•œํ•˜๋Š” ์ตœ์‹  ์›น ๋ธŒ๋ผ์šฐ์ €์— ๊ตฌํ˜„๋œ ๋ณด์•ˆ ๊ธฐ๋Šฅ์ด๋‹ค. CORS๋Š” ์•…์˜์ ์ธ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์—ฌ๋Ÿฌ ๋„๋ฉ”์ธ์—์„œ ์ค‘์š”ํ•œ ๋ฐ์ดํ„ฐ์— ์•ก์„ธ์Šคํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ํ•„์ˆ˜ ๋ณด์•ˆ ๊ธฐ๋Šฅ์ด๋‹ค.

๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…(same-origin policy)์€ ์›น ํŽ˜์ด์ง€๊ฐ€ ์ž์ฒด ์ถœ์ฒ˜๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์ถœ์ฒ˜(๋„๋ฉ”์ธ, ํ”„๋กœํ† ์ฝœ ๋˜๋Š” ํฌํŠธ)์˜ ๋ฆฌ์†Œ์Šค์— ์•ก์„ธ์Šคํ•˜๋Š” ๊ฒƒ์„ ์ œํ•œํ•˜๋Š” ์›น ๋ธŒ๋ผ์šฐ์ €์— ์˜ํ•ด ๊ตฌํ˜„๋œ ๊ธฐ๋ณธ ๋ณด์•ˆ ๊ฐœ๋…์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์›น ํŽ˜์ด์ง€๊ฐ€ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์—์„œ ํ˜ธ์ŠคํŒ…๋˜๋Š” REST API์™€ ๊ฐ™์ด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค์— ์•ก์„ธ์Šคํ•ด์•ผ ํ•˜๋Š” ์œ ํšจํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ๋‹ค. CORS๋Š” ์ œ์–ด๋œ ๋ฐฉ์‹์œผ๋กœ ๋™์ผํ•œ ์ถœ์ฒ˜ ์ •์ฑ…์„ ์™„ํ™”ํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ œ๊ณตํ•˜์—ฌ ์›น ํŽ˜์ด์ง€๊ฐ€ ์ถœ์ฒ˜ ๊ฐ„ ์š”์ฒญ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๋™์‹œ์— ์•…์˜์ ์ธ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๊ธฐ๋Šฅ์„ ๋‚จ์šฉํ•˜์ง€ ๋ชปํ•˜๋„๋ก ํ•œ๋‹ค.

CORS๋Š” ์„œ๋ฒ„์˜ ์‘๋‹ต์— HTTP ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ž‘๋™ํ•˜๋ฉฐ, ์ด๋Š” ์›๋ณธ ๊ฐ„ ์š”์ฒญ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๋ฉ”์ธ๊ณผ ์ง€์›๋˜๋Š” HTTP ๋ฉ”์„œ๋“œ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์„œ๋ฒ„๋Š” ๋‹ค์Œ CORS ํ—ค๋” ์ค‘ ํ•˜๋‚˜๋กœ ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Access-Control-Allow-Origin: ๋ฆฌ์†Œ์Šค์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ๋„๋ฉ”์ธ์„ ์ง€์ •ํ•œ๋‹ค. ํ—ค๋”๊ฐ€ ์—†๊ฑฐ๋‚˜ ์™€์ผ๋“œ์นด๋“œ "*"๊ฐ€ ํฌํ•จ๋œ ๊ฒฝ์šฐ ๋ชจ๋“  ๋„๋ฉ”์ธ์ด ๋ฆฌ์†Œ์Šค์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Access-Control-Allow-Methods: GET, POST, PUT, DELETE ๋“ฑ๊ณผ ๊ฐ™์€ ์›๋ณธ ๊ฐ„ ์š”์ฒญ์— ๋Œ€ํ•ด ํ—ˆ์šฉ๋˜๋Š” HTTP ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•œ๋‹ค.

  • Access-Control-Allow-Headers: ๊ต์ฐจ ์ถœ์ฒ˜ ์š”์ฒญ์— ํ—ˆ์šฉ๋˜๋Š” ์š”์ฒญ ํ—ค๋”๋ฅผ ์ง€์ •ํ•œ๋‹ค.

  • Access-Control-Allow-Credentials: ์›๋ณธ ๊ฐ„ ์š”์ฒญ์— ์ฟ ํ‚ค ๋˜๋Š” HTTP ์ธ์ฆ๊ณผ ๊ฐ™์€ ์ž๊ฒฉ ์ฆ๋ช…์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

์›น ํŽ˜์ด์ง€๊ฐ€ ๊ต์ฐจ ์ถœ์ฒ˜ ์š”์ฒญ์„ ํ•˜๋ฉด ์›น ๋ธŒ๋ผ์šฐ์ €๋Š” ์š”์ฒญ๋œ ๋ฆฌ์†Œ์Šค๊ฐ€ ํ—ˆ์šฉ๋˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์„ ์„œ๋ฒ„๋กœ ๋ณด๋‚ธ๋‹ค. ์‹คํ–‰ ์ „ ์š”์ฒญ์—๋Š” HTTP OPTIONS ๋ฉ”์„œ๋“œ์™€ ์›๋ณธ ๊ฐ„ ์š”์ฒญ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์ง€์ •ํ•˜๋Š” ์ถ”๊ฐ€ ํ—ค๋”๊ฐ€ ํฌํ•จ๋œ๋‹ค. ์„œ๋ฒ„๋Š” ์›๋ณธ ๊ฐ„ ์š”์ฒญ์ด ํ—ˆ์šฉ๋˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ ์ ˆํ•œ CORS ํ—ค๋”๋กœ ์‘๋‹ตํ•œ๋‹ค. ์š”์ฒญ์ด ํ—ˆ์šฉ๋˜๋ฉด ์›น ๋ธŒ๋ผ์šฐ์ €๋Š” ์š”์ฒญ๋œ ๋ฉ”์„œ๋“œ ๋ฐ ํ—ค๋”์™€ ํ•จ๊ป˜ ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค. preflight ์š”์ฒญ์€ cross-origin ์š”์ฒญ์ด ํ—ˆ์šฉ๋˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ ์„œ๋ฒ„๋Š” ์ ์ ˆํ•œ CORS ํ—ค๋”๋กœ ์‘๋‹ตํ•œ๋‹ค.

Reference

Last updated