CORS๋ž€?

niireymikยท2024๋…„ 5์›” 27์ผ

๐Ÿฆ–

์›น ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ, ํŠนํžˆ ํ”„๋ก ํŠธ์—์„œ CORS ๋ฌธ์ œ๊ฐ€ ์ข…์ข… ๋ฐœ์ƒํ•œ๋‹ค. ์ด๋Š” ๋กœ์ปฌ์—์„œ ํ™•์ธ์„ ํ•  ๋•Œ์—๋„, Postman์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ์—๋„ ์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๊ฐ€, ํ”„๋ก ํŠธ์—์„œ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ๋ฉด ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ด๊ธฐ์— ์ฒ˜์Œ ์ง๋ฉดํ•˜๋ฉด ๋‹นํ™ฉ์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์ด๋‹ค. ์ด๋Ÿฌํ•œ CORS ์—๋Ÿฌ๊ฐ€ ์™œ ๋ฐœ์ƒํ•˜๋Š”์ง€, CORS๋ž€ ๋ฌด์—‡์ธ์ง€ ์ œ๋Œ€๋กœ ์•Œ์•„๋ณด์ž! ๐Ÿ€



๐Ÿšง CORS

CORS(Cross-Origin Resource Sharing)์˜ ๊ฐœ๋…์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”, ์šฐ์„  Origin(์ถœ์ฒ˜)์ด ๋ฌด์—‡์ธ์ง€ ์•Œ์•„์•ผ ํ•œ๋‹ค :)

Origin (์ถœ์ฒ˜)

์šฐ๋ฆฌ๊ฐ€ ํ‰์†Œ ์ ‘๊ทผํ•˜๋Š” URL์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค..

์œ„์˜ ๊ตฌ์„ฑ์š”์†Œ ์ค‘์—์„œ Protocol + Host + Port ์ด ์…‹์„ ํ•ฉ์นœ ๋ถ€๋ถ„์„ Origin, ์ถœ์ฒ˜๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ์ด ๋ถ€๋ถ„์ด ๊ฐ™์œผ๋ฉด ๋™์ผ ์ถœ์ฒ˜(Same-Origin), ๋‹ค๋ฅด๋ฉด ๋‹ค๋ฅธ ์ถœ์ฒ˜(Cross-Origin)๋ผ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.


๋‹ค๋ฅธ ์ถœ์ฒ˜ ์š”์ฒญ์˜ ์œ„ํ—˜์„ฑ

์„œ๋กœ ์ถœ์ฒ˜๊ฐ€ ๋‹ค๋ฅธ (Cross-Origin) ์›น์‚ฌ์ดํŠธ ๊ฐ„์˜ ์š”์ฒญ์€ ์ƒ๊ฐ๋ณด๋‹ค ํฐ ์œ„ํ—˜์„ฑ์„ ์ง€๋‹Œ๋‹ค. ์ด๋Š” ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…(SOP)์ด ์กด์žฌํ•˜๋Š” ์ด์œ ์ด๊ธฐ๋„ ํ•˜๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด, ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์š”์ฒญ์€ ์™œ ์œ„ํ—˜ํ• ๊นŒ? ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…์ด ์™œ ํ•„์š”ํ•œ ๊ฑธ๊นŒ?

์šฐ์„  ์•Œ์•„๋‘˜ ๊ฒƒ์€, SOP : ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…์ด๋ž€, ๋™์ผํ•œ ์ถœ์ฒ˜์˜ ์›นํŽ˜์ด์ง€ ์‚ฌ์ด์—์„œ๋งŒ ์š”์ฒญ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œํ•œํ•˜๋Š” ์ •์ฑ…์ด๋‹ค.
์ดํ•ด๋ฅผ ์œ„ํ•ด ์‰ฝ๊ฒŒ ์–˜๊ธฐํ•˜์ž๋ฉด, '์‹ ๋ขฐํ•˜๋Š” ๊ณณ'์œผ๋กœ๋ถ€ํ„ฐ '์‹ ๋ขฐํ•˜์ง€ ์•Š๋Š” ๊ณณ'์œผ๋กœ ๋ณด๋‚ด๋Š” ์š”์ฒญ์„ ๋‚ด ์ปดํ“จํ„ฐ์˜ '๋ธŒ๋ผ์šฐ์ €'๊ฐ€ ๋ง‰๋Š” ๊ฒƒ์ด๋‹ค.

์ง€๋‚œ๋ฒˆ์— ์‚ดํŽด๋ณธ ์ฟ ํ‚ค/์„ธ์…˜/ํ† ํฐ์˜ ๋‚ด์šฉ์„ ์กฐ๊ธˆ ์งš์–ด๋ณด์ž. ์šฐ๋ฆฌ๊ฐ€ ์•ˆ์ „ํ•œ ์›นํŽ˜์ด์ง€A์— ๋กœ๊ทธ์ธํ•˜๋ฉด, ๋งค๋ฒˆ ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•ด์•ผ ํ•˜๋Š” ์ด์ƒํ•œ ์ƒํ™ฉ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ ์ปดํ“จํ„ฐ์˜ ๋ธŒ๋ผ์šฐ์ €๋Š” ์ฟ ํ‚ค์˜ ํ˜•ํƒœ๋กœ ์šฐ๋ฆฌ์˜ ์ •๋ณด๋ฅผ ์ €์žฅํ•ด ๋‘์—ˆ๋‹ค๊ฐ€ ์š”์ฒญ ์‹œ ํ•จ๊ป˜ ๋ณด๋‚ธ๋‹ค.

์ด ์ ์ด ์ค‘์š”ํ•˜๋‹ค. ์šฐ๋ฆฌ์˜ ๋ธŒ๋ผ์šฐ์ €๋Š” ์ค‘์š”ํ•œ '๋กœ๊ทธ์ธ ์ •๋ณด'๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๋งŒ์•ฝ '์‹ ๋ขฐํ•˜์ง€ ์•Š๋Š” ์›นํŽ˜์ด์ง€B'์— ๋ฐฉ๋ฌธํ–ˆ๋‹ค๊ฐ€ (์ด ์›น ํŽ˜์ด์ง€๊ฐ€ ์•…์˜๋ฅผ ๋‘๊ณ  ๋งŒ๋“  ๊ฒƒ์ผ ๊ฒฝ์šฐ) ๋ธŒ๋ผ์šฐ์ €์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ๊ฐ€๊ฑฐ๋‚˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•ด๋ฒ„๋ฆฌ๋Š” ๋ถˆ์ƒ์‚ฌ๊ฐ€ ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋ž˜์„œ ๋“ฑ์žฅํ•œ ๊ฒƒ์ด ๋ฐ”๋กœ ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…์ด๋‹ค!


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

๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…(Same-origin policy)์€ ๋ธŒ๋ผ์šฐ์ €์˜ ์ •์ฑ… ์ค‘ ํ•˜๋‚˜๋กœ, ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ๋ถ€ํ„ฐ ์กฐํšŒ๋œ ์ž์›๋“ค์˜ ์ฝ๊ธฐ ์ ‘๊ทผ์„ ๋ง‰์•„ ๋‹ค๋ฅธ ์ถœ์ฒ˜ ๊ณต๊ฒฉ์„ ์˜ˆ๋ฐฉํ•œ๋‹ค.

์š”์ฒญํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ์™€ ์š”์ฒญ๋ฐ›๋Š” ์„œ๋ฒ„๊ฐ€ ๊ฐ™์€ ์ถœ์ฒ˜์— ์žˆ์œผ๋ฉด ๋™์ผ ์ถœ์ฒ˜, ์„œ๋กœ ๋‹ค๋ฅธ ์„œ๋ฒ„์— ์žˆ์œผ๋ฉด ๋‹ค๋ฅธ ์ถœ์ฒ˜ ์š”์ฒญ์ด๋‹ค.

์ฆ‰, ํ”„๋ก ํŠธ-๋ฐฑ์ด ๊ฐ๊ฐ front-tino.com / back-tino.com์˜ ๋„๋ฉ”์ธ์„ ๊ฐ€์งˆ ๋•Œ front-tino.com์—์„œ back-tino.com์— ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ์ด๊ฒƒ์€ ๋‹ค๋ฅธ ์ถœ์ฒ˜ ์š”์ฒญ์— ํ•ด๋‹นํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ๋™์ผ ์ถœ์ฒ˜ ์š”์ฒญ๋งŒ ์ž์œ ๋กญ๊ฒŒ ์š”์ฒญ์ด ๊ฐ€๋Šฅํ•˜๊ธฐ์— ๊ฐ๊ฐ์ด ์•„๋ฌด๋Ÿฐ ์„ค์ •์„ ํ•ด๋‘์ง€ ์•Š๋Š”๋‹ค๋ฉด ์œ„์ฒ˜๋Ÿผ ํ”„๋ก ํŠธ์—์„œ ๋ฐฑ์— ์š”์ฒญํ•˜๋Š” ๊ฒƒ์€ CORS error๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉฐ ์š”์ฒญ์— ์‹คํŒจํ•œ๋‹ค.



โœจ
๊ทธ๋Ÿฌ๋‚˜, ์ ์ฐจ ์ธํ„ฐ๋„ท์ด ๋ฐœ์ „ํ•˜๊ณ  ํ•œ ์ถœ์ฒ˜์—์„œ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์ž์›์„ ํ•„์š”๋กœ ํ•˜๋Š” ์ƒํ˜ธ์  ๊ด€๊ณ„๊ฐ€ ๋ฐœ์ „ํ•˜๋ฉด์„œ SOP๋Š” ๋งŽ์€ ๋ถˆํŽธ์„ ์•ผ๊ธฐํ–ˆ๋‹ค. ์ด๋•Œ๋ฌธ์— ์ƒˆ๋กญ๊ฒŒ ์ƒ๊ฒจ๋‚œ ๋ธŒ๋ผ์šฐ์ €์˜ ์ •์ฑ…์ด CORS์ด๋‹ค.



CORS (Cross-Origin Resource Sharing) ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์ž์› ๊ณต์œ 

CORS(Cross-Origin Resource Sharing)๋Š” ์ถœ์ฒ˜๊ฐ€ ๋‹ค๋ฅธ ์ž์›๋“ค์„ ๊ณต์œ ํ•œ๋‹ค๋Š” ๋œป์œผ๋กœ, ํ•œ ์ถœ์ฒ˜์— ์žˆ๋Š” ์ž์›์—์„œ ๋‹ค๋ฅธ ์ถœ์ฒ˜์— ์žˆ๋Š” ์ž์›์— ์ ‘๊ทผํ•˜๋„๋ก ํ•˜๋Š” ๊ฐœ๋…์ด๋‹ค.

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ, SOP๋กœ ์ธํ•ด '๋™์ผ ์ถœ์ฒ˜ ๋‚ด์˜ ์š”์ฒญ'์œผ๋กœ๋งŒ ์ œํ•œ๋๋˜ ์š”์ฒญ์— ๋Œ€ํ•ด ๊ทธ ์ œํ•œ์„ ํ’€์–ด์ฃผ๋Š” ๊ฒƒ์ด CORS์ด๋‹ค.

(+) ์ฒ˜์Œ์—๋Š” CORS ์—๋Ÿฌ๋ฅผ ๋ณด๊ณ , CORS๊ฐ€ ์ ‘๊ทผ์„ ๋ง‰๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋Š”๋ฐ, ์˜คํžˆ๋ ค SOP๊ฐ€ ์ ‘๊ทผ์„ ๋ง‰๊ณ  CORS๊ฐ€ ๊ทธ๊ฒƒ์„ ์ผ๋ถ€ ํ’€์–ด์ฃผ๋Š” ๊ฒƒ์ด์—ˆ๋‹ค...!

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



๐Ÿšฅ CORS ์ •์ฑ… 3๊ฐ€์ง€

1. Simple Request

๋‹จ์ˆœ ์š”์ฒญ์€ ์„œ๋ฒ„์— ๋ฐ”๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ํ›„, ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต ํ—ค๋”์— Access-Contorol-Allow-Origin๊ณผ ๊ฐ™์€ ๊ฐ’์„ ๋ณด๋‚ด๋ฉด ๊ทธ ๋•Œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ CORS ์ •์ฑ… ์œ„๋ฐ˜ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์‚ฌํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

์˜ˆ๋น„ ์š”์ฒญ์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋Š” Simple Request๋Š” ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•ด์•ผ ํ•œ๋‹ค.

  • ์š”์ฒญ ๋ฉ”์„œ๋“œ๋Š” GET, HEAD, POST ์ค‘ ํ•˜๋‚˜์—ฌ์•ผ ํ•œ๋‹ค.
  • Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width๋ฅผ ์ œ์™ธํ•œ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
  • ๋งŒ์•ฝ Content-Type๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ application/x-www-form-urlencoded, multipart/form-data, text/plain๋งŒ ํ—ˆ์šฉ๋œ๋‹ค.

-> ํ•˜์ง€๋งŒ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์„ค๊ณ„ํ•˜๊ฒŒ ๋˜๋ฉด ๊ฑฐ์˜ ์ถฉ์กฑ์‹œํ‚ค๊ธฐ ์–ด๋ ค์šด ์กฐ๊ฑด๋“ค์ด๋ฏ€๋กœ, ์‚ฌ์‹ค์ƒ Simple Request์˜ ๊ฒฝ์šฐ๋Š” ๋ณด๊ธฐ ์–ด๋ ต๋‹ค.


2. Preflight Request

์ผ๋ฐ˜์ ์œผ๋กœ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•˜๋ผ ๋•Œ ๊ฐ€์žฅ ๋งŽ์ด ๋งˆ์ฃผ์น˜๋Š” ์ƒํ™ฉ์œผ๋กœ, ์ด ์ƒํ™ฉ์—์„œ ๋ธŒ๋ผ์šฐ์ €๋Š” ์š”์ฒญ์„ ํ•œ ๋ฒˆ์— ๋ณด๋‚ด์ง€ ์•Š๊ณ  ์˜ˆ๋น„ ์š”์ฒญ๊ณผ ๋ณธ ์š”์ฒญ์œผ๋กœ ๋‚˜๋ˆ„์–ด์„œ ์„œ๋ฒ„๋กœ ์ „์†กํ•œ๋‹ค.

๋ณธ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „์— ๋ณด๋‚ด๋Š” ์˜ˆ๋น„ ์š”์ฒญ์„ Prefilght๋ผ๊ณ  ํ•˜๋ฉฐ, ์˜ˆ๋น„ ์š”์ฒญ์—๋Š” HTTP ๋ฉ”์„œ๋“œ ์ค‘ OPTIONS ๋ฉ”์„œ๋“œ๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค. ์˜ˆ๋น„ ์š”์ฒญ์˜ ์—ญํ• ์€ ๋ณธ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „์— ๋ธŒ๋ผ์šฐ์ € ์Šค์Šค๋กœ ์ด ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•œ์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

JavaScript์—์„œ ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๋ช…๋ น์„ ๋‚ด๋ฆฌ๋ฉด ๋ธŒ๋ผ์šฐ์ €๋Š” ์„œ๋ฒ„์—๊ฒŒ ์˜ˆ๋น„ ์š”์ฒญ(OPTIONS)์„ ๋จผ์ € ๋ณด๋‚ธ๋‹ค.

OPTIONS ์š”์ฒญ์„ ๋ฐ›์€ ์„œ๋ฒ„๋Š” Response Header์— ์„œ๋ฒ„๊ฐ€ ํ—ˆ์šฉํ•  ์˜ต์…˜์„ ์„ค์ •ํ•˜์—ฌ ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์‘๋‹ต ํ—ค๋”์— Access-Control-Allow-Origin ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ํ—ˆ์šฉํ•  ๋„๋ฉ”์ธ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์„ค์ •ํ•˜๊ฒŒ ๋˜๋ฉด ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Access-Control-Allow-Origin: https://example.com

๋ธŒ๋ผ์šฐ์ €๋Š” ์„œ๋ฒ„๊ฐ€ ๋ณด๋‚ธ Response ์ •๋ณด๋ฅผ ์ด์šฉํ•˜์—ฌ ํ—ˆ์šฉ๋˜์ง€ ์•Š์€ ์š”์ฒญ์ธ ๊ฒฝ์šฐ 405 Method Not Allowed ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ณ , ์‹ค์ œ ํŽ˜์ด์ง€์˜ ์š”์ฒญ(๋ณธ ์š”์ฒญ)์€ ์„œ๋ฒ„๋กœ ์ „์†กํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋ฐ˜๋Œ€๋กœ ํ—ˆ์šฉ๋œ ์š”์ฒญ์ธ ๊ฒฝ์šฐ, ๋‹ค์‹œ ๋ณธ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์„œ๋ฒ„๊ฐ€ ๋ณธ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๋Š” ์ตœ์ข…์ ์œผ๋กœ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์— ๋„˜๊ฒจ์ค€๋‹ค.


3. Credentialed Request

๋˜ ๋‹ค๋ฅธ ์‹œ๋‚˜๋ฆฌ์˜ค๋Š”, ํ—ค๋”์— ์ธ์ฆ๊ณผ ๊ด€๋ จ๋œ ์ •๋ณด(์ฟ ํ‚ค, ํ† ํฐ ๋“ฑ)๋ฅผ ๋‹ด์•„์„œ ๋ณด๋‚ด๋Š” Credential Request (์ธ์ฆ๋œ ์š”์ฒญ)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

์ด๋Š” CORS์˜ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ์‹์ด๋ผ๊ธฐ ๋ณด๋‹ค๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜ ๊ฐ„ ํ†ต์‹ ์—์„œ ์ข€ ๋” ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

์„œ๋ฒ„๋กœ ์ฟ ํ‚ค๋ฅผ ํ•จ๊ป˜ ์ „์†กํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ, ์š”์ฒญ์— ์ฟ ํ‚ค๊ฐ€ ๋‹ด๊ธฐ๊ฒŒ ๋˜๋ฉด Credentialed Request ํ—ˆ์šฉ์ด ๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์ฆ‰, ์ธ์ฆ๊ณผ ๊ด€๋ จ๋œ ์ •๋ณด๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์˜ต์…˜ 'credentials'๋ฅผ ์ค˜์•ผํ•˜๋Š”๋ฐ, ์ด ๋•Œ ์„œ๋ฒ„ ์ชฝ์—์„œ ์‘๋‹ต ํ—ค๋”์— Access-Control-Allow-Credentials: true๋ฅผ ๋ณด๋‚ด์ฃผ์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‘๋‹ต์„ ๋ฐ›๋Š” ๊ฒƒ์„ ๊ฑฐ๋ถ€ํ•˜๊ฒŒ ๋œ๋‹ค.

์ด ์˜ต์…˜์—๋Š” ์ด 3๊ฐ€์ง€์˜ ๊ฐ’์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ ๊ฐ’๋“ค์ด ๊ฐ€์ง€๋Š” ์˜๋ฏธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

์˜ต์…˜ ๊ฐ’์„ค๋ช…
same-origin(๊ธฐ๋ณธ๊ฐ’)๊ฐ™์€ ์ถœ์ฒ˜ ๊ฐ„ ์š”์ฒญ์—๋งŒ ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค
include๋ชจ๋“  ์š”์ฒญ์— ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค
omit๋ชจ๋“  ์š”์ฒญ์— ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด์ง€ ์•Š๋Š”๋‹ค

๋งŒ์•ฝ same-origin์ด๋‚˜ include์™€ ๊ฐ™์€ ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌ์†Œ์Šค ์š”์ฒญ์— ์ธ์ฆ ์ •๋ณด๊ฐ€ ํฌํ•จ๋œ๋‹ค๋ฉด, ์ด์ œ ๋ธŒ๋ผ์šฐ์ €๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•  ๋•Œ ๋‹จ์ˆœํžˆ Access-Control-Allow-Origin๋งŒ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ข€ ๋” ๋นก๋นกํ•œ ๊ฒ€์‚ฌ ์กฐ๊ฑด์„ ์ถ”๊ฐ€ํ•˜๊ฒŒ ๋œ๋‹ค.

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

  1. Access-Control-Allow-Origin์—๋Š” * (์™€์ผ๋“œ์นด๋“œ)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, ๋ช…์‹œ์ ์ธ URL์ด์–ด์•ผํ•œ๋‹ค.
    (https://foo.com๊ณผ ๊ฐ™์ด ๊ตฌ์ฒด์ ์ธ origin์„ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.)

  2. ์‘๋‹ต ํ—ค๋”์—๋Š” ๋ฐ˜๋“œ์‹œ Access-Control-Allow-Credentials: true๊ฐ€ ์กด์žฌํ•ด์•ผํ•œ๋‹ค.



๐ŸŒฟ Spring Boot์—์„œ cross-origin ์„ค์ •ํ•˜๊ธฐ

SpringBoot์™€ ๊ฐ™์ด ์ผ๋ถ€ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ cross-origin์„ ์ฝ”๋“œ ๋‹จ ๋ช‡์ค„๋งŒ์œผ๋กœ ์‰ฝ๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. SpringBoot์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ์„ค์ •ํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด์ž.

๋ฉ”์„œ๋“œ ์„ค์ •, ์ปจํŠธ๋กค๋Ÿฌ ์„ค์ •์ด ์žˆ์œผ๋ฉฐ ๊ฐœ๋ณ„์ ์œผ๋กœ ์ ์šฉ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๋ฉ”์„œ๋“œ์— ์„ค์ •ํ•˜๊ธฐ

@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin
    @RequestMapping(method = RequestMethod.GET, path = "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

retrieve() ๋ฉ”์„œ๋“œ์— ์„ ์–ธ๋œ @CrossOrigin์˜ ๊ธฐ๋ณธ ์„ค์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
1. ๋ชจ๋“  ์ถœ์ฒ˜๊ฐ€ ํ—ˆ์šฉ๋œ๋‹ค.
2. ํ—ˆ์šฉ๋œ HTTP ๋ฉ”์„œ๋“œ๋Š” @RequestMapping์— ์„ ์–ธ๋œ ๋ฉ”์„œ๋“œ๋“ค์ด๋‹ค.
3. ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์‘๋‹ต์€ 30๋ถ„ ๋™์•ˆ ์บ์‹œ๋œ๋‹ค.


์ปจํŠธ๋กค๋Ÿฌ์— ์„ค์ •ํ•˜๊ธฐ

@CrossOrigin(origins = "http://example.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

    @RequestMapping(method = RequestMethod.GET, path = "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

์ปจํŠธ๋กค๋Ÿฌ์— ์„ค์ •ํ–ˆ์œผ๋ฏ€๋กœ AccountController์— ์žˆ๋Š” retrieve() ์™€ remove() ํ•จ์ˆ˜ ๋ชจ๋‘์— ์ ์šฉ๋œ๋‹ค.


๊ฐœ๋ณ„ ์ ์šฉ์‹œํ‚ค๊ธฐ

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin("http://example.com")
    @RequestMapping(method = RequestMethod.GET, "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

์Šคํ”„๋ง์—์„œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ CORS ์ •์ฑ…์„ ๋ณตํ•ฉํ•ด์„œ ์„ค์ • ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ชจ๋“  ๋ฉ”์„œ์„œ๋“œ๋“ค์€ 3600์ดˆ๊ฐ€ ์บ์‹œ ์‹œ๊ฐ„์ด๋‹ค. retrieve() ๋ฉ”์„œ๋“œ๋Š” ํ—ˆ์šฉ ์ถœ์ฒ˜๊ฐ€ "http://example.com" ๋ฐ–์— ์•ˆ๋œ๋‹ค. ํ•˜์ง€๋งŒ, remove() ๋ฉ”์„œ๋“œ๋Š” ๋ณ„๋„์˜ ์„ค์ •์ด ์—†์œผ๋ฏ€๋กœ ๋ชจ๋“  ์ถœ์ฒ˜๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.


์ „์—ญ ์„ค์ •ํ•˜๊ธฐ

CORS ์ •์ฑ…์˜ ์„ค์ •์€ WebMvcConfigurer๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ํ•„ํ„ฐ ๊ธฐ๋ฐ˜์ด๊ธฐ ๋•Œ๋ฌธ์—, ์ „์—ญ์ ์œผ๋กœ ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด์„œ ๊ฒ€์‚ฌํ•œ๋‹ค.

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}


๐Ÿ’Š CORS ๋ฌธ์ œ ํ•ด๊ฒฐ

์„œ๋‘์—์„œ, ํ”„๋ก ํŠธ์—์„œ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ๋ฉด ๋ฐœ์ƒํ•˜๋Š” CORS์— ๋Œ€ํ•ด์„œ ์–ธ๊ธ‰ํ–ˆ์—ˆ๋‹ค.

CORS์˜ ๊ฐœ๋…์„ ์ดํ•ดํ•˜๊ณ  ์ƒ๊ฐ์„ ๋ฐ”๊พธ๊ฒŒ ๋œ ๊ฒƒ์€, CORS๋Š” ์š”์ฒญ์„ ๋ง‰๋Š” ์ •์ฑ…์ด ์•„๋‹ˆ๋ผ ์˜คํžˆ๋ ค SOP(๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…)๊ฐ€ ์ œํ•œํ•ด๋‘” ์š”์ฒญ์„ ํ’€์–ด์ฃผ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด CORS ์ •์ฑ…์ด๋ผ๋Š” ์‚ฌ์‹ค์ด๋‹ค.

๊ฒฐ๋ก ์ ์œผ๋กœ, CORS ๋ฌธ์ œ์— ๋งž๋‹ฅ๋œจ๋ฆด ๊ฒฝ์šฐ ์œ„์—์„œ ๋‹ค๋ฃฌ cross-origin ์„ค์ •์œผ๋กœ ํ•ด๊ฒฐํ•˜๋ฉด ๋œ๋‹ค! ๐Ÿค—



๐Ÿ“ ์ •๋ฆฌํ•˜๊ธฐ
CORS๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ ์ •์ฑ… ์ค‘ ํ•˜๋‚˜๋กœ, SOP๋กœ ์ œํ•œ๋œ '๋‹ค๋ฅธ ์ถœ์ฒ˜ ์š”์ฒญ'์— ๋Œ€ํ•ด ๊ทธ ์ œํ•œ์„ ํ’€์–ด์ฃผ๋Š” ์ •์ฑ…์ด๋‹ค. ์ฆ‰, ๋‹ค๋ฅธ ์ถœ์ฒ˜ Cross-Origin ์‚ฌ์ด์˜ ์ž์› ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜๋Š” ์ •์ฑ…์ด๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€