2. Origin๊ณผ CORS

(1) Origin๊ณผ SOP

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ HTML, CSS, JavaScript๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ด๋ฏธ์ง€, ํฐํŠธ, ์™ธ๋ถ€ ์Šคํฌ๋ฆฝํŠธ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฆฌ์†Œ์Šค๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. ์ด๋ ‡๊ฒŒ ๋‹ค์–‘ํ•œ ์›น ๋ฆฌ์†Œ์Šค๋“ค์„ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์€ ๋‹จ์ผ ์„œ๋ฒ„๋กœ๋งŒ ํ–ฅํ•˜์ง€ ์•Š๊ณ , CDN, ์™ธ๋ถ€ API ๊ฐ™์€ ์™ธ๋ถ€ ์ถœ์ฒ˜์˜ ์„œ๋ฒ„๋กœ๋„ ์ „๋‹ฌ๋œ๋‹ค.
์™ธ๋ถ€ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ปจํ…์ธ ๋ฅผ ํ’๋ถ€ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๊ณ , ๊ฐœ๋ฐœ์˜ ํšจ์œจ์„ฑ์„ ๋†’์ธ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋™์‹œ์— ๋ณด์•ˆ ์œ„ํ—˜์„ ์ดˆ๋ž˜ํ•  ๊ฐ€๋Šฅ์„ฑ๋„ ํ‚ค์šด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์•…์˜์ ์ธ ์ œ3์ž๊ฐ€ ์‚ฌ์šฉ์ž์˜ ๊ฐœ์ธ์ •๋ณด๋ฅผ ํƒˆ์ทจํ•˜๋Š” ๋“ฑ ํ—ˆ๊ฐ€๋˜์ง€ ์•Š์€ ๋‚ด๋ถ€ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•˜๋ ค ํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด๋Ÿฌํ•œ ์œ„ํ—˜์„ ๋ฐฉ์–ดํ•˜๊ธฐ ์œ„ํ•ด ์›น ๋ธŒ๋ผ์šฐ์ €๋Š” Origin๊ณผ SOP(Same-Origin Policy, ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…)๋ผ๋Š” ๊ธฐ๋ณธ์ ์ธ ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค.

1) Origin

Origin์€ ์›น ๋ณด์•ˆ์˜ ๊ธฐ๋ณธ ๋‹จ์œ„๋กœ ์›น ๋ฆฌ์†Œ์Šค์˜ ์ถœ์ฒ˜๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ํ”„๋กœํ† ์ฝœ(scheme)+ํ˜ธ์ŠคํŠธ(host)+ํฌํŠธ(port)์˜ ์กฐํ•ฉ์œผ๋กœ ํ‘œํ˜„๋˜๋ฉฐ, URL์˜ ๊ตฌ์กฐ scheme://host[:port][/path][?query]์—์„œ scheme://host[:port]์— ํ•ด๋‹นํ•œ๋‹ค. ์•„๋ž˜ ์˜ˆ์‹œ์—์„œ ๋ฐ‘์ค„์นœ ๋ถ€๋ถ„์ด Origin์ด๋‹ค.
  • https://www.google.com/search?q=cat
  • http://localhost:3000/page1
์›น ๋ธŒ๋ผ์šฐ์ €๋Š” Origin์„ ๊ธฐ์ค€์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์„ ์ œ์–ดํ•œ๋‹ค. ๋˜ํ•œ ์›น ์„œ๋ฒ„๋Š” Origin ์ •๋ณด์—์„œ ์š”์ฒญ์˜ ์ถœ์ฒ˜๋ฅผ ํŒŒ์•…ํ•ด ๋‚ด๋ถ€ ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ์„ ์ œ์–ดํ•œ๋‹ค.

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

์•ž์„œ ์„ค๋ช…ํ•œ ๋Œ€๋กœ ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์€ ๋ณด์•ˆ ์œ„ํ—˜์„ ์ˆ˜๋ฐ˜ํ•œ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ์ ์ธ ๋ณด์•ˆ ์ •์ฑ…์ด SOP์ด๋‹ค.
SOP(Same-Origin Policy, ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…)๋Š” ๊ฐ™์€ Origin์˜ ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ๋งŒ์„ ํ—ˆ์šฉํ•˜๋Š” ๋ณด์•ˆ ์ •์ฑ…์ด๋‹ค. ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•˜๊ณ  ์‘๋‹ต์„ ๋ฐ›์„ ๋•Œ, ๋ธŒ๋ผ์šฐ์ €๋Š” ํ•ด๋‹น ์‘๋‹ต์˜ ์ถœ์ฒ˜์™€ ํ˜„์žฌ ์›น ํŽ˜์ด์ง€์˜ ์ถœ์ฒ˜๋ฅผ ๋น„๊ตํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ถœ์ฒ˜๊ฐ€ ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค์˜ ์ ‘๊ทผ์„ ์ฐจ๋‹จํ•จ์œผ๋กœ์จ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ณด์•ˆ์„ ์œ ์ง€ํ•œ๋‹ค.
๋™์ผ ์ถœ์ฒ˜ ํŒ๋‹จ: http://example.com/dir/page.html์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ
๋™์ผ ์ถœ์ฒ˜ ํŒ๋‹จ: http://example.com/dir/page.html์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ
  • http://example.com/dir/page2.html (ํ—ˆ์šฉ)
  • http://example.com/dir2/page.html (ํ—ˆ์šฉ)
  • https://example.com/dir/page.html (์ฐจ๋‹จ, ํ”„๋กœํ† ์ฝœ ๋ถˆ์ผ์น˜)
  • http://example.com:81/dir/page.html (์ฐจ๋‹จ, ํฌํŠธ ๋ถˆ์ผ์น˜)
  • http://news.example.com/dir/page.html (์ฐจ๋‹จ, ํ˜ธ์ŠคํŠธ ๋ถˆ์ผ์น˜)
ย 
SOP์˜ ์ ์šฉ ์—ฌ๋ถ€๋Š” ์š”์ฒญ์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ๊ฒฐ์ •๋œ๋‹ค. ๋Œ€์ฒด๋กœ HTML ํƒœ๊ทธ๋กœ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์€ ํ—ˆ์šฉ์ด ๋˜๋‚˜, JavaScript๋กœ ์ด๋Ÿฌํ•œ ๋ฆฌ์†Œ์Šค์˜ ๋‚ด์šฉ์„ ์ฝ๊ฑฐ๋‚˜ ์กฐ์ž‘ํ•˜๋ ค๊ณ  ํ•  ๋•Œ SOP๊ฐ€ ์ž‘๋™ํ•œ๋‹ค.
SOP ์ž‘๋™ ์‚ฌ๋ก€
SOP ์ž‘๋™ ์‚ฌ๋ก€
  1. HTML ํƒœ๊ทธ๋ฅผ ํ†ตํ•œ ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค ์š”์ฒญ: SOP ์ œํ•œ ์—†์Œ
    1. <img>, <link>, <script>, <iframe>, <video>, <audio>, <object>, <embed> ๋“ฑ
      • e.g., <img src="https://other-site.com/image.jpg">
  1. ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค๋ฅผ JavaScript๋กœ ์กฐ์ž‘: SOP ์ œํ•œ ์ ์šฉ
    1. <iframe src="https://other-site.com"> ๋‚ด๋ถ€์˜ DOM ์ ‘๊ทผ ๋ถˆ๊ฐ€
      • e.g., iframe.contentDocument.body.innerHTML (์ฐจ๋‹จ)
  1. JavaScript๋ฅผ ์ด์šฉํ•œ ๋น„๋™๊ธฐ ํ†ต์‹ : SOP ์ œํ•œ ์ ์šฉ
    1. XMLHttpRequest, Fetch API๋ฅผ ํ†ตํ•œ ์š”์ฒญ์˜ ์‘๋‹ต ์ œํ•œ
      • e.g., fetch('https://other-site.com/api') (์ฐจ๋‹จ)
  1. ์›น ํฐํŠธ: ๋Œ€์ฒด๋กœ SOP ์ œํ•œ ์ ์šฉ
    1. @font-face ๊ทœ์น™์„ ํ†ตํ•ด ๋กœ๋“œ๋˜๋Š” ์™ธ๋ถ€ ํฐํŠธ ํŒŒ์ผ์€ ์˜ˆ์™ธ์ ์œผ๋กœ SOP ์ œํ•œ ์—†์Œ
      • e.g., @font-face { src: url("https://other-site.com/font.woff2") ... } (ํ—ˆ์šฉ)
SOP ์ œํ•œ์ด ์ ์šฉ๋˜๋Š” ๊ฒฝ์šฐ, ๋ธŒ๋ผ์šฐ์ €๋Š” ์„œ๋ฒ„ ์‘๋‹ต์— ํฌํ•จ๋œ Access-Control-Allow-Origin ํ—ค๋”๋ฅผ ํ™•์ธํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์š”์ฒญ์„ ๋ณด๋‚ธ ์ถœ์ฒ˜๊ฐ€ ํ—ค๋”์— ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€์— ๋”ฐ๋ผ ๋ฆฌ์†Œ์Šค์˜ ์ ‘๊ทผ์„ ๊ฒฐ์ •ํ•œ๋‹ค.
์ด๋ ‡๊ฒŒ ๋ธŒ๋ผ์šฐ์ €๋Š” SOP๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ์™ธ๋ถ€ ์ถœ์ฒ˜๋กœ๋ถ€ํ„ฐ์˜ ๋ฌด๋‹จ ์ ‘๊ทผ์„ ์ฐจ๋‹จํ•˜๊ณ , ์‚ฌ์šฉ์ž ๊ฐœ์ธ์ •๋ณด ์œ ์ถœ, ์ž ์žฌ์ ์ธ ๊ณต๊ฒฉ ์œ„ํ—˜์œผ๋กœ๋ถ€ํ„ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ณดํ˜ธํ•  ์ˆ˜ ์žˆ๋‹ค.
ย 

(2) CORS

1) ์ดํ•ด

SOP์˜ ์—„๊ฒฉํ•œ ๊ทœ์น™์€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•˜์ง€๋งŒ, ๋™์‹œ์— ์ •์ƒ์ ์ธ ์™ธ๋ถ€ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋งˆ์ € ์ฐจ๋‹จํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐํ•œ๋‹ค. ํ˜„๋Œ€ ์›น ๊ฐœ๋ฐœ์—์„œ๋Š” ํ’๋ถ€ํ•œ ์ปจํ…์ธ ์™€ ๊ธฐ๋Šฅ ํ™•์žฅ์„ ์œ„ํ•ด ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค ์ž„๋ฒ ๋“œ, ์™ธ๋ถ€ API ์‚ฌ์šฉ ๋“ฑ์˜ ๊ธฐ๋Šฅ์ด ์‚ฌ์šฉ๋œ๋‹ค. ์ด ๋•Œ ํ˜„์žฌ ์›น ํŽ˜์ด์ง€์™€ ๋‹ค๋ฅธ ์ถœ์ฒ˜, ์ฆ‰ ํฌ๋กœ์Šค ์˜ค๋ฆฌ์ง„์„ ํ†ตํ•œ ํ†ต์‹ ์ด ํ•„์ˆ˜์ ์ด๋ฏ€๋กœ ์ด๋ฅผ ์œ„ํ•ด์„œ SOP ์ œํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค.
CORS(Cross-Origin Resource Sharing, ๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ )๋Š” ์ถ”๊ฐ€ HTTP ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•ด ํฌ๋กœ์Šค ์˜ค๋ฆฌ์ง„(๊ต์ฐจ ์ถœ์ฒ˜)์˜ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค. ์„œ๋ฒ„๊ฐ€ HTTP ์‘๋‹ต ํ—ค๋”์— ์ ‘๊ทผ ํ—ˆ์šฉ ์กฐ๊ฑด์„ ๋ช…์‹œํ•˜๋ฉด, ์ด๋ฅผ ๋งŒ์กฑํ•˜๋Š” ์š”์ฒญ์—๋Š” SOP ์ œํ•œ์ด ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด๋Ÿฌํ•œ ์กฐ๊ฑด์„ ์„ค์ •ํ•˜๋Š” ํ—ค๋”๋ฅผ CORS ํ—ค๋”๋ผ๊ณ  ํ•˜๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ๋Š” ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค์— ์•ˆ์ „ํ•˜๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

2) CORS ํ—ค๋”

์„œ๋ฒ„๋Š” CORS ํ—ค๋”๋กœ ์–ด๋–ค ์ถœ์ฒ˜์™€ ์–ด๋–ค HTTP ๋ฉ”์„œ๋“œ์˜ ์š”์ฒญ์„ ํ—ˆ์šฉํ• ์ง€ ๋“ฑ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜๋Š” Expressยนโพ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ๋งŒ๋“  ์„œ๋ฒ„์— CORS ํ—ค๋”๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ ์ฝ”๋“œ์ด๋‹ค.
/* ์„œ๋ฒ„ ์ธก ์ฝ”๋“œ */ const express = require('express'); const app = express(); // ์„œ๋ฒ„ ์•ฑ ์ƒ์„ฑ app.use((req, res, next) => { // CORS ํ—ค๋”๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด ๋“ฑ๋ก res.header('Access-Control-Allow-Origin', 'https://request-origin.com'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.header('Access-Control-Allow-Credentials', 'true'); res.header('Access-Control-Expose-Headers', 'X-Custom-Header'); next(); });
์‘๋‹ต ํ—ค๋”์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” CORS ๊ด€๋ จ ์„ค์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
  • Access-Control-Allow-Origin: ํ—ˆ์šฉํ•  ์ถœ์ฒ˜๋ฅผ ์ง€์ •. ํ•˜๋‚˜๋งŒ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, URL ๋Œ€์‹  *(์™€์ผ๋“œ์นด๋“œ)๋กœ ํ‘œ๊ธฐํ•˜๋ฉด ๋ชจ๋“  ์ถœ์ฒ˜์˜ ์ ‘๊ทผ์„ ํ—ˆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์Œ
  • Access-Control-Allow-Methods: ํ—ˆ์šฉํ•  HTTP ๋ฉ”์„œ๋“œ ์ง€์ •
  • Access-Control-Allow-Headers: ํ—ˆ์šฉํ•  HTTP ํ—ค๋” ์ง€์ •
  • Access-Control-Allow-Credentials: ์ฟ ํ‚ค, HTTP ์ธ์ฆ ๋“ฑ ์ž๊ฒฉ ์ฆ๋ช…๋ฅผ ํฌํ•จํ•œ ์š”์ฒญ ํ—ˆ์šฉ ์—ฌ๋ถ€ ์ง€์ •
  • Access-Control-Expose-Headers: ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ปค์Šคํ…€ ํ—ค๋” ์ง€์ •
  • Access-Control-Max-Age: ์‚ฌ์ „ ์š”์ฒญยฒโพ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹œํ•  ์‹œ๊ฐ„ ์ง€์ •
์ด ์ค‘ Access-Control-Allow-Origin ํ—ค๋”๋Š” ํ—ˆ์šฉ๋˜์ง€ ์•Š์€ ์ถœ์ฒ˜์˜ ์š”์ฒญ์— ๋Œ€ํ•œ ์„œ๋ฒ„ ์‘๋‹ต์„ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ฐจ๋‹จํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฏ€๋กœ, ํด๋ผ์ด์–ธํŠธ ์ธก ๋ณด์•ˆ ๊ฐ•ํ™”์— ํŠนํžˆ ์ค‘์š”ํ•˜๋‹ค.

3) ์ž‘๋™ ๋ฐฉ์‹

CORS ํ—ค๋” ์„ค์ •์€ ํด๋ผ์ด์–ธํŠธ์˜ ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ์„ ์ œํ•œํ•˜์ง€๋งŒ, ์„œ๋ฒ„๋กœ ์ „์†ก๋˜๋Š” ์š”์ฒญ ์ž์ฒด๋ฅผ ๋ง‰์ง€๋Š” ๋ชปํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ณต๊ฒฉ์ž๊ฐ€ ์‚ฌ์šฉ์ž์˜ ์ธ์ฆ ์ •๋ณด๋ฅผ ํƒˆ์ทจํ•ด ์„œ๋ฒ„์— DELETE ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒฝ์šฐ, ์„œ๋ฒ„๋Š” ์š”์ฒญ์˜ ์ถœ์ฒ˜๋ฅผ ํ™•์ธํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉ์ž์˜ ์ •๋ณด๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ—ˆ์šฉ๋˜์ง€ ์•Š์€ ์ถœ์ฒ˜๋กœ๋ถ€ํ„ฐ์˜ ์š”์ฒญ์ด ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด, CORS๋Š” ๋‹จ์ˆœ ์š”์ฒญ๊ณผ ์œ„ํ—˜ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์š”์ฒญ์„ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ๋‹ค.

โ‘  ๋‹จ์ˆœ ์š”์ฒญ

๊ธฐ์กด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •/์‚ญ์ œํ•˜์ง€ ์•Š๋Š” ์š”์ฒญ์ด๋‹ค. ๊ตฌ์ฒด์ ์œผ๋กœ๋Š” ์•„๋ž˜ ์กฐ๊ฑด์„ ๋ชจ๋‘ ๋งŒ์กฑํ•ด์•ผ ํ•œ๋‹ค. ๋‹จ์ˆœ ์š”์ฒญ ์ฒ˜๋ฆฌ์—์„œ ๋ธŒ๋ผ์šฐ์ €๋Š” ์„œ๋ฒ„์— ๋ฐ”๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์„œ๋ฒ„์˜ ์‘๋‹ต ํ—ค๋”๋ฅผ ํ™•์ธํ•˜์—ฌ CORS ์ •์ฑ…์„ ๊ฒ€์‚ฌํ•œ๋‹ค.
๋‹จ์ˆœ ์š”์ฒญ์˜ ์กฐ๊ฑด: ๋ชจ๋‘ ๋งŒ์กฑํ•˜์ง€ ์•Š์œผ๋ฉด ์‚ฌ์ „ ์š”์ฒญ ์ฒ˜๋ฆฌ๊ฐ€ ๋จ
๋‹จ์ˆœ ์š”์ฒญ์˜ ์กฐ๊ฑด: ๋ชจ๋‘ ๋งŒ์กฑํ•˜์ง€ ์•Š์œผ๋ฉด ์‚ฌ์ „ ์š”์ฒญ ์ฒ˜๋ฆฌ๊ฐ€ ๋จ
  • ๋ฉ”์„œ๋“œ: GET, HEAD, POST ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉ
  • ํ—ค๋”: ์ž๋™ ์„ค์ • ํ—ค๋”์™€ Accept, Accept-Language, Content-Language, Content-Type ์™ธ์˜ ์ปค์Šคํ…€ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ
  • Content-Type ํ—ค๋” ์‚ฌ์šฉ์‹œ: ๊ทธ ๊ฐ’์ด application/x-www-form-urlencoded, multipart/form-data, text/plain ์ค‘ ํ•˜๋‚˜์ธ ๊ฒฝ์šฐ

โ‘ก ์‚ฌ์ „ ์š”์ฒญ(Preflight ์š”์ฒญ)

๊ธฐ์กด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •/์‚ญ์ œํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์š”์ฒญ์œผ๋กœ, ๋‹จ์ˆœ ์š”์ฒญ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ์•Š์œผ๋ฉด ๋ชจ๋‘ ์‚ฌ์ „ ์š”์ฒญ์œผ๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค. ์‚ฌ์ „ ์š”์ฒญ ์ฒ˜๋ฆฌ์—์„œ๋Š” ๋ณธ ์š”์ฒญ ์ „์— ๋ธŒ๋ผ์šฐ์ €๊ฐ€ OPTIONS ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์‚ฌ์ „ ์š”์ฒญ(Preflight)์„ ๋ณด๋‚ธ๋‹ค. ์„œ๋ฒ„๋Š” ํ—ˆ์šฉ๋˜๋Š” ๋ฉ”์„œ๋“œ, ํ—ค๋” ๋“ฑ CORS ์ •์ฑ… ์ •๋ณด๋ฅผ ์‘๋‹ตํ•˜๊ณ , ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ณธ ์š”์ฒญ์ด ํ—ˆ์šฉ๋ ์ง€ ํŒ๋‹จํ•œ ๋’ค, ๊ทธ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋ณธ ์š”์ฒญ์„ ๋ณด๋‚ด ์‘๋‹ต๊ฐ’์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.
์‚ฌ์ „ ์š”์ฒญ์€ ๋ณธ ์š”์ฒญ ์ „์— ์„œ๋ฒ„์˜ CORS ์ •์ฑ…์„ ํ™•์ธํ•จ์œผ๋กœ์จ ๋ถˆํ•„์š”ํ•œ ์š”์ฒญ์„ ๋ฐฉ์ง€ํ•˜๊ณ  ์ถ”๊ฐ€์ ์ธ ๋ณด์•ˆ ๊ณ„์ธต์„ ์ œ๊ณตํ•œ๋‹ค. ์ด ๊ณผ์ •์€ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉฐ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๊ตฌํ˜„ํ•  ํ•„์š”๋Š” ์—†๋‹ค.
[๊ทธ๋ฆผ 2-6] ์‚ฌ์ „ ์š”์ฒญ(Preflight)[๊ทธ๋ฆผ 2-6] ์‚ฌ์ „ ์š”์ฒญ(Preflight)
[๊ทธ๋ฆผ 2-6] ์‚ฌ์ „ ์š”์ฒญ(Preflight)

4) ์‹ค์Šต

โ‘  CORS ์—๋Ÿฌ ์ดํ•ด

CORS ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ฝ˜์†”์—์„œ ์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
[๊ทธ๋ฆผ 2-7] ์•…๋ช…๋†’์€ CORS ์—๋Ÿฌ[๊ทธ๋ฆผ 2-7] ์•…๋ช…๋†’์€ CORS ์—๋Ÿฌ
[๊ทธ๋ฆผ 2-7] ์•…๋ช…๋†’์€ CORS ์—๋Ÿฌ
์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ดํ•ด
์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ดํ•ด
'http://127.0.0.1:5500'์œผ๋กœ๋ถ€ํ„ฐ 'https://www.google.com/'์— fetch ํ•˜๋ ค๋Š” ์ ‘๊ทผ์ด CORS ์ •์ฑ…์— ์˜ํ•ด ์ฐจ๋‹จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Access-Control-Allow-Origin ํ—ค๋”๊ฐ€ ์š”์ฒญํ•œ ๋ฆฌ์†Œ์Šค์— ์—†์Šต๋‹ˆ๋‹ค. ๋ถˆํˆฌ๋ช…ํ•œ ์‘๋‹ตยณโพ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ์š”์ฒญ ๋ชจ๋“œโดโพ๋ฅผ no-cors๋กœ ์„ค์ •ํ•˜๋ฉด CORS๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•œ ์ƒํƒœ๋กœ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  • ์š”์ฒญ ์ถœ์ฒ˜: http://127.0.0.1:5500
  • ์‘๋‹ต ์ถœ์ฒ˜: https://www.google.com/
  • CORS ์—๋Ÿฌ ๋ฐœ์ƒ ์ด์œ : ์„œ๋ฒ„ ์‘๋‹ต์— Access-Control-Allow-Origin ํ—ค๋”๊ฐ€ ์—†์Œ
์—๋Ÿฌ์˜ ์›์ธ์€ ๋ฉ”์‹œ์ง€ ๋‚ด์—์„œ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ์ฃผ๋กœ ์„œ๋ฒ„ ์ธก ์„ค์ •์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ด๊ฒฐ์ด ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๋Š” ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž์™€ ํ˜‘๋ ฅํ•˜์—ฌ ์ ์ ˆํ•œ CORS ์„ค์ •์„ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

โ‘ก ํด๋ผ์ด์–ธํŠธ ์ธก CORS ์„ค์ •

CORS ์—๋Ÿฌ ํ•ด๊ฒฐ์ด ์ฃผ๋กœ ์„œ๋ฒ„ ์ธก ์„ค์ •์— ์˜์กดํ•˜๋Š” ์ด์œ ๋Š” ์„œ๋ฒ„์˜ ๊ธฐ๋ณธ ์„ค์ •์ด CORS๋ฅผ ๊ฑฐ๋ถ€ํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ฐ˜๋ฉด ํด๋ผ์ด์–ธํŠธ ์ธก์˜ ๊ธฐ๋ณธ ์„ค์ •์€ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ CORS๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋˜์–ด ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐœ๋ฐœ์ž๋Š” ์ผ๋ถ€ ์ƒํ™ฉ์—์„œ ์ด๋ฅผ ์ œ์–ดํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
  1. Fetch API์˜ CORS ์š”์ฒญ ๋ชจ๋“œ
    1. Fetch API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด mode ์˜ต์…˜์œผ๋กœ CORS์˜ ์š”์ฒญ ๋ชจ๋“œ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
      fetch(url, { mode: 'cors' }); // ๊ธฐ๋ณธ๊ฐ’ fetch(url, { mode: 'same-origin' }); fetch(url, { mode: 'no-cors' });
      ์š”์ฒญ ๋ชจ๋“œ
      ์˜๋ฏธ
      cors(๊ธฐ๋ณธ๊ฐ’)
      CORS ์‚ฌ์šฉ. ์„œ๋ฒ„์˜ CORS ์„ค์ •์— ๋”ฐ๋ผ ์š”์ฒญ์ด ํ—ˆ์šฉ๋˜๊ฑฐ๋‚˜ ๊ฑฐ๋ถ€๋จ
      same-origin
      CORS ๋ฏธ์‚ฌ์šฉ. ๋™์ผ ์ถœ์ฒ˜ ์š”์ฒญ๋งŒ ํ—ˆ์šฉํ•˜๊ณ , ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ์˜ ์š”์ฒญ์€ ์—๋Ÿฌ ๋ฐœ์ƒ
      no-cors
      CORS ๋ฏธ์‚ฌ์šฉ. ๊ต์ฐจ ์ถœ์ฒ˜ ์š”์ฒญ ์ค‘ ๋‹จ์ˆœ ์š”์ฒญ๋งŒ ํ—ˆ์šฉํ•˜๊ณ , ๋ถˆํˆฌ๋ช…ํ•œ ์‘๋‹ตยณโพ์„ ๋ฐ›์Œ
  1. HTML ์š”์†Œ์˜ crossorigin ์†์„ฑ
    1. HTML ์š”์†Œ์—์„œ ์ „์†ก๋˜๋Š” ์š”์ฒญ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ CORS๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ, crossorigin ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋ฉด CORS ์š”์ฒญ์„ ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.
      <!-- CORS ๋ฏธ์‚ฌ์šฉ --> <img src="https://cross-origin.com/image.jpg"> <!-- ๊ธฐ๋ณธ๊ฐ’ --> <!-- CORS ์‚ฌ์šฉ --> <img src="https://cross-origin.com/image.jpg" crossorigin> <!-- anonymous์™€ ๊ฐ™์Œ --> <img src="https://cross-origin.com/image.jpg" crossorigin="anonymous"> <img src="https://cross-origin.com/image.jpg" crossorigin="use-credentials">
      crossorigin
      ์˜๋ฏธ
      ์†์„ฑ ์—†์Œ(๊ธฐ๋ณธ๊ฐ’)
      CORS ๋ฏธ์‚ฌ์šฉ. ๊ต์ฐจ ์ถœ์ฒ˜ ์š”์ฒญ ์ค‘ ๋‹จ์ˆœ ์š”์ฒญ๋งŒ ํ—ˆ์šฉํ•˜๊ณ , ๋ถˆํˆฌ๋ช…ํ•œ ์‘๋‹ตยณโพ์„ ๋ฐ›์Œ
      anonymous
      CORS ์‚ฌ์šฉ. ์ฟ ํ‚ค, HTTP ์ธ์ฆ ๋“ฑ ์ž๊ฒฉ ์ฆ๋ช… ์—†๋Š” CORS ์š”์ฒญ
      use-credentials
      CORS ์‚ฌ์šฉ. ์ž๊ฒฉ ์ฆ๋ช…์„ ํฌํ•จํ•œ CORS ์š”์ฒญ. CORS ํ—ค๋”์— ํŠน์ • URL ์ง€์ • ํ•„์š”

โ‘ข ์ฟ ํ‚ค๋ฅผ ํฌํ•จํ•˜๋Š” ์š”์ฒญ์˜ CORS ์„ค์ •

HTTP์˜ ๋ฌด์ƒํƒœ์„ฑ์œผ๋กœ ์ธํ•ด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ƒํƒœ ์ •๋ณด ์œ ์ง€์‹œ ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ณด์•ˆ์ƒ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ต์ฐจ ์ถœ์ฒ˜ ์š”์ฒญ์— ์ฟ ํ‚ค๋ฅผ ํฌํ•จ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค. ์ฟ ํ‚ค๋ฅผ ํฌํ•จํ•œ ๊ต์ฐจ ์ถœ์ฒ˜ ์š”์ฒญ์„ ํ—ˆ์šฉํ•˜๋ ค๋ฉด ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ์–‘์ธก ๋ชจ๋‘์— ์ถ”๊ฐ€ ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ ์ธก ์„ค์ •
    • // XMLHttpRequest ์‚ฌ์šฉ์‹œ const xhr = new XMLHttpRequest(); xhr.open('GET', 'https://cross-origin.com/', true); xhr.withCredentials = true; // ๊ธฐ๋ณธ๊ฐ’ false xhr.send();
      // Fetch API ์‚ฌ์šฉ์‹œ fetch('https://cross-origin.com/', { mode: 'cors', credentials: 'include' // ๊ธฐ๋ณธ๊ฐ’ 'same-origin' });
      // Axios ์‚ฌ์šฉ์‹œ axios.get('https://cross-origin.com/', { withCredentials: true // ๊ธฐ๋ณธ๊ฐ’ false });
      credentials์€ ์ฟ ํ‚ค, HTTP ์ธ์ฆ ๋“ฑ ์ž๊ฒฉ ์ฆ๋ช…์„ ์˜๋ฏธํ•œ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ๋Š” ํ†ต์‹ ์— ์ž๊ฒฉ ์ฆ๋ช…์„ ํฌํ•จํ•  ๊ฒƒ์„ ์ง์ ‘ ์„ค์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. XMLHttpRequest, Axios ์‚ฌ์šฉ์‹œ์—” ์ด๋ฅผ ๋ถˆ๋ฆฐ ๊ฐ’์œผ๋กœ ํ‘œํ˜„ํ•˜์ง€๋งŒ, Fetch API์—์„œ๋Š” ์„ธ๊ฐ€์ง€ ์˜ต์…˜์ด ์ฃผ์–ด์ง„๋‹ค.
      credentials
      ์˜๋ฏธ
      omit
      ์ฟ ํ‚ค ์ „์†ก ์•ˆ ํ•จ
      same-origin(๊ธฐ๋ณธ๊ฐ’)
      ๋™์ผ ์ถœ์ฒ˜ ์š”์ฒญ์—๋งŒ ์ฟ ํ‚ค ํฌํ•จ, ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ ์ฟ ํ‚ค ์ „์†ก ๋ฐฉ์ง€
      include
      ๋ชจ๋“  ์š”์ฒญ์— ์ฟ ํ‚ค ํฌํ•จ
  • ์„œ๋ฒ„ ์ธก ์„ค์ •
    • const express = require('express'); const app = express(); // ์„œ๋ฒ„ ์•ฑ ์ƒ์„ฑ app.use((req, res, next) => { // CORS ํ—ค๋”๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด ๋“ฑ๋ก res.header('Access-Control-Allow-Credentials', 'true'); res.header('Access-Control-Allow-Origin', 'https://specific-domain.com'); next(); });
    • Access-Control-Allow-Credentials: true ๊ฐ’์œผ๋กœ ์ฟ ํ‚ค๋ฅผ ํฌํ•จํ•  ๊ฒƒ์„ ์„ค์ •
    • Access-Control-Allow-Origin: ํ—ˆ์šฉํ•  ์ถœ์ฒ˜๋กœ ํŠน์ • URL ์ง€์ •. *(์™€์ผ๋“œ์นด๋“œ) ์‚ฌ์šฉ ๋ถˆ๊ฐ€

โ‘ฃ Proxy ์„œ๋ฒ„๋ฅผ ์ด์šฉํ•œ ์š”์ฒญ ์šฐํšŒ

๋งˆ์ง€๋ง‰์œผ๋กœ ์„œ๋ฒ„ ์ธก ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋„ CORS ์—๋Ÿฌ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•œ๋‹ค. ๋ฐ”๋กœ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„์˜ ์ค‘๊ฐœ ์„œ๋ฒ„์ธ proxy ์„œ๋ฒ„(์ดํ•˜, ํ”„๋ก์‹œ)๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
[๊ทธ๋ฆผ 2-8] ํ”„๋ก์‹œ ์ค‘๊ฐœ ์„œ๋ฒ„[๊ทธ๋ฆผ 2-8] ํ”„๋ก์‹œ ์ค‘๊ฐœ ์„œ๋ฒ„
[๊ทธ๋ฆผ 2-8] ํ”„๋ก์‹œ ์ค‘๊ฐœ ์„œ๋ฒ„
์ด ๋ฐฉ๋ฒ•์—์„œ ํ”„๋ก์‹œ๋Š” ์›น ์„œ๋ฒ„์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„ ์‚ฌ์ด์— ์œ„์น˜ํ•œ๋‹ค. [๊ทธ๋ฆผ 2-8]์—์„œ๋Š” ์›น ์„œ๋ฒ„๊ฐ€ ํ”„๋ก์‹œ ์ž‘์—…์„ ๋ณ‘ํ–‰ํ•˜๊ณ  ์žˆ๋‹ค.
ํ”„๋ก์‹œ ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ์™€ ๋™์ผ ์ถœ์ฒ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ๋ฐ›์„ ๋•Œ CORS ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ์š”์ฒญ์„ ์šฐํšŒํ•ด์„œ ๊ต์ฐจ ์ถœ์ฒ˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„๋กœ ์ „๋‹ฌํ•˜๋Š”๋ฐ, ์ด ๋•Œ์—” ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๋Š” ์„œ๋ฒ„๊ฐ„์˜ ํ†ต์‹ ์ด๋ฏ€๋กœ ์—ญ์‹œ๋‚˜ CORS ์ œํ•œ์ด ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค.
ํ”„๋ก์‹œ ์šฐํšŒ ์‹œ๋‚˜๋ฆฌ์˜ค
ํ”„๋ก์‹œ ์šฐํšŒ ์‹œ๋‚˜๋ฆฌ์˜ค
  1. https://example.com ์‚ฌ์ดํŠธ์—์„œ 'user'๋ผ๋Š” ์‚ฌ์šฉ์ž์˜ ํ”„๋กœํ•„ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•จ
  1. ๋ธŒ๋ผ์šฐ์ €๋Š” https://example.com/api/@user ์ฃผ์†Œ๋กœ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋ƒ„
  1. 2๋ฒˆ์€ ๋™์ผ ์ถœ์ฒ˜ ์š”์ฒญ์ด๊ธฐ ๋•Œ๋ฌธ์— CORS ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ
  1. ์›น ์„œ๋ฒ„์—์„œ /api ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜จ ์š”์ฒญ์€ ํ”„๋ก์‹œ ์„ค์ •์— ์˜ํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„ https://cross-origin.com/@user๋กœ ์šฐํšŒํ•˜์—ฌ ์ „๋‹ฌ๋จ
  1. 4๋ฒˆ์€ ์„œ๋ฒ„ ๊ฐ„ ํ†ต์‹ ์ด๋ฏ€๋กœ ๋ธŒ๋ผ์šฐ์ €์˜ SOP ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์•„ CORS ์ œํ•œ ์—†์Œ
  1. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„๊ฐ€ ์‘๋‹ตํ•˜๋ฉด ํ”„๋ก์‹œ๊ฐ€ ์ด๋ฅผ ์› ์š”์ฒญ์ž์ธ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „๋‹ฌํ•จ

ยนโพ Express๋Š” Node.js๋กœ ์›น ์„œ๋ฒ„๋ฅผ ์‰ฝ๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๋Œ€ํ‘œ์ ์ธ ํ”„๋ ˆ์ž„์›Œํฌ์ด๋‹ค. ์ด ์ฑ…์€ ์„œ๋ฒ„ ์ธก ์ฝ”๋“œ๋ฅผ ์ตœ์†Œํ•œ์œผ๋กœ๋งŒ ๋‹ค๋ฃจ๋ฉฐ Express๋ฅผ ๋ชฐ๋ผ๋„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ์„œ์ˆ ๋˜์—ˆ๋‹ค.
ยณโพ opaque response. ๋ณด์•ˆ ๋ชฉ์ ์— ์˜ํ•ด ๋ฆฌ์†Œ์Šค ์ž์ฒด๋Š” ์‹คํ–‰๋˜๊ณ  ํ™”๋ฉด์— ๋ณด์ด์ง€๋งŒ JavaScript๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๋ฆฌ์†Œ์Šค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฆฌ์†Œ์Šค๊ฐ€ ์ด๋ฏธ์ง€์ผ ๊ฒฝ์šฐ ํ™”๋ฉด์— ํ‘œ์‹œ๋Š” ๋˜์ง€๋งŒ JavaScript๋กœ ํ”ฝ์…€ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผ ๋ถˆ๊ฐ€ํ•จ
ย