2. Fetch API & CORS

1. Fetch API

Fetch API Fetch ์‚ฌ์šฉํ•˜๊ธฐ

์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์šฉํ•˜๋Š” Web API ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ํฌํ•จํ•œ ๋ฆฌ์†Œ์Šค ์ทจ๋“์„ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์Œ

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

๊ธฐ๋ณธ์ ์ธ Fetch ์š”์ฒญ

fetch('http://example.com/movies.json')
  .then((response) => response.json())
  .then((data) => console.log(data));

json()

Response.json()

JSON ๋ณธ๋ฌธ ์ฝ˜ํ…์ธ ๋ฅผ ์ถ”์ถœํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” json() ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•จ json()์€ ์‘๋‹ต ๋ณธ๋ฌธ ํ…์ŠคํŠธ๋ฅผ JSON์œผ๋กœ ํŒŒ์‹ฑํ•œ ๊ฒฐ๊ณผ๋กœ ์ดํ–‰ํ•˜๋Š”, ๋˜ ๋‹ค๋ฅธ ํ”„๋กœ๋ฏธ์Šค๋ฅผ ๋ฐ˜ํ™˜

fetch๋ฅผ ์‚ฌ์šฉํ•ด JSON ๊ตฌ๋ฌธ๋ถ„์„ํ•˜๊ธฐ API์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ• .json() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด JSON ์‘๋‹ต์„ JavaScript ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ๋˜๋Š” ๋ฐฐ์—ด๋กœ ์ž๋™์œผ๋กœ ๊ตฌ๋ฌธ๋ถ„์„

2. Promise

Promise

Promise ๊ฐ์ฒด๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์ด ๋งž์ดํ•  ๋ฏธ๋ž˜์˜ ์™„๋ฃŒ ๋˜๋Š” ์‹คํŒจ์™€ ๊ทธ ๊ฒฐ๊ณผ ๊ฐ’์„ ๋‚˜ํƒ€๋ƒ„

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

Promise์˜ ์ƒํƒœ

Promise๋Š” ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜์˜ ์ƒํƒœ๋ฅผ ๊ฐ€์ง

  • ๋Œ€๊ธฐ(pending): ์ดํ–‰ํ•˜์ง€๋„, ๊ฑฐ๋ถ€ํ•˜์ง€๋„ ์•Š์€ ์ดˆ๊ธฐ ์ƒํƒœ

  • ์ดํ–‰(fulfilled): ์—ฐ์‚ฐ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋จ

  • ๊ฑฐ๋ถ€(rejected): ์—ฐ์‚ฐ์ด ์‹คํŒจํ•จ

3. ReadableStream

ReadableStream

Streams API์˜ ReadableStream ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ฐ”์ดํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์ŠคํŠธ๋ฆผ์„ ์ œ๊ณต Fetch API๋Š” Response ๊ฐ์ฒด์˜ body ์†์„ฑ์„ ํ†ตํ•ด ReadableStream์˜ ๊ตฌ์ฒด์ ์ธ ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณต

๊ธฐ๋ณธ์ ์ธ ์‚ฌ์šฉ๋ฒ•

ReadableStream์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์šฐ์„  getReader()๋กœ ์–ป์–ด์˜จ ํ›„ ์ง„ํ–‰

fetch('http://localhost:3000/products');
// โ†’ Promise

await fetch('http://localhost:3000/products');
// โ†’ Response

const response = await fetch('http://localhost:3000/products');
// โ†’ response.body๋Š” ReadableStream

const reader = response.body.getReader();

const chunk = await reader.read();
// โ†’ chunk.value๋Š” Uint8Array ํƒ€์ž…
// โ†’ ์›๋ž˜๋Š” chunk.done์ด true์ผ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณตํ•ด์•ผ ํ•จ

const body = new TextDecoder().decode(chunk.value);

const data = JSON.parse(body);
  • chunk.value๋Š” Uint8Array ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— string์œผ๋กœ ๋ฐ”๊ฟ”์ค˜์•ผ ํ•จ

  • TextDecoder๋Š” ์ฃผ์–ด์ง„ ๋ฒ„ํผ์™€ ์ธ์ฝ”๋”ฉ์œผ๋กœ ๊ฐ’์„ ์‹ค์ œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ์ž์—ด๋กœ ์ฝ์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์คŒ

JSON์„ ๊ธฐ๋ณธ ์ง€์›

const response = await fetch('http://localhost:3000/products');
const data = await response.json();

๋‹ค๋ฅธ HTTP Method๋ฅผ ์“ฐ๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ

const response = fetch(url, {
    method: 'POST',
});

ํ…์ŠคํŠธ ํŒŒ์ผ ํ•œ ์ค„์”ฉ ์ฒ˜๋ฆฌํ•˜๊ธฐ

์‘๋‹ต์—์„œ ์ฝ์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ ์ฒญํฌ(chunk)๋Š” ์ค„ ๋‹จ์œ„๋กœ ๊น”๋”ํ•˜๊ฒŒ ๋‚˜๋‰˜์ง€ ์•Š์œผ๋ฉฐ, Uint8Array ํ˜•ํƒœ(๋ฌธ์ž์—ด X) ํ…์ŠคํŠธ ํŒŒ์ผ์„ ๊ฐ€์ ธ์™€์„œ ์ค„ ๋‹จ์œ„๋กœ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด, '์ค„' ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„๋Š” ์ž‘์—…์€ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ

4. Unicode

Unicode Consortium ์œ ๋‹ˆ์ฝ”๋“œ

์œ ๋‹ˆ์ฝ”๋“œ(Unicode)๋Š” ์ „ ์„ธ๊ณ„์˜ ๋ชจ๋“  ๋ฌธ์ž๋ฅผ ์ปดํ“จํ„ฐ์—์„œ ์ผ๊ด€๋˜๊ฒŒ ํ‘œํ˜„ํ•˜๊ณ  ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋œ ์‚ฐ์—… ํ‘œ์ค€ ์œ ๋‹ˆ์ฝ”๋“œ๋Š” ์œ ๋‹ˆ์ฝ”๋“œ ํ˜‘ํšŒ(Unicode Consortium)๊ฐ€ ์ œ์ • ์ด ํ‘œ์ค€์—๋Š” ISO 10646 ๋ฌธ์ž ์ง‘ํ•ฉ, ๋ฌธ์ž ์ธ์ฝ”๋”ฉ, ๋ฌธ์ž ์ •๋ณด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ๋ฌธ์ž๋“ค์„ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋“ฑ์ด ํฌํ•จ

๊ธฐ์กด ์ธ์ฝ”๋”ฉ์˜ ๊ทœ๋ชจ๋‚˜ ๋ฒ”์œ„ ๋ฉด์—์„œ ํ•œ์ •๋˜์–ด ์žˆ๊ณ , ๋‹ค๊ตญ์–ด ํ™˜๊ฒฝ์—์„œ๋Š” ์„œ๋กœ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐ

๐ŸŒŽ ISO(๊ตญ์ œ ํ‘œ์ค€ํ™” ๊ธฐ๊ตฌ)

International Organization for Standardization ์—ฌ๋Ÿฌ ๋‚˜๋ผ์˜ ํ‘œ์ค€ ์ œ์ • ๋‹จ์ฒด๋“ค์˜ ๋Œ€ํ‘œ๋“ค๋กœ ์ด๋ฃจ์–ด์ง„ ๊ตญ์ œ์ ์ธ ํ‘œ์ค€ํ™” ๊ธฐ๊ตฌ ๋‚˜๋ผ๋งˆ๋‹ค ๋‹ค๋ฅธ ์‚ฐ์—…, ํ†ต์ƒ ํ‘œ์ค€์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ตญ์ œ์ ์œผ๋กœ ํ†ต์šฉ๋˜๋Š” ํ‘œ์ค€์„ ๊ฐœ๋ฐœํ•˜๊ณ  ๋ณด๊ธ‰

๐Ÿ”  UCS(๊ตญ์ œ ๋ฌธ์ž ์„ธํŠธ)

Universal Character Set, ๋ฒ”์šฉ ๋ฌธ์ž ์ง‘ํ•ฉ ISO 10646์œผ๋กœ ์ •์˜๋œ ๋ฌธ์ž ์ธ์ฝ”๋”ฉ์˜ ๊ตญ์ œ ํ‘œ์ค€

Uint8Array

Uint8Array

Uint8Array ํ˜•์‹ํ™” ๋ฐฐ์—ด(TypedArray) ํ”Œ๋žซํผ์˜ ๋ฐ”์ดํŠธ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ฅด๋Š” 8๋น„ํŠธ ๋ถ€ํ˜ธ ์—†๋Š” ์ •์ˆ˜์˜ ๋ฐฐ์—ด ๋ฐฐ์—ด์˜ ๋‚ด์šฉ์€ 0์œผ๋กœ ์ดˆ๊ธฐํ™”๋จ ๋ฐฐ์—ด์ด ์ƒ์„ฑ๋˜๋ฉด ๊ฐ์ฒด์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ํ‘œ์ค€ ๋ฐฐ์—ด ์ธ๋ฑ์Šค ๊ตฌ๋ฌธ(๋Œ€๊ด„ํ˜ธ ํ‘œ๊ธฐ๋ฒ•)์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฐ์—ด์˜ ์š”์†Œ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Œ

5. CORS

๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…(Same Origin Policy)

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

๐Ÿ”— ์‹ค์Šต ๋งํฌ

์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๊ฐ€์ง„ ๊ธฐ๋ณธ ๋ณด์•ˆ ์ •์ฑ… ์–ด๋–ค ์ถœ์ฒ˜์—์„œ ๋ถˆ๋Ÿฌ์˜จ ๋ฌธ์„œ๋‚˜ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋‹ค๋ฅธ ์ถœ์ฒ˜์—์„œ ๊ฐ€์ ธ์˜จ ๋ฆฌ์†Œ์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๊ฒƒ์„ ์ œํ•œํ•˜๋Š” ๋ณด์•ˆ ๋ฐฉ์‹

๐Ÿšจ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€

Access to fetch at 'http://localhost:3000/products' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

๊ฐœ๋ฐœ์ž ๋„๊ตฌ์˜ ๋„คํŠธ์›Œํฌ ํƒญ์—์„œ ์‚ดํŽด๋ณด๋ฉด ์„œ๋ฒ„์—์„œ response ์‘๋‹ต์€ ์˜ค์ง€๋งŒ(๐ŸŸข 200 OK) ๋™์ผ ์ถœ์ฒ˜๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ง‰ํž˜ โ†’ ์˜ค๋ฅ˜ ๋ฐœ์ƒ

์›น ๋ธŒ๋ผ์šฐ์ €๋Š” Same Origin Policy์— ๋”ฐ๋ผ ์›น ํŽ˜์ด์ง€์™€ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•œ ๊ณณ(์—ฌ๊ธฐ์„œ๋Š” REST API ์„œ๋ฒ„)์ด ์„œ๋กœ ๋‹ค๋ฅธ ์ถœ์ฒ˜(ํฌํŠธ๊นŒ์ง€ ํฌํ•จ)์ผ ๋•Œ, ์„œ๋ฒ„์—์„œ ์–ป์€ ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ ๋ง‰์Œ โš ๏ธ ์„œ๋ฒ„์— ์š”์ฒญํ•˜๊ณ  ์‘๋‹ต์„ ๋ฐ›์•„์˜ค๋Š” ๊ฒƒ๊นŒ์ง€๋Š” ์ด๋ฏธ ์ง„ํ–‰์ด ๋‹ค ๋œ ์ƒํ™ฉ

  • ์ž ์žฌ์ ์œผ๋กœ ํ•ด๋กœ์šธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์„œ๋ฅผ ๋ถ„๋ฆฌํ•ด, ๊ณต๊ฒฉ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ๋กœ๋ฅผ ์ค„์—ฌ์คŒ

  • CORS๋ฅผ ์‚ฌ์šฉํ•ด ๊ต์ฐจ ์ถœ์ฒ˜ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Œ

๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ  (CORS)

๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ  (CORS)

Cross-Origin Resource Sharing CORS๋Š” HTTP์˜ ์ผ๋ถ€๋กœ, ์–ด๋–ค ํ˜ธ์ŠคํŠธ์—์„œ ์ž์‹ ์˜ ์ฝ˜ํ…์ธ ๋ฅผ ๋ถˆ๋Ÿฌ๊ฐˆ ์ˆ˜ ์žˆ๋Š”์ง€ ์„œ๋ฒ„์— ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ์ถœ์ฒ˜๊ฐ€ ๋‹ค๋ฅธ ๊ณณ์ด์–ด๋„ ๊ดœ์ฐฎ์œผ๋ฉฐ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ณต์œ ํ•  ๊ฒƒ์ด๋ผ๊ณ  ์„œ๋ฒ„(๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ณณ) ์—์„œ ์•Œ๋ ค์คŒ

  • REST API ์„œ๋ฒ„์—์„œ Headers์— Access-Control-Allow-Origin ์†์„ฑ์„ ์ถ”๊ฐ€

  • Express์—์„œ๋Š” CORS ๋ฏธ๋“ค์›จ์–ด ๋ฅผ ์„ค์น˜ํ•ด์„œ ์‚ฌ์šฉ

์ถ”๊ฐ€ HTTP ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•ด, ํ•œ ์ถœ์ฒ˜์—์„œ ์‹คํ–‰ ์ค‘์ธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์„ ํƒํ•œ ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋„๋ก ๋ธŒ๋ผ์šฐ์ €์— ์•Œ๋ ค์ฃผ๋Š” ์ฒด์ œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ž์‹ ์˜ ์ถœ์ฒ˜(๋„๋ฉ”์ธ, ํ”„๋กœํ† ์ฝœ, ํฌํŠธ)์™€ ๋‹ค๋ฅผ ๋•Œ ๊ต์ฐจ ์ถœ์ฒ˜ HTTP ์š”์ฒญ์„ ์‹คํ–‰

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

ํŒจํ‚ค์ง€ ์„ค์น˜

npm i cors
npm i -D @types/cors

CORS ๋ฏธ๋“ค์›จ์–ด ์‚ฌ์šฉ

import express from 'express';
import cors from 'cors';

const app = express();

app.use(cors());

Last updated