CORS๋ '๊ต์ฐจ ์ถ์ฒ ๋ฆฌ์์ค ๊ณต์ '๋ผ๋ ์ด๋ฆ์ผ๋ก, HTTP ํค๋๋ฅผ ์ฌ์ฉํ์ฌ ํ ์ถ์ฒ(origin)์์ ์คํ์ค์ธ ์น ์ดํ๋ฆฌ์ผ์ด์ ์ด ๋ค๋ฅธ ์ถ์ฒ(cross-origin)์ ์ ํํ ์์์ ์ ๊ทผํ ์ ์๋ ๊ถํ์ ๋ถ์ฌํ๋๋ก ๋ธ๋ผ์ฐ์ ์ ์๋ ค์ฃผ๋ ์ ์ฑ
Origin
SOP(Same Origin Policy)
CORS(Cross Origin Resource Sharing)
CORS ์๋ฌ ํด๊ฒฐ๋ฐฉ์
์ถ์ฒ(Origin)๋ URL ๊ตฌ์กฐ์์ ์ดํด๋ณธ Protocal, Host, Port๋ฅผ ํฉ์น ๊ฒ์ ๋งํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ์ ์ฝ์ ์ฐฝ์ location.origin๋ฅผ ์คํํ๋ฉด ์ถ์ฒ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
ํ์ฌ ์นํ์ด์ง์ ์ฃผ์๊ฐ https://csstudy.github.io/tech/ ์ผ ๋ ๊ฐ์ ์ถ์ฒ์ธ์ง ๋ค๋ฅธ ์ถ์ฒ์ธ์ง ํ์ธํ๊ธฐ
https://csstudy.github.io/about?q=work : ๊ฐ์ ์ถ์ฒ
http://csstudy.github.io : ๋ค๋ฅธ ์ถ์ฒ
https://csstudy.github.io:81/about/ : ๋ค๋ฅธ ์ถ์ฒ
SOP ์ ์ฑ ์ '๋์ผ ์ถ์ฒ ์ ์ฑ '์ด๋ผ๋ ์ด๋ฆ์ผ๋ก, ๊ฐ์ ์ถ์ฒ์ ๋ํ HTTP ์์ฒญ๋ง์ ํ๋ฝํ๋ค. ์น ์ดํ๋ฆฌ์ผ์ด์ ์์์ ์ค์ํ ๋ณด์๋ชจ๋ธ์ด๋ค.
Postman์ผ๋ก API๋ฅผ ํ ์คํธํ๊ฑฐ๋, ๋ค๋ฅธ ์๋ฒ์์ API๋ฅผ ํธ์ถํ ๋๋ ๋ฉ์ฉกํ ์ ๋์ํ๋ค๊ฐ ๋ธ๋ผ์ฐ์ ์์ API๋ฅผ ํธ์ถํ ๋๋ง CORS policy ์ค๋ฅ๊ฐ ๋ฐ์ํด์ ๋นํน์ค๋ฌ์ธ ๋๊ฐ ์์ผ์ จ์ ์๋ ์๋ค. ๊ทธ ์ด์ ๋ ๋ธ๋ผ์ฐ์ ๊ฐ ๋์ผ ์ถ์ฒ ์ ์ฑ (Same-Origin Policy, SOP)๋ฅผ ์ง์ผ์ ๋ค๋ฅธ ์ถ์ฒ์ ๋ฆฌ์์ค ์ ๊ทผ์ ๊ธ์งํ๊ธฐ ๋๋ฌธ์ด๋ค. ํ์ง๋ง ์ค์ ๋ก ์นํ์ด์ง๋ ์๋นํ ์์ฃผ ๋ค๋ฅธ ์ถ์ฒ์ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค. ์๋ฅผ ๋ค์ด csstudy.github.io๋ผ๋ ๋๋ฉ์ธ ์ฃผ์๋ฅผ ์ฌ์ฉํ๋ ์นํ์ด์ง์์ csstudy-api.github.io๋ผ๋ API ์๋ฒ๋ก ๋ฐ์ดํฐ๋ฅผ ์์ฒญํด์ ํ๋ฉด์ ๊ทธ๋ฆฐ๋ค๋ฉด ์ด ์นํ์ด์ง๋ ๋์ผ ์ถ์ฒ ์ ์ฑ ์ ์๋ฐํ ๊ฒ์ด ๋๋ค.
๋์ผ ์ถ์ฒ ์ ์ฑ ์ ์งํค๋ฉด ์ธ๋ถ ๋ฆฌ์์ค๋ฅผ ๊ฐ์ ธ์ค์ง ๋ชปํด ๋ถํธํ์ง๋ง, ๋์ผ ์ถ์ฒ ์ ์ฑ ์ XSS๋ XSRF ๋ฑ์ ๋ณด์ ์ทจ์ฝ์ ์ ๋ ธ๋ฆฐ ๊ณต๊ฒฉ์ ๋ฐฉ์ดํ ์ ์๋ค. ํ์ง๋ง ํ์ค์ ์ผ๋ก๋ ์ธ๋ถ ๋ฆฌ์์ค๋ฅผ ์ฐธ๊ณ ํ๋ ๊ฒ์ ํ์ํ๊ธฐ ๋๋ฌธ์ ์ธ๋ถ ๋ฆฌ์์ค๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ ๋ฐฉ๋ฒ์ด ์กด์ฌํด์ผ ํ๋ค. ์ธ๋ถ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ SOP์ ์์ธ ์กฐํญ์ด CORS๋ค.
์น ์๋ฒ์๊ฒ ๋ณด์ cross-domain ๋ฐ์ดํฐ ์ ์ก์ ํ์ฑํํ๋ cross-domain ์ ๊ทผ ์ ์ด๊ถ์ ๋ถ์ฌํ๋ค.
1) Simple Request
Simple Request๋ ์๋ฒ์๊ฒ ๋ฐ๋ก ์์ฒญ์ ๋ณด๋ด๋ ๋ฐฉ๋ฒ์ด๋ค. ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ์๊ฒ ๋ฐ๋ก ์์ฒญ์ ํ๋ฉด ์๋ฒ๋ Access-Control-Allow-Origin ํค๋๋ฅผ ํฌํจํ ์๋ต์ ๋ธ๋ผ์ฐ์ ์ ๋ณด๋ธ๋ค. ๋ธ๋ผ์ฐ์ ๋ Access-Control-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 ์ค ํ๋๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ง์ด ์ฌ์ฉํ๊ณ ์๋ application/json์ ํฌํจ๋์ง ์๋๋ค.
2) Preflight Request
์๋ฒ์ ์๋น ์์ฒญ์ ๋ณด๋ด์ ์์ ํ์ง ํ๋จํ ํ ๋ณธ ์์ฒญ์ ๋ณด๋ด๋ ๋ฐฉ๋ฒ์ด๋ค. ๋ณธ ์์ฒญ์ ์์, OPTIONS ๋ฉ์๋๋ก ์์ฒญ์ด ๋ณด๋ด์ง๊ณ , ํด๋น ๋ฉ์๋๋ฅผ ํตํด ์ค์ ์์ฒญ์ ์ ์กํ ์ง ํ๋จํ๋ค. ์๋ฒ๋ OPTIONS์ ์์ฒญ์ ๋ํ ์๋ต์ผ๋ก Access-Control-Allow-Origin ํค๋๋ฅผ ํฌํจํ ์๋ต์ ๋ธ๋ผ์ฐ์ ์ ๋ณด๋ด๊ณ , ๋ธ๋ผ์ฐ์ ๋ ์ Simple Request์ ๋์ผํ๊ฒ Access-Control-Allow-Origin ํค๋๋ฅผ ํ์ธํด์ CORS ๋์์ ์ํํ ์ง ํ๋จํ๋ค.
- POST์์ฒญ์ด์ง๋ง Content-Type์ด application/x-www-form-urlencoded, multipart/form-data, text/plain์ด ์๋ ๊ฒฝ์ฐ๋ ์ฌ๊ธฐ์ ํด๋นํ๋ค.
3) Credentialed Request
์ธ์ฆ๋ ์์ฒญ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค. ์ด ์๋๋ฆฌ์ค๋ CORS์ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ์์ด๋ผ๊ธฐ ๋ณด๋ค๋ ๋ค๋ฅธ ์ถ์ฒ ๊ฐ ํต์ ์์ ์ข ๋ ๋ณด์์ ๊ฐํํ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ๊ฐ ์ ๊ณตํ๋ ๋น๋๊ธฐ ๋ฆฌ์์ค ์์ฒญ API์ธ XMLHttpRequest ๊ฐ์ฒด๋ fetch API๋ ๋ณ๋์ ์ต์ ์์ด ๋ธ๋ผ์ฐ์ ์ ์ฟ ํค ์ ๋ณด๋ ์ธ์ฆ๊ณผ ๊ด๋ จ๋ ํค๋๋ฅผ ํจ๋ถ๋ก ์์ฒญ์ ๋ด์ง ์๋๋ค. ์ด๋ ์์ฒญ์ ์ธ์ฆ๊ณผ ๊ด๋ จ๋ ์ ๋ณด๋ฅผ ๋ด์ ์ ์๊ฒ ํด์ฃผ๋ ์ต์ ์ด ๋ฐ๋ก credentials ์ต์ ์ด๋ค.
์ด ์ต์ ์๋ ์ด 3๊ฐ์ง์ ๊ฐ์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ๊ฐ ๊ฐ๋ค์ด ๊ฐ์ง๋ ์๋ฏธ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- same-origin(๊ธฐ๋ณธ๊ฐ): ๊ฐ์ ์ถ์ฒ ๊ฐ ์์ฒญ์๋ง ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ด์ ์ ์๋ค.
- include: ๋ชจ๋ ์์ฒญ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ด์ ์ ์๋ค.
- omit: ๋ชจ๋ ์์ฒญ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ด์ง ์๋๋ค.
๋ง์ฝ same-origin์ด๋ include์ ๊ฐ์ ์ต์ ์ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค ์์ฒญ์ ์ธ์ฆ ์ ๋ณด๊ฐ ํฌํจ๋๋ค๋ฉด, ์ด์ ๋ธ๋ผ์ฐ์ ๋ ๋ค๋ฅธ ์ถ์ฒ์ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ ๋ ๋จ์ํ Access-Control-Allow-Origin๋ง ํ์ธํ๋ ๊ฒ์ด ์๋๋ผ ์ข ๋ ๋นก๋นกํ ๊ฒ์ฌ ์กฐ๊ฑด์ ์ถ๊ฐํ๊ฒ ๋๋ค.
CORS ์ ์ฑ ์๋ฐ์ผ๋ก ์ธํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฐ์ฅ ๋ํ์ ์ธ ๋ฐฉ๋ฒ์, ๊ทธ๋ฅ ์ ์๋๋ก ์๋ฒ์์ Access-Control-Allow-Origin ํค๋์ ์๋ง์ ๊ฐ์ ์ธํ ํด์ฃผ๋ ๊ฒ์ด๋ค.
์ด๋ ์์ผ๋์นด๋์ธ *์ ์ฌ์ฉํ์ฌ ์ด ํค๋๋ฅผ ์ธํ ํ๊ฒ ๋๋ฉด ๋ชจ๋ ์ถ์ฒ์์ ์ค๋ ์์ฒญ์ ๋ฐ์๋จน๊ฒ ๋ค๋ ์๋ฏธ์ด๋ฏ๋ก ๋น์ฅ์ ํธํ ์ ์๊ฒ ์ง๋ง, ๋ฐ๊ฟ์ ์๊ฐํ๋ฉด ์ ์ฒด๋ ๋ชจ๋ฅด๋ ์ด์ํ ์ถ์ฒ์์ ์ค๋ ์์ฒญ๊น์ง ๋ชจ๋ ๋ฐ์๋จน๊ฒ ๋ค๋ ์คํ ๋ง์ธ๋์ ๋ค๋ฅผ ๊ฒ ์์ผ๋ฏ๋ก ๋ณด์์ ์ผ๋ก ์ฌ๊ฐํ ์ด์๊ฐ ๋ฐ์ํ ์๋ ์๋ค.
๊ทธ๋ฌ๋ ๊ฐ๊ธ์ ์ด๋ฉด ๊ท์ฐฎ๋๋ผ๋ Access-Control-Allow-Origin: https://csstudy.github.io์ ๊ฐ์ด ์ถ์ฒ๋ฅผ ๋ช ์ํด์ฃผ๋๋ก ํ์.
์ด ํค๋๋ Nginx๋ Apache์ ๊ฐ์ ์๋ฒ ์์ง์ ์ค์ ์์ ์ถ๊ฐํ ์๋ ์์ง๋ง, ์๋ฌด๋๋ ๋ณต์กํ ์ธํ ์ ํ๊ธฐ๋ ๋ถํธํ๊ธฐ ๋๋ฌธ์ ์์ค ์ฝ๋ ๋ด์์ ์๋ต ๋ฏธ๋ค์จ์ด ๋ฑ์ ์ฌ์ฉํ์ฌ ์ธํ ํ๋ ๊ฒ์ ์ถ์ฒํ๋ค. Spring, Express, Django์ ๊ฐ์ด ์ด๋ฆ์๋ ๋ฐฑ์๋ ํ๋ ์์ํฌ์ ๊ฒฝ์ฐ์๋ ๋ชจ๋ CORS ๊ด๋ จ ์ค์ ์ ์ํ ์ธํ ์ด๋ ๋ฏธ๋ค์จ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๊ณตํ๊ณ ์์ผ๋ ์ธํ ์์ฒด๊ฐ ์ด๋ ต์ง๋ ์์ ๊ฒ์ด๋ค.
์ฌ์ค CORS๋ฅผ ๊ฐ์ฅ ๋ง์ด ๋ง์ฃผ์น๋ ํ๊ฒฝ์ ๋ฐ๋ก ๋ก์ปฌ์์ ํ๋ก ํธ์๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ๋ ๊ฒฝ์ฐ๋ผ๊ณ ํด๋ ๊ณผ์ธ์ด ์๋๋ค. ๋ฐฑ์๋์๋ ์ด๋ฏธ Access-Control-Allow-Origin ํค๋๊ฐ ์ธํ ๋์ด์๊ฒ ์ง๋ง, ์ด ์ค์ํ ํค๋์๋ค๊ฐ http://localhost:3000 ๊ฐ์ ๋ฒ์ฉ์ ์ธ ์ถ์ฒ๋ฅผ ๋ฃ์ด์ฃผ๋ ๊ฒฝ์ฐ๋ ๋๋ฌผ๊ธฐ ๋๋ฌธ์ด๋ค.
ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๋ ๋๋ถ๋ถ ์นํฉ๊ณผ webpack-dev-server๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์ ๋จธ์ ์ ๊ฐ๋ฐ ํ๊ฒฝ์ ๊ตฌ์ถํ๊ฒ ๋๋๋ฐ, ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ๊ณตํ๋ ํ๋ก์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ์์ฃผ ํธํ๊ฒ CORS ์ ์ฑ ์ ์ฐํํ ์ ์๋ค.
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'https://api.csstudy.com',
changeOrigin: true,
pathRewrite: { '^/api': '' },
},
}
}
}
์ด๋ ๊ฒ ์ค์ ์ ํด๋์ผ๋ฉด ๋ก์ปฌ ํ๊ฒฝ์์ /api๋ก ์์ํ๋ URL๋ก ๋ณด๋ด๋ ์์ฒญ์ ๋ํด ๋ธ๋ผ์ฐ์ ๋ localhost:8000/api๋ก ์์ฒญ์ ๋ณด๋ธ ๊ฒ์ผ๋ก ์๊ณ ์์ง๋ง, ์ฌ์ค ๋ค์์ ์นํฉ์ด https://api.csstudy.com์ผ๋ก ์์ฒญ์ ํ๋ก์ฑํด์ฃผ๊ธฐ ๋๋ฌธ์ ๋ง์น CORS ์ ์ฑ ์ ์งํจ ๊ฒ์ฒ๋ผ ๋ธ๋ผ์ฐ์ ๋ฅผ ์์ด๋ฉด์๋ ์ฐ๋ฆฌ๋ ์ํ๋ ์๋ฒ์ ์์ ๋กญ๊ฒ ํต์ ์ ํ ์ ์๋ค. ์ฆ, ํ๋ก์ฑ์ ํตํด CORS ์ ์ฑ ์ ์ฐํํ ์ ์๋ ๊ฒ์ด๋ค.
- CORS์ ๋ํด์ ์ค๋ช ํ์์ค.
- CORS ์๋ฌ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ญ๊ฐ์?
- CORS preflight๋ ๋ฌด์์ธ๊ฐ์?