Unit10 - [Web Server] ๊ธฐ์ดˆ

๊ฐ•์„ฑ์ผยท2023๋…„ 6์›” 1์ผ
0
post-thumbnail

โœ… TIL


์˜ค๋Š˜์€ cors๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ์•„๋ณด๊ณ  node.js๋ฅผ ์ด์šฉํ•˜์—ฌ ์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ–ˆ๋‹ค.

๋˜ํ•œ ๊ณผ์ œ mini-node server๋ฅผ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณผ ์—์ •์ด๋‹ค.

๊ฐ™์€ JavaScript๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ node.js ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ์—๋Š”,
CommonJS๋‚˜ ๋ชจ๋“ˆ ๋“ฑ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ฐพ์•„๋ณผ ์ˆ˜ ์—†๋Š” ๋‹ค์†Œ ์ƒ์†Œํ•œ ๊ฐœ๋…์ด ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.

node.js์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ด ๊ฐœ๋…๋“ค์€ ๋ฐฑ์—”๋“œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ,
ํ”„๋ก ํŠธ์—”๋“œ์—์„œ๋„ ์ ๊ทน ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, API ์„œ๋ฒ„ ๋˜ํ•œ ๊ตฌํ˜„ํ•  ์ค„ ์•Œ์•„์•ผ ํ•œ๋‹ค.

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



CORS, SOP


์ด ์‚ฌ์ง„์€ ์›น ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค ๋ณด๋ฉด, ์ด ์—๋Ÿฌ๋ฅผ ์ ์–ด๋„ ํ•œ ๋ฒˆ์ฏค์€ ๊ฒช๊ฒŒ ๋˜๊ณ , ๊ณจ๋จธ๋ฆฌ๋ฅผ ์•“๊ฒŒ ๋˜๋Š” CORS ์—๋Ÿฌ์ด๋‹ค.

CORS๊ฐ€ ๋Œ€์ฒด ๋ญ๊ธธ๋ž˜.. ์•Œ์•„๋ณด๊ธฐ ์ „์—, CORS๊ฐ€ ํ•„์š”ํ•˜๊ฒŒ ๋œ ๋ฐฐ๊ฒฝ์ธ SOP์— ๋Œ€ํ•ด์„œ ๋จผ์ € ์•Œ์•„๋ณด๋„๋ก ํ•˜์ž.


SOP

SOP์€ Same-Origin Policy์˜ ์ค„์ž„๋ง๋กœ, ๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…์„ ๋œปํ•œ๋‹ค.

ํ•œ ๋งˆ๋””๋กœ โ€˜๊ฐ™์€ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋งŒ ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹คโ€™๋ผ๋Š” ์ •์ฑ…์ด๋‹ค. ์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” โ€˜์ถœ์ฒ˜(Origin)โ€™๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

์ถœ์ฒ˜๋Š” ํ”„๋กœํ† ์ฝœ, ํ˜ธ์ŠคํŠธ, ํฌํŠธ์˜ ์กฐํ•ฉ์œผ๋กœ ๋˜์–ด์žˆ๋‹ค. ์ด ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋‹ค๋ฅด๋ฉด ๋™์ผํ•œ ์ถœ์ฒ˜๋กœ ๋ณด์ง€ ์•Š๋Š”๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด SOP์€ ์™œ ์ƒ๊ฒจ๋‚ฌ์„๊นŒ?

๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…์€ ์ž ์žฌ์ ์œผ๋กœ ํ•ด๋กœ์šธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์„œ๋ฅผ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ ๊ณต๊ฒฉ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ๋กœ๋ฅผ ์ค„์—ฌ์ค€๋‹ค.

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

ํ•ด์ปค๋Š” ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ์ด์šฉํ•ด์„œ ๋„ค์ด๋ฒ„์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

SOP์ด ์žˆ์—ˆ๋‹ค๋ฉด?

์• ์ดˆ์— SOP๋Š” ๋‹ค๋ฅธ ์‚ฌ์ดํŠธ์™€์˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ ๋ฅผ ์ œํ•œํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋กœ๊ทธ์ธ ์ •๋ณด๊ฐ€ ํƒ€ ์‚ฌ์ดํŠธ์˜ ์ฝ”๋“œ์— ์˜ํ•ด์„œ ์ƒˆ์–ด๋‚˜๊ฐ€๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ณด์•ˆ์ƒ ์ด์  ๋•Œ๋ฌธ์— SOP์€ ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์ •์ฑ…์ด๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ์ผ์€ ๋„ˆ๋ฌด๋‚˜๋„ ๋งŽ๋‹ค.
๋‹น์žฅ ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ ๊ฐœ๋ฐœํ•  ๋•Œ์—๋„ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๋ฅผ ๋”ฐ๋กœ ๊ฐœ๋ฐœํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๋‘˜์€ ์ถœ์ฒ˜๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค.

๊ฐœ๋ฐœ ์ค‘์ธ ์›น ์‚ฌ์ดํŠธ์—์„œ ๋„ค์ด๋ฒ„ ์ง€๋„ api๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด? github ์ •๋ณด๋ฅผ ๋ฐ›์•„์™€์„œ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?
๋ชจ๋‘ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ผ์ด๋‹ค.

ํ•˜์ง€๋งŒ, ๋งํ–ˆ๋“ฏ ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ €๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ SOP ์ •์ฑ…์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.
์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ์„๊นŒ?


CORS

์œ„ ๋ฌธ์ œ ์ƒํ™ฉ์—์„œ ํ•„์š”ํ•œ ๊ฒƒ์ด ๋ฐ”๋กœ CORS์ด๋‹ค.
CORS๋Š” Cross-Origin Resource Sharing์˜ ์ค„์ž„๋ง๋กœ ๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ ๋ฅผ ๋œปํ•œ๋‹ค.

MDN์—์„œ๋Š” CORS๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜ํ•˜๊ณ  ์žˆ๋‹ค.

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

์ฆ‰, ๋ธŒ๋ผ์šฐ์ €๋Š” SOP์— ์˜ํ•ด ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ ๋ฅผ ๋ง‰์ง€๋งŒ, CORS๋กœ ์ ‘๊ทผ ๊ถŒํ•œ์„ ์–ป์„ ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์ง€๊ธˆ๊นŒ์ง€ ๊ณต๋ถ€ํ•œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ด ์—๋Ÿฌ๋ฅผ ์‰ฝ๊ณ  ์นœ์ ˆํ•˜๊ฒŒ ํ’€์–ด์„œ ์“ฐ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์„ ๊ฒƒ์ด๋‹ค.

๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๋ ค๊ณ  ํ–ˆ์ง€๋งŒ SOP ๋•Œ๋ฌธ์— ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.
CORS ์„ค์ •์„ ํ†ตํ•ด ์„œ๋ฒ„์˜ ์‘๋‹ต ํ—ค๋”์— โ€˜Access-Control-Allow-Originโ€™์„ ์ž‘์„ฑํ•˜๋ฉด ์ ‘๊ทผ ๊ถŒํ•œ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

์ฆ‰, ์ด ์—๋Ÿฌ๋Š” CORS ๋•Œ๋ฌธ์ด ์•„๋‹ˆ๋ผ, SOP ๋•Œ๋ฌธ์ด๋‹ค.
CORS๋Š” ์˜คํžˆ๋ ค ์ด ์—๋Ÿฌ๋ฅผ ํ•ด๊ฒฐํ•ด ์ค„ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์•ˆ์ด์—ˆ๋˜ ๊ฒƒ์ด๋‹ค!



CORS ๋™์ž‘ ๋ฐฉ์‹


CORS์˜ ๋™์ž‘ ๋ฐฉ์‹์—๋Š” ํฌ๊ฒŒ ์„ธ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

1. ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ (Preflight Request)

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

์œ„ ์ด๋ฏธ์ง€์˜ ํ๋ฆ„๊ณผ ๊ฐ™์ด, ๋ธŒ๋ผ์šฐ์ €๋Š” ์„œ๋ฒ„์— ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „์— ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ ,
์‘๋‹ต ํ—ค๋”์˜ Access-Control-Allow-Origin์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ์ถœ์ฒ˜๊ฐ€ ๋Œ์•„์˜ค๋ฉด ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋œ๋‹ค.

๋งŒ์•ฝ์— ์š”์ฒญ์„ ๋ณด๋‚ธ ์ถœ์ฒ˜๊ฐ€ ์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†๋‹ค๋ฉด ๋ธŒ๋ผ์šฐ์ €์—์„œ CORS ์—๋Ÿฌ๋ฅผ ๋„์šฐ๊ฒŒ ๋˜๊ณ , ์‹ค์ œ ์š”์ฒญ์€ ์ „๋‹ฌ๋˜์ง€ ์•Š๋Š”๋‹ค.

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


like.. internet Explorer

CORS ์ด์ „์— ๋งŒ๋“ค์–ด์ง„ ์„œ๋ฒ„๋“ค์€ SOP ์š”์ฒญ๋งŒ ๋“ค์–ด์˜ค๋Š” ์ƒํ™ฉ์„ ๊ณ ๋ คํ•˜๊ณ  ๋งŒ๋“ค์–ด์กŒ๋‹ค.
๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ ์ถœ์ฒ˜์—์„œ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ ๋Œ€๋น„๊ฐ€ ๋˜์–ด์žˆ์ง€ ์•Š์•˜๋‹ค.


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

๋‹จ์ˆœ ์š”์ฒญ์€ ํŠน์ • ์กฐ๊ฑด์ด ๋งŒ์กฑ๋˜๋ฉด, ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์„ ์ƒ๋žตํ•˜๊ณ  ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

๋Œ€ํ‘œ์ ์œผ๋กœ ์•„๋ž˜ 3๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ๋งŒ์กฑํ•  ๋•Œ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์š”์ฒญ์˜ ๋ฉ”์†Œ๋“œ๋Š” 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์ค‘ ํ•˜๋‚˜์—ฌ์•ผํ•œ๋‹ค. ์•„๋‹ ๊ฒฝ์šฐ ์˜ˆ๋น„ ์š”์ฒญ์œผ๋กœ ๋™์ž‘๋œ๋‹ค.

์ด์ฒ˜๋Ÿผ ๋‹ค์†Œ ๊นŒ๋‹ค๋กœ์šด ์กฐ๊ฑด๋“ค์ด ๋งŽ๊ธฐ ๋•Œ๋ฌธ์—, ์œ„ ์กฐ๊ฑด์„ ๋ชจ๋‘ ๋งŒ์กฑ๋˜์–ด ๋‹จ์ˆœ ์š”์ฒญ์ด ์ผ์–ด๋‚˜๋Š” ์ƒํ™ฉ์€ ๋“œ๋ฌผ๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.
๋Œ€๋ถ€๋ถ„ HTTP API ์š”์ฒญ์€ text / xml ์ด๋‚˜ application / json ์œผ๋กœ ํ†ต์‹ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— 3๋ฒˆ์งธ Content-Type์ด ์œ„๋ฐ˜๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋”ฐ๋ผ์„œ '๋Œ€๋ถ€๋ถ„์˜ API ์š”์ฒญ์€ ์˜ˆ๋น„ ์š”์ฒญ(preflight)์ด๋‹ค' ๋ผ๊ณ  ์ดํ•ดํ•˜๋ฉด ๋œ๋‹ค.


3. ์ธ์ฆ์ •๋ณด๋ฅผ ํฌํ•จํ•œ ์š”์ฒญ (Credentialed Request)


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

  • ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ๋Š” ์š”์ฒญ ํ—ค๋”์— withCredentials : true๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค.
  • ์„œ๋ฒ„ ์ธก์—์„œ๋Š” ์‘๋‹ต ํ—ค๋”์— Access-Control-Allow-Credentials : true๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค.
  • ์„œ๋ฒ„ ์ธก์—์„œ Access-Control-Allow-Origin์„ ์„ค์ •ํ•  ๋•Œ, ๋ชจ๋“  ์ถœ์ฒ˜๋ฅผ ํ—ˆ์šฉํ•œ๋‹ค๋Š” ๋œป์˜ ์™€์ผ๋“œ์นด๋“œ(*)๋กœ ์„ค์ •ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ค๋ฃจ๋Š” ๋งŒํผ ์ถœ์ฒ˜๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์„ค์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.


CORS ์„ค์ • ๋ฐฉ๋ฒ•


1. Node.js ์„œ๋ฒ„

const http = require('http');

const server = http.createServer((request, response) => {
// ๋ชจ๋“  ๋„๋ฉ”์ธ
  response.setHeader("Access-Control-Allow-Origin", "*");

// ํŠน์ • ๋„๋ฉ”์ธ
  response.setHeader("Access-Control-Allow-Origin", "https://codestates.com");

// ์ธ์ฆ ์ •๋ณด๋ฅผ ํฌํ•จํ•œ ์š”์ฒญ์„ ๋ฐ›์„ ๊ฒฝ์šฐ
  response.setHeader("Access-Control-Allow-Credentials", "true");
})


Node.js๋กœ ๊ฐ„๋‹จํ•œ HTTP ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค ๊ฒฝ์šฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‘๋‹ต ํ—ค๋”๋ฅผ ์„ค์ •ํ•ด ์ค„ ์ˆ˜ ์žˆ๋‹ค.


2. Express ์„œ๋ฒ„

const cors = require("cors");
const app = express();

//๋ชจ๋“  ๋„๋ฉ”์ธ
app.use(cors());

//ํŠน์ • ๋„๋ฉ”์ธ
const options = {
  origin: "https://codestates.com", // ์ ‘๊ทผ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋Š” ๋„๋ฉ”์ธ
  credentials: true, // ์‘๋‹ต ํ—ค๋”์— Access-Control-Allow-Credentials ์ถ”๊ฐ€
  optionsSuccessStatus: 200, // ์‘๋‹ต ์ƒํƒœ 200์œผ๋กœ ์„ค์ •
};

app.use(cors(options));

//ํŠน์ • ์š”์ฒญ
app.get("/example/:id", cors(), function (req, res, next) {
  res.json({ msg: "example" });
});


Express ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒฝ์šฐ์—๋Š”,
cors ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋”์šฑ ๊ฐ„๋‹จํ•˜๊ฒŒ CORS ์„ค์ •์„ ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.



๐Ÿ’ฌ Sprint Review


๋ธŒ๋ผ์šฐ์ €์—๋Š” ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด fetch ๊ฐ™์€ HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋„๊ตฌ๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚ด์žฅ๋˜์–ด ์žˆ๋‹ค.
์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €)์˜ HTTP ์š”์ฒญ์— ๋งž๊ฒŒ ์‘๋‹ต์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.

Node.js๋Š” HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๊ฑฐ๋‚˜, ์‘๋‹ต์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋“ค์„ ์ œ๊ณตํ•œ๋‹ค
HTTP ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‘๋‹ต์„ ๋ณด๋‚ด ์ฃผ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์›น ์„œ๋ฒ„(Web Server)๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

์ด๋ฒˆ ๊ณผ์ œ์—์„œ๋Š” Node.js์˜ http ๋ชจ๋“ˆ์„ ์ด์šฉํ•ด ์›น ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ ๋‹ค. - ์ฐธ๊ณ ์ž๋ฃŒ โœจ
Node.js์—์„œ ํŒŒ์ผ์„ ์ฝ๊ฑฐ๋‚˜ ์“ฐ๊ธฐ ์œ„ํ•ด fs ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋“ฏ์ด, HTTP ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด HTTP ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•œ๋‹ค.


์„œ๋ฒ„ ์‹คํ–‰


ํด๋ผ์ด์–ธํŠธ ์‹คํ–‰

  • client/index.html๋ฅผ ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • ํŠน์ • ํฌํŠธ๋กœ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, serve๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    • npx serve -l ํฌํŠธ๋ฒˆํ˜ธ client/


๐Ÿ”ฅ Bare minimum requirements


์ด๋ฒˆ ๊ณผ์ œ์—์„œ ๊ตฌํ˜„ํ•˜๋Š” ์›น ์„œ๋ฒ„์˜ ๊ธฐ๋Šฅ์€ ๋งค์šฐ ๋‹จ์ˆœํ•˜๋‹ค.

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



โš™๏ธ Code

// ๐Ÿ’ฌ ์ฃผ์–ด์ง„ ์ฝ”๋“œ

const http = require("http");
const PORT = 4999;
const ip = "localhost";

const server = http.createServer((request, response) => {
  console.log(
    `http request method is ${request.method}, url is ${request.url}`
  );
  response.writeHead(200, defaultCorsHeader);
  response.end("hello mini-server sprints");
});

server.listen(PORT, ip, () => {
  console.log(`http server listen on ${ip}:${PORT}`);
});

const defaultCorsHeader = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
  "Access-Control-Allow-Headers": "Content-Type, Accept",
  "Access-Control-Max-Age": 10,
};

// โœ… ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ

const http = require("http");
const PORT = 4999;
const ip = "localhost";

const server = http.createServer((request, response) => {
  // GET / ์š”์ฒญ ์ฒ˜๋ฆฌ
  if (request.method === "GET" && request.url === "/") {
    response.writeHead(200, defaultCorsHeader); // 200 OK ์‘๋‹ต ์ฝ”๋“œ์™€ CORS ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜
    response.end("hello mini-server sprints"); // "hello mini-server sprints"๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋ƒ„
  }

  // OPTIONS ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ
  else if (request.method === "OPTIONS") {
    response.writeHead(204, defaultCorsHeader); // 204 No Content ์‘๋‹ต ์ฝ”๋“œ์™€ CORS ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜
    response.end();
    return;
  }

  // POST /lower ์š”์ฒญ ์ฒ˜๋ฆฌ
  else if (request.method === "POST" && request.url === "/lower") {
    let requestBody = "";

    request.on("data", (text) => {
      requestBody += text.toString();
    });

    request.on("end", () => {
      const convertedText = requestBody.toLowerCase(); // ๋ฐ›์€ ํ…์ŠคํŠธ๋ฅผ ์†Œ๋ฌธ์ž๋กœ ๋ณ€ํ™˜
      response.writeHead(200, defaultCorsHeader); // 200 OK ์‘๋‹ต ์ฝ”๋“œ์™€ CORS ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜
      response.end(convertedText); // ๋ณ€ํ™˜๋œ ํ…์ŠคํŠธ๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋ƒ„
    });
  }
  // POST /upper ์š”์ฒญ ์ฒ˜๋ฆฌ
  else if (request.method === "POST" && request.url === "/upper") {
    let requestBody = "";

    request.on("data", (text) => {
      requestBody += text.toString();
    });

    request.on("end", () => {
      const convertedText = requestBody.toUpperCase(); // ๋ฐ›์€ ํ…์ŠคํŠธ๋ฅผ ๋Œ€๋ฌธ์ž๋กœ ๋ณ€ํ™˜
      response.writeHead(200, defaultCorsHeader); // 200 OK ์‘๋‹ต ์ฝ”๋“œ์™€ CORS ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜
      response.end(convertedText); // ๋ณ€ํ™˜๋œ ํ…์ŠคํŠธ๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋ƒ„
    });
  }
  // ๊ทธ ์™ธ์˜ ์š”์ฒญ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ (404 Not Found)
  else {
    response.statusCode = 404; // 404 Not Found ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ์„ค์ •
    response.end(); // ์‘๋‹ต ์ข…๋ฃŒ
  }
  // ์กฐ๊ธˆ ๋” ๋ณดํŽธ์ ์ธ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•
  // request.on("error", (err) => {
  //   console.error(err);
  //   response.statusCode = 400;
  //   response.end();
  // });
  // response.on("error", (err) => {
  //   console.error(err);
  // });

  console.log(
    `http request method is ${request.method}, url is ${request.url}`
  );
});

server.listen(PORT, ip, () => {
  console.log(`http server listen on ${ip}:${PORT}`);
});

// ์‘๋‹ต ํ—ค๋”
const defaultCorsHeader = {
  "Access-Control-Allow-Origin": "*", // ๋ชจ๋“  ์ถœ์ฒ˜์—์„œ์˜ ์š”์ฒญ์„ ํ—ˆ์šฉ
  "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", // ์›ํ•˜๋Š” HTTP ๋ฉ”์„œ๋“œ๋ฅผ ๋ช…์‹œ
  "Access-Control-Allow-Headers": "Content-Type, Accept", // ํ—ˆ์šฉํ•˜๋Š” ์š”์ฒญ ํ—ค๋”๋ฅผ ๋ช…์‹œ
  "Access-Control-Max-Age": 10, // Preflight ์š”์ฒญ์˜ ์บ์‹ฑ ์‹œ๊ฐ„์„ ์„ค์ •
};


๊ตฌํ˜„ํ•œ ์„œ๋ฒ„


๊ตฌํ˜„ํ•œ ํด๋ผ์ด์–ธํŠธ


์ž‘๋™ ์˜์ƒ

profile
์•„์ด๋””์–ด๊ฐ€ ๋„˜์น˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๊ฟˆ๊ฟ‰๋‹ˆ๋‹ค ๐Ÿ”ฅ

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