Skip to content

Latest commit

ย 

History

History
304 lines (217 loc) ยท 23.7 KB

CORS.md

File metadata and controls

304 lines (217 loc) ยท 23.7 KB

CORS

CORS

์ž‘์„ฑ์ž : ์ „์ฐฌ๋ฏผ

  • ์ฐธ๊ณ ์˜์ƒ: CORS
  • ์ฐธ๊ณ ์ž๋ฃŒ: CORS

SOP (Same Origin Policy)

๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ์ œํ•œํ•˜๋Š” ๋ณด์•ˆ๋ฐฉ์‹

์ถœ์ฒ˜(Origin)๋ž€?

Origin

URL์˜ Protocol, Host, Port๋ฅผ ํ†ตํ•ด ๊ฐ™์€ ์ถœ์ฒ˜์ธ์ง€ ๋‹ค๋ฅธ ์ถœ์ฒ˜์ธ์ง€ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค. Protocol, Host, Port์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋‹ค๋ฅด๋ฉด ๋‹ค๋ฅธ ์ถœ์ฒ˜๋ผ๊ณ  ํ•˜๋Š”๊ฒƒ์ด๊ณ , 3๊ฐ€์ง€๊ฐ€ ๋ชจ๋‘ ๊ฐ™์•„์•ผ์ง€๋งŒ ๊ฐ™์€ ์ถœ์ฒ˜๋ผ ํ•˜๋Š”๊ฒƒ์ด๋‹ค. ์ต์Šคํ”Œ๋กœ๋Ÿฌ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” Port๊ฐ€ ์ถœ์ฒ˜๋ฅผ ํŒ๋‹จํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰, Port๊ฐ€ ๋‹ฌ๋ผ๋„ ๊ฐ™์€ ์ถœ์ฒ˜์ด๋‹ค ๋ผ๊ณ  ์ธํ„ฐ๋„ท ์ต์Šคํ”Œ๋กœ๋Ÿฌ๋Š” ํŒ๋‹จ์„ ํ•œ๋‹ค.

๋ฌธ์ œ!

http://localhost์™€ ๋™์ผ ์ถœ์ฒ˜์ธ url์€?

  1. https://localhost
  2. http://localhost:80
  3. http://127.0.0.1
  4. http://localhost/api/cors

๋‹ต์€ 2๋ฒˆ๊ณผ 4๋ฒˆ์ด๋‹ค.
1๋ฒˆ ๋ณด๊ธฐ๋Š” http, ์ฆ‰ Protocol์ด ๋‹ค๋ฅด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ์ถœ์ฒ˜๋ผ ๋ณด์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. 2๋ฒˆ์€ ํฌํŠธ80์ด ๋ถ™์–ด์ ธ ์žˆ๋Š”๋ฐ http๊ธฐ๋ณธ port๋ฒˆํ˜ธ๊ฐ€ 80์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ์ถœ์ฒ˜๋ผ ๋ณด์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์œ„์˜ ๋ณด๊ธฐ์—์„œ๋Š” ์ƒ๋žต์ด ๋œ ์ƒํƒœ์ด๋‹ค. 3๋ฒˆ์€ 127.0.0.1.์˜ IP๋Š” localhost๊ฐ€ ๋งž๋‹ค. ๊ทธ๋ ‡์ง€๋งŒ ๋ธŒ๋ผ์šฐ์ € ์ž…์žฅ์—์„œ๋Š” ์ด๊ฑฐ๋ฅผ String value๋ฅผ ์„œ๋กœ ๋น„๊ต๋ฅผ ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ String value๊ฐ€ localhost์™€ 127.0.0.1์ด ์„œ๋กœ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๋ธŒ๋ผ์šฐ์ € ์ž…์žฅ์—์„œ๋Š” ๋‹ค๋ฅธ์ถœ์ฒ˜๋ผ๊ณ  ํŒ๋‹จ์„ ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค. 4๋ฒˆ์€ api/cors ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์ถ”๊ฐ€์ ์œผ๋กœ ๋ถ™๋Š” ๋กœ์ผ€์ด์…˜์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— api ์•ž์—๊นŒ์ง€ ๋น„๊ต๋ฅผ ํ•ด์„œ ์ด๊ฒƒ์€ ๋™์ผ ์ถœ์ฒ˜์ด๋‹ค ๋ผ๊ณ  ํŒ๋‹จ์„ ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

SOP๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ์ œํ•œํ•˜๋Š” ๋ณด์•ˆ๋ฐฉ์‹์ด๋ผ๊ณ  ํ•˜๋Š”๋ฐ ์™œ ์ด๋Ÿฐ SOP๋ฅผ ์‚ฌ์šฉ์„ ํ•ด์•ผ ๋ณด์•ˆ์— ๋„์›€์„ ์ค„๊นŒ?

SOP
์—ฌ๊ธฐ ์„ ๋Ÿ‰ํ•œ ์ฐฌ๋ฏผ์ด ์žˆ๋‹ค. ์ฐฌ๋ฏผ์ด๊ฐ€ ํŽ˜์ด์Šค๋ถ ์„œ๋น„์Šค์— ๋กœ๊ทธ์ธ์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ด์ œ ๋กœ๊ทธ์ธ์„ ํ•˜๊ฒŒ ๋˜๋ฉด ํŽ˜์ด์Šค๋ถ ์ธ์ฆ ํ† ํฐ์„ ๋ฐ›์•„์˜จ๋‹ค. ์„ ๋Ÿ‰ํ•œ ์ฐฌ๋ฏผ์€ ํŽ˜์ด์Šค๋ถ์— ์ธ์ฆ ํ† ํฐ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค๊ฐ€ ํ•ด์ปค์šฐ์˜์ด ํฅ๋ฏธ์ง„์ง„ํ•œ ๋‚ด์šฉ๊ณผ ๋งํฌ๋ฅผ ๋ฉ”์ผ์„ ํ†ตํ•ด์„œ ๋ณด๋‚ธ๋‹ค. ๊ทธ๋ž˜์„œ ์„ ๋Ÿ‰ํ•œ ์ฐฌ๋ฏผ์€ ํด๋ฆญ์„ ํ•œ๋‹ค. ํด๋ฆญ์„ ํ•˜๋‹ˆ๊นŒ ํ•ด์ปค๊ฐ€ ๋งŒ๋“  ์ฃผ์†Œ๋กœ ์ด๋™์„ ํ•˜๊ฒŒ ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ ํ•ด์ปค๋Š” ์Šคํฌ๋ฆฝํŠธ๋กœ "ํŽ˜์ด์Šค๋ถ์— ๋‚˜๋Š” ๋ฐ”๋ณด๋‹ค ๋ผ๋Š” ํฌ์ŠคํŠธ๋ฅผ ๋“ฑ๋กํ•ด" ๋ผ๋Š” ์ŠคํŠธ๋ฆฝํŠธ๊ฐ€ ์ž‘์„ฑ์ด ๋˜์–ด ์žˆ๋Š” ์ƒํƒœ์ด๋‹ค. ๊ทธ๋ž˜์„œ ๋งํฌ๋ฅผ ํƒ€๊ณ  ๋“ค์–ด๊ฐ”๋”๋‹ˆ ์Šคํฌ๋ฆฝํŠธ์˜ ๋‚ด์šฉ์ด ์‹คํ–‰๋œ๋‹ค. ์•„๊นŒ ์ด์•ผ๊ธฐ ํ–ˆ๋“ฏ ์„ ๋Ÿ‰ํ•œ ์ฐฌ๋ฏผ์€ ํŽ˜์ด์Šค๋ถ์— ์ž๊ธฐ์ธ์ฆ ํ† ํฐ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ํ•ด์ปค๋Š” ๊ทธ ์ธ์ฆํ† ํฐ์„ ๊ฐ€์ง€๊ณ  ํŽ˜์ด์Šค๋ถ์— ๋‚˜๋Š” ๋ฐ”๋ณด๋‹ค ํฌ์ŠคํŠธ๋ฅผ ๊ฐœ์‹œํ•˜๋ผ๊ณ  ๋ช…๋ น์„ ํ•˜๊ฒŒ ๋œ๋‹ค. ๊ทผ๋ฐ ์ด์ œ ์—ฌ๊ธฐ์„œ SOP๊ฐ€ ์ •๋ง๋กœ ์œ„๋ ฅ์„ ๋ฐœํœ˜ํ•œ๋‹ค. ํŽ˜์ด์Šค๋ถ ์ž…์žฅ์—์„  origin์„ ํ™•์ธํ•œ๋‹ค. ์ด ์š”์ฒญ์˜ ์ถœ์ฒ˜๋ฅผ ํ™•์ธํ•˜๋‹ˆ๊นŒ hacker.ck์—์„œ ์˜จ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํŽ˜์ด์Šค๋ถ ์ž…์žฅ์—์„œ๋Š” ์ž๊ธฐ ์ถœ์ฒ˜์™€ ๋‹ค๋ฅด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ด origin์€ ๋‹ค๋ฅธ ์ถœ์ฒ˜๋ผ๊ณ  ํŒ๋‹จ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฆ‰, cross origin์ด๋ผ๊ณ  ํŒ๋‹จ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— SOP์— ์œ„๋ฐ˜๋œ๋‹ค. ๊ทธ๋ž˜์„œ ์ด ์š”์ฒญ์€ ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์—†๋‹ค๊ณ  ์ด์•ผ๊ธฐ๋ฅผ ํ•œ๋‹ค.

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

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

CORS์˜ ๋™์ž‘ ๋ฐฉ๋ฒ•

๊ธฐ๋ณธ์ ์œผ๋กœ ์›น ํด๋ผ์ด์–ธํŠธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•  ๋•Œ๋Š” HTTP ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ๋•Œ ๋ธŒ๋ผ์šฐ์ €๋Š” ์š”์ฒญํ—ค๋”์— Origin ์ด๋ผ๋Š” ํ•„๋“œ์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์ถœ์ฒ˜๋ฅผ ํ•จ๊ป˜ ๋‹ด์•„๋ณด๋‚ธ๋‹ค.

Origin : https://even-moon.github.io

์ดํ›„ ์„œ๋ฒ„๊ฐ€ ์ด ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ํ•  ๋•Œ ์‘๋‹ต ํ—ค๋”์˜ Access-Control-Allow-Origin์ด๋ผ๋Š” ๊ฐ’์— "์ด ๋ฆฌ์†Œ์Šค๋ฅผ ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์ด ํ—ˆ์šฉ๋œ ์ถœ์ฒ˜" ๋ฅผ ๋‚ด๋ ค์ฃผ๊ณ , ์ดํ›„ ์‘๋‹ต์„ ๋ฐ›์€ ๋ธŒ๋ผ์šฐ์ €๋Š” ์ž์‹ ์ด ๋ณด๋ƒˆ๋˜ ์š”์ฒญ์˜ Origins๊ณผ ์„œ๋ฒ„๊ฐ€ ๋ณด๋‚ด์ค€ Access-Control-Allow-Origin์„ ๋น„๊ตํ•ด๋ณธ ํ›„ ์ด ์‘๋‹ต์ด ์œ ํšจํ•œ ์‘๋‹ต์ธ์ง€ ์•„๋‹Œ์ง€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค.

CORS ์ ‘๊ทผ์ œ์–ด ์‹œ๋‚˜๋ฆฌ์˜ค

  • ๋‹จ์ˆœ์š”์ฒญ (Simple Request)
  • ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ (Preflight Request)
  • ์ธ์ฆ์ •๋ณด ํฌํ•จ ์š”์ฒญ (Credentialed Request)

Preflight Request

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

Preflight
์šฐ๋ฆฌ๊ฐ€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ fetch API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ›์•„ ์˜ค๋ผ๋Š” ๋ช…๋ น์„ ๋‚ด๋ฆฌ๋ฉด ์„œ๋ฒ„์—๊ฒŒ ์˜ˆ๋น„์š”์ฒญ์„ ๋จผ์ € ๋ณด๋‚ด๊ณ , ์„œ๋ฒ„๋Š” ์ด ์˜ˆ๋น„ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ํ˜„์žฌ ์ž์‹ ์ด ์–ด๋–ค ๊ฒƒ๋“ค์„ ํ—ˆ์šฉํ•˜๊ณ , ์–ด๋–ค ๊ฒƒ๋“ค์„ ๊ธˆ์ง€ํ•˜๊ณ  ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์‘๋‹ต ํ—ค๋”์— ๋‹ด์•„์„œ ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ๋‹ค์‹œ ๋ณด๋‚ด์ฃผ๊ฒŒ๋œ๋‹ค.

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

์ด ํ”Œ๋กœ์šฐ๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ ์ฝ˜์†”์—์„œ๋„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์žฌํ˜„ํ•ด๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ, RSS ํŒŒ์ผ ๋ฆฌ์†Œ์Šค์— ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ณธ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ์ „์— OPTIONS ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ˆ๋น„์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

const headers = new Headers({
  "Content-Type": "text/xml",
});
fetch("https://evanmoon.tistory.com/rss", { headers });
OPTIONS https://evanmoon.tistory.com/rss

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,ko;q=0.8,ja;q=0.7,la;q=0.6
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: GET
Connection: keep-alive
Host: evanmoon.tistory.com
Origin: https://evan-moon.github.io
Referer: https://evan-moon.github.io/2020/05/21/about-cors/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site

์‹ค์ œ๋กœ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ณด๋‚ธ ์š”์ฒญ์„ ๋ณด๋ฉด, ๋‹จ์ˆœํžˆ Origin์— ๋Œ€ํ•œ ์ •๋ณด ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ž์‹ ์ด ์˜ˆ๋น„์š”์ฒญ ์ดํ›„์— ๋ณด๋‚ผ ๋ณธ ์š”์ฒญ์— ๋Œ€ํ•œ ๋‹ค๋ฅธ ์ •๋ณด๋“ค๋„ ํ•จ๊ป˜ ํฌํ•จ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด ์˜ˆ๋น„ ์š”์ฒญ์—์„œ ๋ธŒ๋ผ์šฐ์ €๋Š” Access-Control-Request-Headers๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž์‹ ์ด ๋ณธ ์š”์ฒญ์—์„œ Content-Typeํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์„ ์•Œ๋ ค์ฃผ๊ฑฐ๋‚˜, Access-Control-Request-Method๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ดํ›„ GET๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์„ ์„œ๋ฒ„์—๊ฒŒ ๋ฏธ๋ฆฌ ์•Œ๋ ค์ฃผ๊ณ  ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

OPTIONS https://evanmoon.tistory.com/rss 200 OK

Access-Control-Allow-Origin: https://evanmoon.tistory.com
Content-Encoding: gzip
Content-Length: 699
Content-Type: text/xml; charset=utf-8
Date: Sun, 24 May 2020 11:52:33 GMT
P3P: CP='ALL DSP COR MON LAW OUR LEG DEL'
Server: Apache
Vary: Accept-Encoding
X-UA-Compatible: IE=Edge

์—ฌ๊ธฐ์„œ ๋ด์•ผ ํ•  ๊ฒƒ์€ ์„œ๋ฒ„๊ฐ€ ๋ณด๋‚ด์ค€ ์‘๋‹ตํ—ค๋”์— ํฌํ•จ๋œ Access-Control-Allow-Origin: https://evanmoon.tistory.com ๋ผ๋Š” ๊ฐ’์ด๋‹ค. ์„œ๋ฒ„๋Š” ์ด ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•œ ์ถœ์ฒ˜๋Š” ์˜ค์ง https://evanmoon.tistory.com ๋ฟ์ด๋ผ๊ณ  ๋ธŒ๋ผ์šฐ์ €์—๊ฒŒ ์ด์•ผ๊ธฐํ•ด์ค€ ๊ฒƒ์ด๊ณ , ์ด ์š”์ฒญ์„ ๋ณด๋‚ธ ์ถœ์ฒ˜๋Š” https://evan-moon.github.io์ด๋ฏ€๋กœ ์„œ๋ฒ„๊ฐ€ ํ—ˆ์šฉํ•ด์ค€ ์ถœ์ฒ˜์™€๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜์ด๋‹ค. ๊ฒฐ๊ตญ ๋ธŒ๋ผ์šฐ์ €๋Š” ์ด ์š”์ฒญ์ด CORS ์ •์ฑ…์„ ์œ„๋ฐ˜ํ–ˆ๋‹ค๊ณ  ํŒ๋‹จํ•˜๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๋ฅผ ๋ฑ‰๋Š”๋‹ค.

๐Ÿšจ Access to fetch at โ€˜https://evanmoon.tistory.com/rssโ€™ from origin โ€˜https://evan-moon.github.ioโ€™ has been blocked by CORS policy: Response to preflight request doesnโ€™t pass access control check: The โ€˜Access-Control-Allow-Originโ€™ header has a value โ€˜http://evanmoon.tistory.comโ€™ that is not equal to the supplied origin. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the requestโ€™s mode to โ€˜no-corsโ€™ to fetch the resource with CORS disabled.

์ด๋•Œ ์˜ˆ๋น„ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  ์ •์ƒ์ ์œผ๋กœ 200์ด ๋–จ์–ด์กŒ๋Š”๋ฐ, ์ฝ˜์†” ์ฐฝ์—๋Š” ๋นจ๊ฐ›๊ฒŒ ์—๋Ÿฌ๊ฐ€ ํ‘œ์‹œ๋˜๊ธฐ ๋–„๋ฌธ์— ๋งŽ์€ ๋ถ„๋“ค์ด ํ—ท๊ฐˆ๋ คํ•˜์‹œ๋Š”๋ฐ, CORS ์ •์ฑ… ์œ„๋ฐ˜์œผ๋กœ ์ธํ•œ ์—๋Ÿฌ๋Š” ์˜ˆ๋น„ ์š”์ฒญ์˜ ์„ฑ๊ณต ์—ฌ๋ถ€์™€ ๋ณ„ ์ƒ๊ด€์ด ์—†๋‹ค. ๋ธŒ๋ผ์šฐ์ €๊ฐ€ CORS ์ •์ฑ… ์œ„๋ฐ˜ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•˜๋Š” ์‹œ์ ์€ ์˜ˆ๋น„ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ๋ฐ›์€ ์ดํ›„์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ฌผ๋ก  ์˜ˆ๋น„ ์š”์ฒญ ์ž์ฒด๊ฐ€ ์‹คํŒจํ•ด๋„ ๋˜‘๊ฐ™์ด CORS ์ •์ฑ… ์œ„๋ฐ˜์œผ๋กœ ์ฒ˜๋ฆฌ๋  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ค‘์š”ํ•œ ๊ฒƒ์€ ์˜ˆ๋น„ ์š”์ฒญ์˜ ์„ฑ๊ณต/์‹คํŒจ ์—ฌ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ผ "์‘๋‹ต ํ—ค๋”์— ์œ ํšจํ•œ Access-Control-Allow-Origin๊ฐ’์ด ์กด์žฌํ•˜๋Š” ๊ฐ€" ์ด๋‹ค. ๋งŒ์•ฝ ์˜ˆ๋น„ ์š”์ฒญ์ด ์‹คํŒจํ•ด์„œ 200์ด ์•„๋‹Œ ์ƒํƒœ์ฝ”๋“œ๊ฐ€ ๋‚ด๋ ค์˜ค๋”๋ผ๋„ ํ—ค๋”์— ์ € ๊ฐ’์ด ์ œ๋Œ€๋กœ ๋“ค์–ด๊ฐ€ ์žˆ๋‹ค๋ฉด CORS ์ •์ฑ…์œ„๋ฐ˜์ด ์•„๋‹ˆ๋ผ๋Š” ์˜๋ฏธ์ด๋‹ค.

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

Simple Request

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

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

  1. ์š”์ฒญ์˜ ๋ฉ”์†Œ๋“œ๋Š” 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๋งŒ ํ—ˆ์šฉ๋œ๋‹ค.

1๋ฒˆ ์กฐ๊ฑด์˜ ๊ฒฝ์šฐ๋Š” ๊ทธ๋ƒฅ PUT์ด๋‚˜ DELETE๊ฐ™์€ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ๋˜๋Š” ๊ฒƒ ๋ฟ์ด๋‹ˆ ๊ทธ๋ ‡๊ฒŒ ๋ณด๊ธฐ ๋“œ๋ฌธ ์ƒํ™ฉ์€ ์•„๋‹ˆ์ง€๋งŒ, 2๋ฒˆ์ด๋‚˜ 3๋ฒˆ ์กฐ๊ฑด ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ๊นŒ๋‹ค๋กญ๋‹ค. ์ € ์กฐ๊ฑด์— ๋ช…์‹œ๋œ ํ—ค๋”๋“ค์€ ์ง„์งœ ๊ธฐ๋ณธ์ ์ธ ํ—ค๋”๋“ค์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋ณต์žกํ•œ ์ƒ์šฉ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ด ํ—ค๋”๋“ค ์™ธ์— ์ถ”๊ฐ€์ ์ธ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋Š” ๋“œ๋ฌผ๋‹ค. ์‚ฌ์šฉ์ž ์ธ์ฆ์— ์‚ฌ์šฉ๋˜๋Š” Authorization ํ—ค๋” ์กฐ์ฐจ ์ € ์กฐ๊ฑด์—๋Š” ํฌํ•จ๋˜์ง€ ์•Š๋Š”๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ HTTP API๋Š” text/xml์ด๋‚˜ application/json์ปจํ…์ธ  ํƒ€์ž…์„ ๊ฐ€์ง€๋„๋ก ์„ค๊ณ„๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ์กฐ๊ฑด๋“ค์„ ๋ชจ๋‘ ๋งŒ์กฑ์‹œํ‚ค๋Š” ์ƒํ™ฉ์„ ๋งŒ๋“ค๊ธฐ๋Š” ๊ทธ๋ ‡๊ฒŒ ์‰ฝ์ง€์•Š๋‹ค.

Credentialed Request

CORS์˜ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ์‹์ด๋ผ๊ธฐ ๋ณด๋‹ค๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜ ๊ฐ„ ํ†ต์‹ ์—์„œ ์ข€ ๋” ๋ณด์•ˆ์„ ๊ฐ•ํ™”ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋น„๋™๊ธฐ ๋ฆฌ์†Œ์Šค ์š”์ฒญ API์ธ XMLHttpRequest๊ฐ์ฒด๋‚˜ fetch API๋Š” ๋ณ„๋„์˜ ์˜ต์…˜ ์—†์ด ๋ธŒ๋ผ์šฐ์ €์˜ ์ฟ ํ‚ค ์ •๋ณด๋‚˜ ์ธ์ฆ๊ณผ ๊ด€๋ จ๋œ ํ—ค๋”๋ฅผ ํ•จ๋ถ€๋กœ ์š”์ฒญ์— ๋‹ด์ง€ ์•Š๋Š”๋‹ค. ์ด ๋•Œ ์š”์ฒญ์— ์ธ์ฆ๊ณผ ๊ด€๋ จ๋œ ์ •๋ณด๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์˜ต์…˜์ด ๋ฐ”๋กœ credentials์˜ต์…˜์ด๋‹ค.

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

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

๊ทธ๋ž˜์„œ http://localhost:8000๊ณผ ๊ฐ™์€ ๋กœ์ปฌ์˜ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋„ fetchAPI๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ์Œ๋Œ€๋กœ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•˜๊ณ , ๋˜ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

fetch("https://evan-moon.github.io/feed.xml");
Request
GET https://evan-moon.github.io/feed.xml

Origin: http://localhost:8000
Referer: http://localhost:8000/2020/05/21/about-cors/
Response
GET https://evan-moon.github.io/feed.xml 200 OK

Access-Control-Allow-Origin: *
Content-Encoding: gzip
Content-Length: 1132748
Content-Type: application/xml
Server: GitHub.com
Status: 200

๋˜ํ•œ ๊ตฌ๊ธ€ ํฌ๋กฌ ๋ธŒ๋ผ์šฐ์ €์˜ credentials๊ธฐ๋ณธ ๊ฐ’์€ ๊ฐ™์€ ์ถœ์ฒ˜ ๋‚ด์—์„œ๋งŒ ์ธ์ฆ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค๋Š” same-origin์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ https://even-moon.github.io๋กœ ๋ณด๋‚ด๋Š” ๋ฆฌ์†Œ์Šค ์š”์ฒญ์—๋Š” ๋‹น์—ฐํžˆ ๋ธŒ๋ผ์šฐ์ €์˜ ์ฟ ํ‚ค์™€ ๊ฐ™์€ ์ธ์ฆ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋ธŒ๋ผ์šฐ์ €๋Š” ๋‹จ์ˆœํžˆ Access-Control: *์ด๋ผ๋Š” ๊ฐ’๋งŒ ๋ณด๊ณ  ์•ˆ์ „ํ•œ ์š”์ฒญ์ด๋‹ค ๋ผ๋Š” ๊ฒฐ๋ก ์„ ๋‚ด๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ crednetials์˜ต์…˜์„ ๋ชจ๋“  ์š”์ฒญ์— ์ธ์ฆ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ๋ฅผ ๊ฐ€์ง„include๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๊ฐ™์€ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ์ด๋ฒˆ์—๋Š” ์ƒํ™ฉ์ด ๋‹ฌ๋ผ์ง„๋‹ค.

fetch('https://evan-moon.github.io/feed.xml', {
  credentials: 'include', // Credentials ์˜ต์…˜ ๋ณ€๊ฒฝ!
});

์ง์ ‘ ๋ธŒ๋ผ์šฐ์ € ์ฝ˜์†”์—์„œ ์‹คํ–‰ํ•ด๋ณด๋ฉด ์•Œ๊ฒ ์ง€๋งŒ, ์ด๋ฒˆ์—๋Š” credentials: include์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ผ ์ถœ์ฒ˜ ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ๋ฌด์กฐ๊ฑด ์š”์ฒญ์— ์ธ์ฆ ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜๋„๋ก ์„ค์ •ํ–ˆ์œผ๋ฏ€๋กœ, ์ด๋ฒˆ ์š”์ฒญ์—๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ ์ฟ ํ‚ค์ •๋ณด๊ฐ€ ํ•จ๊ป˜ ๋‹ด๊ฒจ ์žˆ๋Š”๊ฒƒ์„ ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ํ˜ธ์ŠคํŒ…ํ•˜๊ณ  ์žˆ๋Š” Github์„œ๋ฒ„๋Š” ์ด๋ฒˆ์—๋„ ๋™์ผํ•œ ์‘๋‹ต์„ ๋‚ด์ฃผ์—ˆ์ง€๋งŒ, ๋ธŒ๋ผ์šฐ์ €์˜ ๋ฐ˜์‘์€ ๋‹ค๋ฅด๋‹ค.

๐Ÿšจ Access to fetch at โ€™https://evan-moon.github.io/feed.xmlโ€™ from origin โ€™http://localhost:8000โ€™ has been blocked by CORS policy: The value of the โ€˜Access-Control-Allow-Originโ€™ header in the response must not be the wildcard โ€™*โ€™ when the requestโ€™s credentials mode is โ€˜includeโ€™.

๋ธŒ๋ผ์šฐ์ €๋Š” ์ธ์ฆ๋ชจ๋“œ๊ฐ€ include์ผ ๊ฒฝ์šฐ, ๋ชจ๋“  ์š”์ฒญ์„ ํ—ˆ์šฉํ•œ๋‹ค๋Š” ์˜๋ฏธ์˜ *์„ Access-Control-Allow-Originํ—ค๋”์— ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋œ๋‹ค๊ณ  ํ•œ๋‹ค.

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

  1. Access-Control-Allow-Origin์—๋Š” *์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, ๋ช…์‹œ์ ์ธ URL์ด์–ด์•ผ ํ•œ๋‹ค.
  2. ์‘๋‹ต ํ—ค๋”์—๋Š” ๋ฐ˜๋“œ์‹œ Access-Control-Allow-Credentials: true๊ฐ€ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค.

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

CORS๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•

Access-Control-Allow-Origin ์„ธํŒ…ํ•˜๊ธฐ

CORS ์ •์ฑ… ์œ„๋ฐ˜์œผ๋กœ ์ธํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ๋ฐฉ๋ฒ•์€, ๊ทธ๋ƒฅ ์ •์„๋Œ€๋กœ ์„œ๋ฒ„์—์„œ Access-Control-Allow-Originํ—ค๋”์— ์•Œ๋งž์€ ๊ฐ’์„ ์„ธํŒ…ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋•Œ *์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด ํ—ค๋”๋ฅผ ์„ธํŒ…ํ•˜๊ฒŒ ๋˜๋ฉด ๋ชจ๋“  ์ถœ์ฒ˜์—์„œ ์˜ค๋Š” ์š”์ฒญ์„ ๋ฐ›์•„๋จน๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์ด๋ฏ€๋กœ ๋‹น์žฅ์€ ํŽธํ•  ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, ๋ฐ”๊ฟ”์„œ ์ƒ๊ฐํ•˜๋ฉด ์ •์ฒด๋„ ๋ชจ๋ฅด๋Š” ์ด์ƒํ•œ ์ถœ์ฒ˜์—์„œ ์˜ค๋Š” ์š”์ฒญ๊นŒ์ง€ ๋ชจ๋‘ ๋ฐ›์•„๋จน๊ฒ ๋‹ค๋Š” ๊ฒƒ๊ณผ ๋‹ค๋ฅผ ๊ฒƒ ์—†์œผ๋ฏ€๋กœ ๋ณด์•ˆ์ ์œผ๋กœ ์‹ฌ๊ฐํ•œ ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๊ฐ€๊ธ‰์ ์œผ๋ฉด Access-Control-Allow-Origin: https://evan.github.io์™€ ๊ฐ™์ด ์ถœ์ฒ˜๋ฅผ ๋ช…์‹œํ•˜์ž!

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

Webpack Dev Server๋กœ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹ฑํ•˜๊ธฐ

CORS๋ฅผ ๊ฐ€์žฅ ๋งŽ์ด ๋งˆ์ฃผ์น˜๋Š” ํ™˜๊ฒฝ์€ ๋ฐ”๋กœ ๋กœ์ปฌ์—์„œ ํ”„๋ก ํŠธ์—”๋“œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒฝ์šฐ๋ผ๊ณ  ํ•ด๋„ ๊ณผ์–ธ์ด ์•„๋‹ˆ๋‹ค. ๋ฐฑ์—”๋“œ์—๋Š” ์ด๋ฏธ Access-Control-Allow-Originํ—ค๋”๊ฐ€ ์„ธํŒ…๋˜์–ด ์žˆ๊ฒ ์ง€๋งŒ, ์ด ์ค‘์š”ํ•œ ํ—ค๋”์— http://localhost:3000๊ฐ™์€ ๋ฒ”์šฉ์ ์ธ ์ถœ์ฒ˜๋ฅผ ๋„ฃ์–ด์ฃผ๋Š” ๊ฒฝ์šฐ๋Š” ๋“œ๋ฌผ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๋Š” ๋Œ€๋ถ€๋ถ„ ์›นํŒฉ๊ณผ webpack-dev-server๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž์‹ ์˜ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์„ ๊ตฌ์ถ•ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ํ”„๋ก์‹œ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด ์•„์ฃผ ํŽธํ•˜๊ฒŒ CORS ์ •์ฑ…์„ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

module.exports = {
  devServer: {
    proxy: {
      "/api": {
        target: "https://api.evan.com",
        changeOrigin: true,
        pathRewrite: { "^/api": "" },
      },
    },
  },
};

์ด๋ ‡๊ฒŒ ์„ค์ •์„ ํ•ด ๋†“์œผ๋ฉด ๋กœ์ปฌํ™˜๊ฒฝ์—์„œ /api๋กœ ์‹œ์ž‘ํ•˜๋Š” URL๋กœ ๋ณด๋‚ด๋Š” ์š”์ฒญ์— ๋Œ€ํ•ด ๋ธŒ๋ผ์šฐ์ €๋Š” localhost:8000/api๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๊ฒƒ์œผ๋กœ ์•Œ๊ณ  ์žˆ์ง€๋งŒ, ์‚ฌ์‹ค ๋’ค์—์„œ ์›นํŒฉ์ด https://api.evan.com์œผ๋กœ ์š”์ฒญ์„ ํ”„๋ก์‹ฑํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋งˆ์น˜ CORS ์ •์ฑ…์„ ์ง€ํ‚จ ๊ฒƒ์ฒ˜๋Ÿผ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์†์ด๋ฉด์„œ๋„ ์šฐ๋ฆฌ๋Š” ์›ํ•˜๋Š” ์„œ๋ฒ„์™€ ์ž์œ ๋กญ๊ฒŒ ํ†ต์‹ ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ํ”„๋ก์‹ฑ์„ ํ†ตํ•ด CORS ์ •์ฑ…์„ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

ํ˜น์‹œ Webpack-dev-middelware์™€ Node ์„œ๋ฒ„์˜ ์กฐํ•ฉ์œผ๋กœ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์„ ์ง์ ‘ ๊ตฌ์ถ•ํ–ˆ๋”๋ผ๋„ http-proxy-middleware ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์†์‰ฝ๊ฒŒ ํ”„๋ก์‹œ ์„ค์ •์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.(webpack-dev-server๋„ ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” http-proxy-middleware์‚ฌ์šฉํ•œ๋‹ค.)

๊ทธ๋ ‡์ง€๋งŒ ์ด ๋ฐฉ๋ฒ•์€ ์‹ค์ œ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋„ ํด๋ผ์ด์–ธํŠธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์†Œ์Šค๋ฅผ ์„œ๋น™ํ•˜๋Š” ์ถœ์ฒ˜์™€ API ์„œ๋ฒ„์˜ ์ถœ์ฒ˜๊ฐ€ ๊ฐ™์€ ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๋กœ์ปฌ ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ๋Š” ์›นํŒฉ์ด ์š”์ฒญ์„ ํ”„๋ก์‹ฑํ•ด์ฃผ๋‹ˆ ์ด์ƒ์ด ์—†์ง€๋งŒ, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋นŒ๋“œํ•˜๊ณ  ์„œ๋ฒ„์— ์˜ฌ๋ฆฌ๊ณ  ๋‚˜๋ฉด ๋”์ด์ƒ webpack-dev-server๊ฐ€ ๊ตฌ๋™ํ•˜๋Š” ํ™˜๊ฒฝ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์ƒํ•œ ๊ณณ์œผ๋กœ API์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, API์„œ๋ฒ„์˜ ์ถœ์ฒ˜๋Š” https://api.evan.com์ด๊ณ , ํด๋ผ์ด์–ธํŠธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„œ๋น™ํ•˜๋Š” ์„œ๋ฒ„์˜ ์ถœ์ฒ˜๋Š” https://www.evan.com์ด๋ผ๋ฉด, ์ด๋Ÿฐ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•œ๋‹ค.

fetch("/api/me");
๋กœ์ปฌํ™˜๊ฒฝ์—์„œ๋Š”...
GET https://api.evan.com/me 200 OK

์‹ค์ œ ์„œ๋ฒ„์—๋Š” ํ”„๋ก์‹ฑ ๋กœ์ง์ด ์—†์Œ...
GET https://www.evan.com/api/me 404 Not Found

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋‚ด์—์„œ process.env.NODE_ENV์™€ ๊ฐ™์€ ๋นŒ๋“œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ถ„๊ธฐ ๋กœ์ง์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์ง€๋งŒ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์ด๋Ÿฐ ๊ฐœ๋ฐœํ™˜๊ฒฝ ์ „์šฉ ์†Œ์Šค๊ฐ€ ํฌํ•จ๋˜๋Š” ๊ฒƒ์€ ์ข‹์ง€ ์•Š๋‹ค๊ณ  ํ•œ๋‹ค.

์š”์ฒญ์„ img ํƒœ๊ทธ์— ๋„ฃ์œผ๋ฉด?

SOP(Same-Origin Policy) ์ •์ฑ…์—๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ์˜ˆ์™ธ์กฐํ•ญ์ด ์กด์žฌํ•˜๊ณ , ๊ทธ ์ค‘ ํ•˜๋‚˜๊ฐ€ CORS ์ •์ฑ…์„ ์ง€ํ‚จ ์š”์ฒญ์ด๋ผ๊ณ  ์ด์•ผ๊ธฐํ–ˆ์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  CORS ์ •์ฑ…์„ ์ง€ํ‚จ ์š”์ฒญ์„ ์ œ์™ธํ•œ SOP์˜ ์˜ˆ์™ธ ์กฐํ•ญ์€ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์Šคํฌ๋ฆฝํŠธ, ๋ Œ๋”๋  ์ด๋ฏธ์ง€ ์Šคํƒ€์ผ ์‹œํŠธ ์ •๋„๊ฐ€ ์žˆ๋‹ค.

<img src="https://evanmoon.tistory.com/rss" />
<script src="https://evanmoon.tistory.com/rss"></script>

์ด๋Ÿฐ ์‹์œผ๋กœ ์ ‘๊ทผํ•˜๋ฉด CORS๋ฅผ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š๊ณ  ์š”์ฒญ ์ž์ฒด๋Š” ์„ฑ๊ณตํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ธŒ๋ผ์šฐ์ €์˜ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์˜ ๋„คํŠธ์›Œํฌ ํƒญ์—์„œ ์ด ์š”์ฒญ๋“ค์˜ ํ—ค๋”๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๋ฉด Sec-Fetch-Mode: no-cors๋ผ๋Š” ๊ฐ’์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

Sec-Fetch-Modeํ—ค๋”๋Š” ์š”์ฒญ์„ ๋ชจ๋“œ๋ฅผ ์„ค์ •ํ•˜๋Š” ํ•„๋“œ์ธ๋ฐ, ๋ธŒ๋ผ์šฐ์ €๋Š” ์ด ํ•„๋“œ์˜ ๊ฐ’์ด no-cors์ธ ๊ฒฝ์šฐ์—๋Š” ๋‹ค๋ฅธ ์ถœ์ฒ˜๋ผ๊ณ  ํ•ด๋„ CORS ์ •์ฑ… ์œ„๋ฐ˜ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ•˜์ง€๋งŒ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ด ํ—ค๋”์— ๊ฐ’์ด ํฌํ•จ๋œ ์š”์ฒญ์˜ ์‘๋‹ต์„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—๊ฒŒ ์•Œ๋ ค์ฃผ์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ฆ‰, ์šฐ๋ฆฌ๋Š” ์ฝ”๋“œ๋ ˆ๋ฒจ์—์„œ ์ ˆ๋Œ€ ์ด ์‘๋‹ต์— ๋‹ด๊ธด ๋‚ด์šฉ์— ์ ‘๊ทผํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค.

๋งˆ์น˜๋ฉฐ

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

webpack-dev-server์˜ ํ”„๋ก์‹ฑ ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž์ฒด์ ์œผ๋กœ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์ง€๋งŒ, ์ด ๋ฐฉ๋ฒ•์€ ๋กœ์ปฌ ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ๋งŒ ํ†ตํ•˜๋Š” ๋ฐฉ๋ฒ•์ธ๋ฐ๋‹ค๊ฐ€, ๊ทผ๋ณต์ ์ธ ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐ๊ตญ ์šด์˜ ํ™˜๊ฒฝ์—์„œ CORS ์ •์ฑ… ์œ„๋ฐ˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž์˜ ๋„์›€์ด ํ•„์š”ํ•  ์ˆ˜ ๋ฐ–์— ์—†๋‹ค. CORS ์ •์ฑ… ์œ„๋ฐ˜์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ• ์ž์ฒด๊ฐ€ ๊ทธ๋ ‡๊ฒŒ ์–ด๋ ต๊ณ  ๋ณต์žกํ•œ ํŽธ์€ ์•„๋‹ˆ๋ผ์„œ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๋‚˜ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž ์ค‘ ํ•œ๋ช…์ด๋ผ๋„ ์ด๋Ÿฌํ•œ ์ •์ฑ…์— ๋Œ€ํ•ด์„œ ์ž˜ ์•Œ๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ๋ผ๋ฉด ์ƒ๊ฐ๋ณด๋‹ค ๋น ๋ฅด๊ณ  ์ˆ˜์›”ํ•˜๊ฒŒ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.