Access-Control-Allow-Origin ํ—ค๋” ์™„๋ฒฝ ๊ฐ€์ด๋“œ

Access-Control-Allow-Origin ํ—ค๋” ์™„๋ฒฝ ๊ฐ€์ด๋“œ

D
dongAuthor
5 min read

CORS ์˜ค๋ฅ˜์˜ ์›์ธ์ธ Access-Control-Allow-Origin ํ—ค๋”๋ฅผ ์™„๋ฒฝํžˆ ์ดํ•ดํ•˜๊ณ  ํ•ด๊ฒฐํ•˜์„ธ์š”. ๋ฌธ๋ฒ•, ๋ณด์•ˆ, Nginx/Node.js ์„ค์ • ์˜ˆ์‹œ๊นŒ์ง€ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

์›น ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค ๋ณด๋ฉด ํ•œ ๋ฒˆ์ฏค์€ ์ฝ˜์†”์—์„œ CORS error๋ผ๋Š” ๋ฌด์‹œ๋ฌด์‹œํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋งˆ์ฃผํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด ์˜ค๋ฅ˜๋Š” ๋Œ€๋ถ€๋ถ„ ๋‹ค๋ฅธ ์ถœ์ฒ˜(origin)์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š”๋ฐ์š”, ๋ฐ”๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์—ด์‡ ๊ฐ€ Access-Control-Allow-Origin ํ—ค๋”์— ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€์—์„œ๋Š” ๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ (CORS)์˜ ํ•ต์‹ฌ์ธ Access-Control-Allow-Origin ํ—ค๋”๊ฐ€ ๋ฌด์—‡์ธ์ง€, ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ ์„œ๋ฒ„ ํ™˜๊ฒฝ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์„ค์ •ํ•ด์•ผ ํ•˜๋Š”์ง€ ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๊ธ€์„ ๋๊นŒ์ง€ ์ฝ์œผ์‹œ๋ฉด CORS ์˜ค๋ฅ˜์— ์ž์‹ ๊ฐ ์žˆ๊ฒŒ ๋Œ€์ฒ˜ํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”!

Access-Control-Allow-Origin ์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

Access-Control-Allow-Origin์€ HTTP ์‘๋‹ต ํ—ค๋” ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ "์ด ์‘๋‹ต์€ ํŠน์ • ์ถœ์ฒ˜(origin)์™€ ๊ณต์œ ํ•ด๋„ ๊ดœ์ฐฎ์•„"๋ผ๊ณ  ์•Œ๋ ค์ฃผ๋Š” ์—ญํ• ์„ ํ•˜์ฃ .

์›น ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ณด์•ˆ์ƒ์˜ ์ด์œ ๋กœ '๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…(Same-Origin Policy)'์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. ์ด ์ •์ฑ…์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ž์‹ ์ด ๋กœ๋“œ๋œ ์ถœ์ฒ˜์™€ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๊ฒƒ์„ ๋ง‰์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, https://my-awesome-site.com์—์„œ ์‹คํ–‰๋˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋Š” https://api.another-site.com์˜ API๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ํ˜„๋Œ€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์—ฌ๋Ÿฌ ์„œ๋น„์Šค์˜ API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋“ฑ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค. ์ด๋•Œ ํ•„์š”ํ•œ ๊ฒƒ์ด ๋ฐ”๋กœ ๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ (Cross-Origin Resource Sharing, CORS) ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋ฉฐ, Access-Control-Allow-Origin ํ—ค๋”๋Š” ์ด ๋ฉ”์ปค๋‹ˆ์ฆ˜์˜ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ด๊ณ  ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

CORS์˜ ๋™์ž‘ ๋ฐฉ์‹์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

  1. ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ HTTP ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ, ์š”์ฒญ ํ—ค๋”์˜ Origin ํ•„๋“œ์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์ถœ์ฒ˜๋ฅผ ๋‹ด์•„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  2. ์š”์ฒญ์„ ๋ฐ›์€ ์„œ๋ฒ„๋Š” ์ด ์š”์ฒญ์„ ํ—ˆ์šฉํ• ์ง€ ๊ฒฐ์ •ํ•˜๊ณ , ์‘๋‹ต ํ—ค๋”์˜ Access-Control-Allow-Origin ํ•„๋“œ์— ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•˜๋Š” ์ถœ์ฒ˜๋ฅผ ๋ช…์‹œํ•˜์—ฌ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.
  3. ์‘๋‹ต์„ ๋ฐ›์€ ๋ธŒ๋ผ์šฐ์ €๋Š” ์ž์‹ ์ด ๋ณด๋‚ธ ์š”์ฒญ์˜ Origin ๊ฐ’๊ณผ ์„œ๋ฒ„๊ฐ€ ๋ณด๋‚ด์ค€ Access-Control-Allow-Origin ๊ฐ’์„ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐ’์ด ์ผ์น˜ํ•˜๋ฉด ๋ฆฌ์†Œ์Šค๋ฅผ ์ •์ƒ์ ์œผ๋กœ ๋กœ๋“œํ•˜๊ณ , ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด CORS ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋ฉฐ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ๋ฒ•๊ณผ ์‚ฌ์šฉ๋ฒ•

Access-Control-Allow-Origin ํ—ค๋”๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๊ฐ’์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: <origin>
Access-Control-Allow-Origin: null

๊ฐ ๊ฐ’์ด ์–ด๋–ค ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๋Š”์ง€ ์ž์„ธํžˆ ์‚ดํŽด๋ณด์ฃ .

* (์™€์ผ๋“œ์นด๋“œ)

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ์„ค์ • ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. *๋Š” "๋ชจ๋“  ์ถœ์ฒ˜์—์„œ ์˜ค๋Š” ์š”์ฒญ์„ ํ—ˆ์šฉํ•œ๋‹ค"๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ์–ด๋–ค ๋„๋ฉ”์ธ์—์„œ๋“  ๋‚ด ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์ฃ .

Access-Control-Allow-Origin: *

๊ฐœ๋ฐœ ์ดˆ๊ธฐ ๋‹จ๊ณ„๋‚˜ ๊ณต๊ฐœ API์ฒ˜๋Ÿผ ์ถœ์ฒ˜์— ์ƒ๊ด€์—†์ด ๋ˆ„๊ตฌ๋‚˜ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณตํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ธ์ฆ ์ •๋ณด(credentials)๊ฐ€ ํฌํ•จ๋œ ์š”์ฒญ์—๋Š” *๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์ค‘์š”ํ•œ ์ œ์•ฝ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฟ ํ‚ค๋‚˜ ์ธ์ฆ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์š”์ฒญ์— *๋กœ ์‘๋‹ตํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ณด์•ˆ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

<origin> (ํŠน์ • ์ถœ์ฒ˜)

๊ฐ€์žฅ ์•ˆ์ „ํ•˜๊ณ  ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. https://my-awesome-site.com๊ณผ ๊ฐ™์ด ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•  ์ •ํ™•ํ•œ ์ถœ์ฒ˜๋ฅผ ๋ช…์‹œํ•ฉ๋‹ˆ๋‹ค.

Access-Control-Allow-Origin: https://developer.mozilla.org

์ด๋ ‡๊ฒŒ ์„ค์ •ํ•˜๋ฉด https://developer.mozilla.org์—์„œ ๋ณด๋‚ธ ์š”์ฒญ์— ๋Œ€ํ•ด์„œ๋งŒ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ณต์œ ํ•˜๊ณ , ๊ทธ ์™ธ ๋‹ค๋ฅธ ๋ชจ๋“  ์ถœ์ฒ˜์˜ ์š”์ฒญ์€ ๋ธŒ๋ผ์šฐ์ €์— ์˜ํ•ด ์ฐจ๋‹จ๋ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ์ถœ์ฒ˜๋งŒ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์—ฌ๋Ÿฌ ์ถœ์ฒ˜๋ฅผ ํ—ˆ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์„œ๋ฒ„ ์ธก์—์„œ ์š”์ฒญ์˜ Origin ํ—ค๋” ๊ฐ’์„ ํ™•์ธํ•˜๊ณ  ํ—ˆ์šฉ ๋ชฉ๋ก์— ์žˆ๋Š” ๊ฐ’์œผ๋กœ ๋™์ ์œผ๋กœ ์„ค์ •ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

null

null ๊ฐ’์€ ์•ฝ๊ฐ„ ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋กœ์ปฌ ํŒŒ์ผ(file://)์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฑฐ๋‚˜ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ Origin ํ—ค๋” ๊ฐ’์ด null์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ณด์•ˆ์ƒ null์„ ๋ช…์‹œ์ ์œผ๋กœ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์‹ ์ค‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ”ํžˆ ๊ฒช๋Š” ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

CORS ๊ด€๋ จ ๋ฌธ์ œ ์ค‘ ๊ฐ€์žฅ ํ”ํ•œ ๊ฒƒ์€ ์ธ์ฆ ์ •๋ณด(credentials)๊ฐ€ ํฌํ•จ๋œ ์š”์ฒญ์ด ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

fetch API๋‚˜ XMLHttpRequest๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ credentials: 'include' ์˜ต์…˜์„ ์ฃผ๋ฉด ์ฟ ํ‚ค๋‚˜ ์ธ์ฆ ํ—ค๋”์™€ ๊ฐ™์€ ์ธ์ฆ ์ •๋ณด๋ฅผ ์š”์ฒญ์— ๋‹ด์•„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๊ฒฝ์šฐ, ์„œ๋ฒ„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทœ์น™์„ ๋ฐ˜๋“œ์‹œ ์ง€์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • Access-Control-Allow-Origin ํ—ค๋” ๊ฐ’์œผ๋กœ * ์™€์ผ๋“œ์นด๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋“œ์‹œ ์š”์ฒญ์„ ๋ณด๋‚ธ ํŠน์ • ์ถœ์ฒ˜๋ฅผ ๋ช…์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • Access-Control-Allow-Credentials: true ํ—ค๋”๋ฅผ ์‘๋‹ต์— ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ—ค๋”๊ฐ€ ์—†์œผ๋ฉด ๋ธŒ๋ผ์šฐ์ €๋Š” ์ธ์ฆ ์ •๋ณด๊ฐ€ ํฌํ•จ๋œ ์‘๋‹ต์„ ๊ฑฐ๋ถ€ํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ ์„œ๋ฒ„๊ฐ€ ์™€์ผ๋“œ์นด๋“œ(*)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ธ์ฆ์„ ํ—ˆ์šฉํ•˜๋ ค๊ณ  ํ•˜๋ฉด, ๋ธŒ๋ผ์šฐ์ €๋Š” ์ด ์‘๋‹ต์„ ์œ ํšจํ•˜์ง€ ์•Š์€ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•˜๊ณ  ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ธ์ฆ์ด ํ•„์š”ํ•œ API๋ฅผ ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ ํ—ˆ์šฉํ•  ์ถœ์ฒ˜๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ณด์•ˆ ๊ณ ๋ ค์‚ฌํ•ญ

Access-Control-Allow-Origin: * ์„ค์ •์€ ํŽธ๋ฆฌํ•˜์ง€๋งŒ, ๋ณด์•ˆ ์ธก๋ฉด์—์„œ๋Š” ์ž ์žฌ์ ์ธ ์œ„ํ—˜์„ ์•ˆ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์„ค์ •์€ ์•…์˜์ ์ธ ์‚ฌ์ดํŠธ๋ฅผ ํฌํ•จํ•œ ๋ชจ๋“  ์ถœ์ฒ˜๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์˜ ์„œ๋ฒ„ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” API๋ฅผ *๋กœ ์„ค์ •ํ•ด๋‘๋ฉด ์™ธ๋ถ€์—์„œ ํ•ด๋‹น API๋ฅผ ๋ฌด๋‹จ์œผ๋กœ ํ˜ธ์ถœํ•˜์—ฌ ์ •๋ณด๋ฅผ ํƒˆ์ทจํ•˜๊ฑฐ๋‚˜ ์„œ๋ฒ„์— ๋ถ€๋‹ด์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ณด์•ˆ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ๋”ฐ๋ฅด๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

  • ํ—ˆ์šฉ ๋ชฉ๋ก(Allowlist) ์‚ฌ์šฉ: ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ์ด ํ•„์š”ํ•œ ์ถœ์ฒ˜๋“ค์„ ๋ฏธ๋ฆฌ ์ •์˜ํ•ด๋‘๊ณ , ์„œ๋ฒ„๋Š” ์š”์ฒญ์˜ Origin ํ—ค๋”๊ฐ€ ์ด ๋ชฉ๋ก์— ํฌํ•จ๋œ ๊ฒฝ์šฐ์—๋งŒ ํ•ด๋‹น ์ถœ์ฒ˜๋ฅผ Access-Control-Allow-Origin ๊ฐ’์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.
  • ์ตœ์†Œ ๊ถŒํ•œ์˜ ์›์น™: ๊ผญ ํ•„์š”ํ•œ ์ถœ์ฒ˜์—๋งŒ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•˜๊ณ , ๊ฐ€๋Šฅํ•˜๋ฉด * ์‚ฌ์šฉ์€ ํ”ผํ•˜์„ธ์š”.

์„œ๋ฒ„ ์„ค์ • ์˜ˆ์‹œ

์‹ค์ œ ์„œ๋ฒ„ ํ™˜๊ฒฝ์—์„œ Access-Control-Allow-Origin ํ—ค๋”๋ฅผ ์–ด๋–ป๊ฒŒ ์„ค์ •ํ•˜๋Š”์ง€ Nginx์™€ Node.js(Express)์˜ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Nginx ์„ค์ • ์˜ˆ์‹œ

Nginx์—์„œ๋Š” add_header ์ง€์‹œ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1. ๋ชจ๋“  ์ถœ์ฒ˜ ํ—ˆ์šฉ (๋น„๊ถŒ์žฅ)

# nginx.conf
location / {
    add_header 'Access-Control-Allow-Origin' '*';
    # ... ๋‹ค๋ฅธ ์„ค์ •๋“ค
}

2. ํŠน์ • ์ถœ์ฒ˜๋งŒ ํ—ˆ์šฉ (๊ถŒ์žฅ)

# nginx.conf
location / {
    add_header 'Access-Control-Allow-Origin' 'https://your-domain.com';
    add_header 'Vary' 'Origin'; # ์บ์‹ฑ ๊ด€๋ จ ์ด์Šˆ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€
    # ... ๋‹ค๋ฅธ ์„ค์ •๋“ค
}

์„œ๋ฒ„๊ฐ€ ํŠน์ • ์ถœ์ฒ˜๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋‚ผ ๋•Œ๋Š”, ์‘๋‹ต์ด Origin ์š”์ฒญ ํ—ค๋”์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ์„ ํด๋ผ์ด์–ธํŠธ์™€ ์ค‘๊ฐ„ ์บ์‹œ ์„œ๋ฒ„์— ์•Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด Vary: Origin ํ—ค๋”๋ฅผ ํ•จ๊ป˜ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

Node.js (Express) ์„ค์ • ์˜ˆ์‹œ

Express ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ์‘๋‹ต์— CORS ํ—ค๋”๋ฅผ ์‰ฝ๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. cors์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋” ํŽธ๋ฆฌํ•˜์ง€๋งŒ, ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

1. ๋ชจ๋“  ์ถœ์ฒ˜ ํ—ˆ์šฉ (๋น„๊ถŒ์žฅ)

// app.js
const express = require('express');
const app = express();

app.use((req, res, next) => {
    res.setHeader('Access-Control-Allow-Origin', '*');
    // ํ•„์š”ํ•œ ๋‹ค๋ฅธ CORS ํ—ค๋”๋“ค (Access-Control-Allow-Methods ๋“ฑ)
    next();
});

// ... ๋ผ์šฐํŠธ ์„ค์ •

2. ํŠน์ • ์ถœ์ฒ˜๋งŒ ํ—ˆ์šฉ (๊ถŒ์žฅ)

// app.js
const express = require('express');
const app = express();

const allowedOrigins = ['http://localhost:3000', 'https://your-domain.com'];

app.use((req, res, next) => {
    const origin = req.headers.origin;
    if (allowedOrigins.includes(origin)) {
        res.setHeader('Access-Control-Allow-Origin', origin);
    }
    res.setHeader('Access-Control-Allow-Credentials', 'true');
    // ... ํ•„์š”ํ•œ ๋‹ค๋ฅธ CORS ํ—ค๋”๋“ค
    next();
});

// ... ๋ผ์šฐํŠธ ์„ค์ •

๋” ๋‚˜์€ ์›น์„ ์œ„ํ•œ ์ฒซ๊ฑธ์Œ

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

Access-Control-Allow-Origin ํ—ค๋” ์™„๋ฒฝ ๊ฐ€์ด๋“œ | devdong