BackEnd๐ŸŒฑ/Etc

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

dkswnkk 2022. 7. 14. 23:15

์„œ๋ก 

๋ฐฑ์—”๋“œ๋ฅผ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ ํ”„๋ŸฐํŠธ ๊ฐœ๋ฐœ์ž์™€ ํ˜‘์—…์„ ์ง„ํ–‰ํ•˜๋‹ค ๋ณด๋ฉด ํ•œ ๋ฒˆ์ฏค์€ ์œ„ ์ด๋ฏธ์ง€์ฒ˜๋Ÿผ CORS ์—๋Ÿฌ์— ๋Œ€ํ•ด ๋งž๋‹ฅ๋œจ๋ฆฐ ์ ์ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋ฒˆ ๊ฒŒ์‹œ๊ธ€์—์„œ๋Š” ์ด๋Ÿฌํ•œ CORS๊ฐ€ ๋ญ”์ง€, ๊ทธ๋ฆฌ๊ณ  ์™œ ๋ฐœ์ƒํ•˜๊ณ  ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ•œ๋ฒˆ ์ •๋ฆฌํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

SOP(Same Origin Policy)

CORS๋ฅผ ์•Œ๊ธฐ ์ „์— ๋จผ์ € SOP๋ผ๋Š” ๊ฐœ๋…์— ๋Œ€ํ•ด ๋จผ์ € ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. 

๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…(same-origin policy)์€ ์–ด๋–ค ์ถœ์ฒ˜(origin)์—์„œ ๋ถˆ๋Ÿฌ์˜จ ๋ฌธ์„œ๋‚˜ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋‹ค๋ฅธ ์ถœ์ฒ˜์—์„œ ๊ฐ€์ ธ์˜จ ๋ฆฌ์†Œ์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๊ฒƒ์„ ์ œํ•œํ•˜๋Š” ๋ณด์•ˆ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…์€ ์ž ์žฌ์ ์œผ๋กœ ํ•ด๋ฅผ ๋ผ์น  ์ˆ˜ ์žˆ๋Š” ์š”์ฒญ์„ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ ๊ณต๊ฒฉ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ์ค„์—ฌ์ค๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์ถœ์ฒ˜(origin)๋Š” ์ ‘๊ทผํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” URL์˜ ํ”„๋กœํ† ์ฝœ, ํ˜ธ์ŠคํŠธ(๋„๋ฉ”์ธ), ํฌํŠธ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋‘ ๊ฐ์ฒด์˜ ํ”„๋กœํ† ์ฝœ, ํ˜ธ์ŠคํŠธ, ํฌํŠธ๊ฐ€ ๋ชจ๋‘ ์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ ๊ฐ™์€ ์ถœ์ฒ˜๋ฅผ ๊ฐ€์กŒ๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค.

URL์˜ ๊ตฌ์กฐ

์œ„ ์ด๋ฏธ์ง€์—์„œ HTTP ํ˜น์€ HTTPS์˜ ๊ฒฝ์šฐ๊ฐ€ ํ”„๋กœํ† ์ฝœ์ด ๋˜๊ณ , www.example.com์˜ ๊ฒฝ์šฐ ํ˜ธ์ŠคํŠธ(๋„๋ฉ”์ธ)๊ฐ€ ๋˜๋ฉฐ, 80์˜ ๊ฒฝ์šฐ ํฌํŠธ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ํ”„๋กœํ† ์ฝœ์˜ HTTP๋Š” 80๋ฒˆ, HTTPS๋Š” 443๋ฒˆ ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, 80๋ฒˆ๊ณผ 443๋ฒˆ ํฌํŠธ๋Š” ์ƒ๋žต์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์ •๋ฆฌํ•˜๋ฉด ์ถœ์ฒ˜(Origin)๋ž€ URL ๊ตฌ์กฐ์—์„œ ์‚ดํŽด๋ณธ ํ”„๋กœํ† ์ฝœ, ํ˜ธ์ŠคํŠธ, ํฌํŠธ๋ฅผ ํ•ฉ์นœ ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. 

๋™์ผ ์ถœ์ฒ˜ VS ๋‹ค๋ฅธ ์ถœ์ฒ˜

URL ๊ฒฐ๊ณผ ์ด์œ 
http://example.com/app1/index.html
http://example.com/app2/index.html
๋™์ผ ์ถœ์ฒ˜ ํ”„๋กœํ† ์ฝœ(http)์™€ ํ˜ธ์ŠคํŠธ(example.com) ์ผ์น˜
http://Example.com:80 
http://example.com
๋™์ผ ์ถœ์ฒ˜ HTTP์˜ ๊ธฐ๋ณธ ํฌํŠธ๋Š” 80์ด๋ฏ€๋กœ ์ƒ๋žต๊ฐ€๋Šฅ ํ•˜๊ธฐ์— ๋™์ผ ์ถœ์ฒ˜
(๋Œ€์†Œ๋ฌธ์ž๋Š” ๋™์ผํ•œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ)
http://example.com/app1
https://example.com/app2
๋‹ค๋ฅธ ์ถœ์ฒ˜ ์„œ๋กœ ํ”„๋กœํ† ์ฝœ(http, https)๊ฐ€ ๋‹ค๋ฆ„
http://example.com
http://www.example.com
http://myapp.example.com
๋‹ค๋ฅธ ์ถœ์ฒ˜ ์„œ๋กœ ํ˜ธ์ŠคํŠธ๊ฐ€ ๋‹ค๋ฆ„
http://example.com
http://example.com:8080
๋‹ค๋ฅธ ์ถœ์ฒ˜ ์„œ๋กœ ํฌํŠธ๊ฐ€ ๋‹ค๋ฆ„

๊ทธ๋ ‡๋‹ค๋ฉด ์™œ ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…(same-origin policy, SOP)์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ณด์•ˆ์— ๋„์›€์ด ๋˜๋Š”์ง€ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…(same-origin policy, SOP)์ด ์™œ ํ•„์š”ํ• ๊นŒ?

์œ„ ์ด๋ฏธ์ง€์—์„œ domainA๋ผ๋Š” ์‚ฌ์ดํŠธ์— ์ ‘์†ํ•ด์„œ ๋กœ๊ทธ์ธ์„ ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ์‹œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  domainA๋ผ๋Š” ์‚ฌ์ดํŠธ ๋‚ด์—์„œ pg2๋ผ๋Š” ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ์ˆ˜๋„ ์žˆ๊ณ , domainB๋ผ๋Š” ์‚ฌ์ดํŠธ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ์‹œ๋‹ค.

domainA/pg2๋ผ๋Š” ํŽ˜์ด์ง€์˜ ๊ฒฝ์šฐ ์ด์ „ ํŽ˜์ด์ง€์ธ domainA/pg์™€ ๊ฐ™์€ ์ถœ์ฒ˜(origin) ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋™์ผํ•œ ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ domainB/pg๋ผ๋Š” ํŽ˜์ด์ง€๋Š” domainA์™€๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜(origin)์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ domainB๋ผ๋Š” ์‚ฌ์ดํŠธ์—์„œ๋Š” domainA์— ๋กœ๊ทธ์ธ๋œ ์ •๋ณด๋ฅผ ํƒˆ์ทจํ•˜์—ฌ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์˜จ๋‹ค๊ฑฐ๋‚˜ ํ•˜๋Š” ๋ถˆ๋ฏธ์Šค๋Ÿฌ์šด ์ƒํ™ฉ์ด ์ผ์–ด๋‚  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ด์ œ ์—ฌ๊ธฐ์„œ SOP์˜ ๊ธฐ๋Šฅ์ด ๋ฐœํœ˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. 

  1. domainA์˜ ์ž…์žฅ์—์„œ๋Š” ๋‹ค์Œ ์š”์ฒญ(domainB)์˜ ์ถœ์ฒ˜(origin)๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  2. ํ™•์ธํ•ด ๋ณด๋‹ˆ ์ด ์š”์ฒญ์€ domainB์—์„œ ์™”์Šต๋‹ˆ๋‹ค.
  3. domainA๋Š” ์ด ์š”์ฒญ์ด ๋‹ค๋ฅธ ์ถœ์ฒ˜(origin)์ด๋ผ๊ณ  ํŒ๋‹จ ์ฆ‰, cross origin์ด๋ผ๊ณ  ํŒ๋‹จ์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  4. ๋”ฐ๋ผ์„œ domainB์˜ ์š”์ฒญ์€ ๋ฐ›์•„๋“ค์—ฌ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ๋งŒ์•ฝ ๋‹ค๋ฅธ ์ถœ์ฒ˜(domainB)์˜ ๋ฆฌ์†Œ์Šค๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ• ๊นŒ์š”?

๋ฐ”๋กœ ์ด๋•Œ CORS๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

 

CORS

๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ (Cross Origin Resource Sharing, CORS)๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์ž์›์„ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

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

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์ ์€ ์ฒซ์งธ, ๋‹ค๋ฅธ ์ถœ์ฒ˜์— ์ ‘๊ทผ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๊ณ  ๋‘˜์งธ, ๊ถŒํ•œ์„ ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ์•Œ๋ ค์ฃผ๋Š” ์ฒด์ œ๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

CORS์˜ ์ ‘๊ทผ ๋ฐฉ๋ฒ•์€ ํฌ๊ฒŒ ์„ธ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๋‹จ์ˆœ ์š”์ฒญ(Simple Request)
  2. ์‚ฌ์ „ ์š”์ฒญ(Prefilight Request)
  3. ์ธ์ฆ์ •๋ณด ํฌํ•จ ์š”์ฒญ(Credentialed Request)

 

๋‹จ์ˆœ ์š”์ฒญ(Simple Request)

๋‹จ์ˆœ ์š”์ฒญ์€ ์„œ๋ฒ„์—๊ฒŒ ๋ฐ”๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

๋‹จ์ˆœ ์š”์ฒญ(Simple Request)

์œ„ ์ด๋ฏธ์ง€๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ API๋ฅผ ์š”์ฒญํ•  ๋•Œ ๋ธŒ๋ผ์šฐ์ €(ํฌ๋กฌ, ์›จ์ผ ๋“ฑ)์™€ ์„œ๋ฒ„์˜ ๋™์ž‘์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ด๋ฏธ์ง€์ž…๋‹ˆ๋‹ค.

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

Simple request ์กฐ๊ฑด

์„œ๋ฒ„๋กœ ์ „๋‹ฌํ•˜๋Š” ์š”์ฒญ(request)์ด ์•„๋ž˜์˜ 3๊ฐ€์ง€ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•ด์•ผ ์„œ๋ฒ„๋กœ ์ „๋‹ฌํ•˜๋Š” ์š”์ฒญ์ด ๋‹จ์ˆœ ์š”์ฒญ์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

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

์ฒซ ๋ฒˆ์งธ ์กฐ๊ฑด์€ ์–ด๋ ต์ง€ ์•Š์€ ์กฐ๊ฑด์ด์ง€๋งŒ 2๋ฒˆ, 3๋ฒˆ ์กฐ๊ฑด์€ ๊นŒ๋‹ค๋กœ์šด ์กฐ๊ฑด์ž…๋‹ˆ๋‹ค. 2๋ฒˆ ์กฐ๊ฑด์€ ์‚ฌ์šฉ์ž ์ธ์ฆ์— ์‚ฌ์šฉ๋˜๋Š” Authorization ํ—ค๋”๋„ ํฌํ•จ๋˜์ง€ ์•Š์•„ ๊นŒ๋‹ค๋กœ์šด ์กฐ๊ฑด์ด๋ฉฐ, 3๋ฒˆ ์กฐ๊ฑด์€ ๋งŽ์€ REST API๋“ค์ด Content-Type์œผ๋กœ application/json์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ง€์ผœ์ง€๊ธฐ ์–ด๋ ค์šด ์กฐ๊ฑด์ž…๋‹ˆ๋‹ค.

 

์‚ฌ์ „ ์š”์ฒญ(Preflight request)

์‚ฌ์ „ ์š”์ฒญ(Preflight request) ์š”์ฒญ์€ ์„œ๋ฒ„์— ์˜ˆ๋น„ ์š”์ฒญ์„ ๋ณด๋‚ด์„œ ์•ˆ์ „ํ•œ์ง€ ํŒ๋‹จ ํ›„ ๋ณธ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. 

์‚ฌ์ „ ์š”์ฒญ(Preflight request)

์‚ฌ์ „ ์š”์ฒญ์€ ์‹ค์ œ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•˜๊ธฐ ์ „์— OPTIONS๋ผ๋Š” ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์˜ ๋ฆฌ์†Œ์Šค์— ์š”์ฒญ์ด ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธ ํ›„, ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ์‹ค์ œ ์š”์ฒญ(Actual Request)์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

OPTIONS ๋ฉ”์„œ๋“œ๋กœ ์„œ๋ฒ„์— ์˜ˆ๋น„ ์š”์ฒญ์„ ๋จผ์ € ๋ณด๋‚ด๊ณ , ์„œ๋ฒ„๋Š” ์ด ์˜ˆ๋น„ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ Access-Control-Allow-Origin ํ—ค๋”๋ฅผ ํฌํ•จํ•œ ์‘๋‹ต์„ ๋ธŒ๋ผ์šฐ์ €(ํฌ๋กฌ, ์›จ์ผ ๋“ฑ)์— ๋ณด๋ƒ…๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ €๋Š” ๋‹จ์ˆœ ์š”์ฒญ๊ณผ ๋™์ผํ•˜๊ฒŒ Access-Control-Allow-Origin ํ—ค๋”๋ฅผ ํ™•์ธํ•ด์„œ CORS ๋™์ž‘์„ ์ˆ˜ํ–‰ํ• ์ง€ ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์ „ ์š”์ฒญ ๋ฐฉ์‹์€ ์‚ฌ์ „ ์š”์ฒญ๊ณผ ์‹ค์ œ ์š”์ฒญ ์ด ๋‘ ๋ฒˆ ๋ณด๋‚ด์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด์€ ๋งค๋ฒˆ ํ•˜๋‚˜์˜ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ๋งˆ๋‹ค ๋‘ ๋ฒˆ์˜ ์š”์ฒญ์ด ์™”๋‹ค ๊ฐ”๋‹ค ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ต‰์žฅํžˆ ๋ฆฌ์†Œ์Šค์ ์œผ๋กœ ๋ถ€๋‹ด์ด ๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด OPTIONS ๋ฉ”์„œ๋“œ์˜ ์‘๋‹ต์— ๋Œ€ํ•ด์„œ ๋ธŒ๋ผ์šฐ์ €๋Š” ์บ์‹ฑ์„ ํ•ด๋‘๊ณ  ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ ๋‹ค์Œ ๋˜‘๊ฐ™์€ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ preflight ์บ์‹ฑ๋œ ๊ฒƒ์„ ํ™•์ธํ•˜๊ณ  ๋™์ผํ•œ ์š”์ฒญ์ด๋ผ๋ฉด ์‚ฌ์ „ ์š”์ฒญ์„ ๋ฏธ๋ฆฌ ๋ณด๋‚ด์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ๋ณธ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ถ€๋‹ด์„ ์ค„์ž…๋‹ˆ๋‹ค.

๋”๋ณด๊ธฐ

Preflight Request

  • Origin : ์š”์ฒญ ์ถœ์ฒ˜
  • Access-Control-Request-Method : ์‹ค์ œ ์š”์ฒญ์˜ ๋ฉ”์„œ๋“œ
  • Access-Control-Request-Headers : ์‹ค์ œ ์š”์ฒญ์˜ ์ถ”๊ฐ€ ํ—ค๋”

Preflight Response

  • Access-Control-Allow-Origin : ํ—ˆ๊ฐ€ ์ถœ์ฒ˜
  • Access-Control-Allow-Methods : ํ—ˆ๊ฐ€ ๋ฉ”์„œ๋“œ
  • Access-Control-Allow-Headers : ํ—ˆ๊ฐ€ ํ—ค๋”
  • Access-Control-Max-Age : Preflight ์‘๋‹ต ์บ์‹œ ์‹œ๊ฐ„

์—ฌ๊ธฐ์„œ Preflight Response์˜ ์‘๋‹ต ์ฝ”๋“œ๋Š” 200๋Œ€์—ฌ์•ผ ํ•˜๊ณ  Body๋Š” ๋น„์–ด์žˆ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

 

์ธ์ฆ ์š”์ฒญ(Credentialed Request)

์ธ์ฆ ์š”์ฒญ์€ ์ธ์ฆ ๊ด€๋ จ ํ—ค๋”๋ฅผ ํฌํ•จํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์š”์ฒญ์ž…๋‹ˆ๋‹ค.

  • ํด๋ผ์ด์–ธํŠธ: ์ฟ ํ‚ค ๋˜๋Š” JWT ํ† ํฐ์„ ๋‹ด์•„ ๋ณด๋‚ผ ๊ฒฝ์šฐ credentials : include๋ฅผ ํฌํ•จํ•˜์—ฌ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  • ์„œ๋ฒ„: Access-Control-Allow-Credentials๋ฅผ true๋กœ ์„ค์ • ์‹œ ํด๋ผ์ด์–ธํŠธ์˜ ์ธ์ฆ ํฌํ•จ ์š”์ฒญ ํ—ˆ์šฉ์ด ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.

 

CORS์˜ ํ•ด๊ฒฐ

CORS์˜ ํ•ด๊ฒฐ์—๋Š” ์„ธ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ํ”„๋ŸฐํŠธ ํ”„๋ก์‹œ ์„œ๋ฒ„ ์„ค์ •: ํ”„๋ŸฐํŠธ ์„œ๋ฒ„์—์„œ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ, ๋Œ€์ƒ์˜ URL์„ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
  2. ์ง์ ‘ ํ—ค๋” ์„ค์ •: ์ง์ ‘ ํ—ค๋”์— ์„ค์ •์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  3. ์„œ๋ฒ„์—์„œ ์Šคํ”„๋ง ๋ถ€ํŠธ ๋‚ด ์„ค์ •: ์„ค์ • ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  WebMvcConfigurer์„ ๊ตฌํ˜„ํ•˜๋ฉด addCorsMappings๋ž€ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ CORS์˜ ์ถœ์ฒ˜ ๋ฐ ์„ค์ •์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3๋ฒˆ์˜ ๋ฐฉ๋ฒ•์€ ์•„๋ž˜๋กœ ํ•ด๊ฒฐ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

package com.example.demo.src;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    private static final long MAX_AGE_SECOND = 3600;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true)
                .maxAge(MAX_AGE_SECOND);
    }

}

src ํด๋”์— WebConfig.java ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์—ฌ ์œ„ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ณด์•ˆ์„ ์œ„ํ•ด ์˜๋„์ ์œผ๋กœ ์ œํ•œํ•ด๋†“์€ ๊ธฐ๋Šฅ์„ ์„œ๋ฒ„์—์„œ ๊ฐ•์ œ๋กœ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ข‹์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋ŸฐํŠธ์—์„œ 1๋ฒˆ์˜ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

 

์ฐธ๊ณ 

  1. https://beomy.github.io/tech/browser/cors/
  2. https://www.youtube.com/watch?v=-2TgkKYmJt4&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9CTech 
  3. https://developer.mozilla.org/ko/docs/Glossary/Origin