2. Fetch API & CORS

ํ‚ค์›Œ๋“œ

  • Fetch API๋ž€

  • Promise

  • ReadableStream

  • Unicode

  • CORS๋ž€

Fetch API

๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค

fetch()

  • Promise๋ฅผ ๋ฐ˜ํ™˜

  • ์ฒซ๋ฒˆ์งธ ์ธ์ž๋กœ URL, ๋‘๋ฒˆ์งธ ์ธ์ž๋กœ ์˜ต์…˜ ๊ฐ์ฒด๋ฅผ ๋ฐ›์Œ

  • API ํ˜ธ์ถœ์ด ์„ฑ๊ณตํ–ˆ์„ ๋•Œ๋Š” response ๊ฐ์ฒด๋ฅผ resolve

  • ์‹คํŒจํ–ˆ์„ ๋•Œ๋Š” ์˜ˆ์™ธ(error) ๊ฐ์ฒด๋ฅผ reject

  • ์˜ต์…˜์„ ํ†ตํ•ด HTTP Method, ์š”์ฒญ ํ—ค๋”, ์š”์ฒญ body ๋“ฑ์„ ์„ค์ • ๊ฐ€๋Šฅ

  • response ๊ฐ์ฒด๋Š” HTTP ์‘๋‹ต์ƒํƒœ(status), header, body๋“ฑ์„ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ์Œ

fetch(url, options)
  .then((response) => console.log("response:", response))
  .catch((error) => console.log("error:", error));

Promise

  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์— ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด

  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํŠน์ •์ฝ”๋“œ์˜ ์‹คํ–‰์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋จผ์ € ์ˆ˜ํ–‰

  • ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๋ฐ›๊ธฐ ์ „์— ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œ์‹œํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒ

  • ์‘๋‹ต์„ ๋ฐ›์€ ๋’ค์— ๋‹ค์Œ ๋ช…๋ น์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ํ”„๋กœ๋ฏธ์Šค๋Š” ์ฝœ๋ฐฑ์ด ์ค‘์ฒฉ๋˜์–ด ์ฝ”๋“œ๊ฐ€ ์ฝ๊ธฐ ์–ด๋ ค์›Œ์ง€๋Š” ๊ฑธ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ์Œ

function getData(callback) {
  // new Promise() ์ถ”๊ฐ€
  return new Promise(function(resolve, reject) {
    $.get('url ์ฃผ์†Œ/products/1', function(response) {
      // ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์œผ๋ฉด resolve() ํ˜ธ์ถœ
      resolve(response);
    });
  });
}

// getData()์˜ ์‹คํ–‰์ด ๋๋‚˜๋ฉด ํ˜ธ์ถœ๋˜๋Š” then()
getData().then(function(tableData) {
  // resolve()์˜ ๊ฒฐ๊ณผ ๊ฐ’์ด ์—ฌ๊ธฐ๋กœ ์ „๋‹ฌ๋จ
  console.log(tableData); // $.get()์˜ reponse ๊ฐ’์ด tableData์— ์ „๋‹ฌ๋จ
});

ํ”„๋กœ๋ฏธ์Šค์˜ ์„ธ๊ฐ€์ง€ ์ƒํƒœ

  • Pending(๋Œ€๊ธฐ) : ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๋กœ์ง์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์€ ์ƒํƒœ

  • Fulfilled(์ดํ–‰) : ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜์–ด ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ๊ฒฐ๊ณผ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์ค€ ์ƒํƒœ

  • Rejected(์‹คํŒจ) : ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๊ฐ€ ์‹คํŒจํ•˜๊ฑฐ๋‚˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ์ƒํƒœ

new Promise() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด Pending ์ƒํƒœ๊ฐ€ ๋จ

new Promise() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๊ณ , ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ธ์ž๋Š” resolve์™€ reject

resolve๋ฅผ ์‹คํ–‰ํ•˜๋ฉด Fulfilled ์ƒํƒœ๊ฐ€ ๋จ

์ดํ–‰(์™„๋ฃŒ)์ƒํƒœ๊ฐ€ ๋˜๋ฉด then()์„ ์ด์šฉํ•ด์„œ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ๊ฐ’์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ

function getData() {
  return new Promise(function(resolve, reject) {
    var data = 100;
    resolve(data);
  });
}

// resolve()์˜ ๊ฒฐ๊ณผ ๊ฐ’ data๋ฅผ resolvedData๋กœ ๋ฐ›์Œ
getData().then(function(resolvedData) {
  console.log(resolvedData); // 100
});

reject๋ฅผ ์‹คํ–‰ํ•˜๋ฉด Reject ์ƒํƒœ๊ฐ€ ๋จ

์‹คํŒจ์ƒํƒœ๊ฐ€ ๋˜๋ฉด Error๋ฅผ catch()๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ

function getData() {
  return new Promise(function(resolve, reject) {
    reject(new Error("Request is failed"));
  });
}

// reject()์˜ ๊ฒฐ๊ณผ ๊ฐ’ Error๋ฅผ err์— ๋ฐ›์Œ
getData().then().catch(function(err) {
  console.log(err); // Error: Request is failed
});

GET ๋ฐฉ์‹ ํ˜ธ์ถœํ•˜๊ธฐ

fetch("https://jsonplaceholder.typicode.com/posts/1").then((response) =>
  console.log(response)
);

// ๊ฒฐ๊ณผ
Response {status: 200, ok: true, redirected: false, type: "cors", url: "https://jsonplaceholder.typicode.com/posts/1", โ€ฆ}

๋Œ€๋ถ€๋ถ„์˜ REST API๋Š” JSON ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‘๋‹ตํ•˜๊ธฐ ๋•Œ๋ฌธ์— response ๊ฐ์ฒด๋Š” json() ๋ฉ”์„œ๋“œ ์ œ๊ณต

์‘๋‹ต ๊ฐ์ฒด๋กœ๋ถ€ํ„ฐ JSON ํฌ๋งท์˜ ์‘๋‹ต ์ „๋ฌธ์„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์–ป์„ ์ˆ˜ ์žˆ์Œ

{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipitโ†ตsuscipit recusandae consequuntur โ€ฆstrum rerum est autem sunt rem eveniet architecto"
}

POST ํ˜ธ์ถœ

method ์˜ต์…˜์„ POST๋กœ ์ง€์ •, headers ์˜ต์…˜์œผ๋กœ JSON ํฌ๋งท์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์•Œ๋ ค์ฃผ๊ณ , ์š”์ฒญ ์ „๋ฌธ์„ JSON ํฌ๋งท์œผ๋กœ ์ง๋ ฌํ™”ํ•˜์—ฌ body ์˜ต์…˜์— ์„ค์ •

fetch("https://jsonplaceholder.typicode.com/posts", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "Test",
    body: "I am testing!",
    userId: 1,
  }),
}).then((response) => console.log(response));

// ๊ฒฐ๊ณผ
Response {type: "cors", url: "https://jsonplaceholder.typicode.com/posts", redirected: false, status: 201, ok: true, โ€ฆ}

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ response.json() ํ˜ธ์ถœํ•˜๋ฉด ์‘๋‹ต ์ „๋ฌธ์„ ๊ฐ์ฒด๋กœ ์–ป์„ ์ˆ˜ ์žˆ์Œ

{title: "Test", body: "I am testing!", userId: 1, id: 101}

json() ๋ฉ”์†Œ๋“œ ์—†์ด response ์ฝ์–ด์˜ค๊ธฐ

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);

response.body()๋Š” ReadableStream

  • ReadableStream์€ ๋ฐ”์ดํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์ŠคํŠธ๋ฆผ ์ œ๊ณต

  • ReadableStream.getReader() : Reader๋ฅผ ๋งŒ๋“ค๊ณ  ์ŠคํŠธ๋ฆผ์„ Reader์— ๊ณ ์ •. ์ŠคํŠธ๋ฆผ์ด ๊ณ ์ •๋˜์–ด ์žˆ๋Š” ๋™์•ˆ์—๋Š” ๋‹ค๋ฅธ Reader๋ฅผ ์–ป์„ ์ˆ˜ ์—†์Œ

์ฝ์–ด์˜จ ๊ฐ’์€ byte array -> ๋””์ฝ”๋”ฉํ•ด์„œ ์ฝ์Œ -> json.parse()๋กœ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค๊ธฐ

CORS

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

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

  • ๋‘ URL์˜ ํ”„๋กœํ† ์ฝœ, ํฌํŠธ, ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ชจ๋‘ ๊ฐ™์•„์•ผ ํ•จ

  • ์›น ๋ธŒ๋ผ์šฐ์ €๋Š” Same Origin Policy์— ๋”ฐ๋ผ ์›น ํŽ˜์ด์ง€์™€ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•œ ๊ณณ(์„œ๋ฒ„)์ด ์„œ๋กœ ๋‹ค๋ฅธ ์„œ๋ฒ„์ผ ๋•Œ ์„œ๋ฒ„์—์„œ ์–ป์€ ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ ๋ง‰์Œ

  • ์ด ๋•Œ ์„œ๋ฒ„์— ์š”์ฒญํ•˜๊ณ  ์‘๋‹ต์„ ๋ฐ›์•„์˜ค๋Š” ๊ฑด ์ง„ํ–‰๋œ ์ƒํƒœ์ด์ง€๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ ๋จ

CORS(Cross-Origin Resource Sharing, ๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ )

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

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

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

Last updated