Jieunny์˜ ๋ธ”๋กœ๊ทธ

S2) Unit 10. [Web Server] CORS ๋ณธ๋ฌธ

CodeStates/learning contents

S2) Unit 10. [Web Server] CORS

Jieunny 2023. 2. 6. 10:32

๐Ÿ“ฃ  SOP

โœ”๏ธ Same-Origin Policy

โœ”๏ธ '๊ฐ™์€ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋งŒ ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค' ๋ผ๋Š” ์ •์ฑ…

โž• ์ถœ์ฒ˜

๋”๋ณด๊ธฐ

โœ”๏ธ ํ”„๋กœํ† ์ฝœ + ํ˜ธ์ŠคํŠธ + ํฌํŠธ์˜ ์กฐํ•ฉ์œผ๋กœ ๋˜์–ด์žˆ๋‹ค.

โžฐ ์ด ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋‹ค๋ฅด๋ฉด ๋™์ผํ•œ ์ถœ์ฒ˜๋กœ ๋ณด์ง€ ์•Š๋Š”๋‹ค.

โžฐ ์ž ์žฌ์ ์œผ๋กœ ํ•ด๋กœ์šธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์„œ๋ฅผ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ ๊ณต๊ฒฉ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ๋กœ๋ฅผ ์ค„์—ฌ์ค€๋‹ค. -> ํ•ดํ‚น ๋“ฑ์˜ ์œ„ํ˜‘์—์„œ ์ข€ ๋” ์•ˆ์ „

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

โžฐ ํ•˜์ง€๋งŒ ๋„ค์ด๋ฒ„ ์ง€๋„ api๋ฅผ ์ด์šฉํ•œ๋‹ค๊ฑฐ๋‚˜, gtihub์˜ ์ •๋ณด๋ฅผ ๋ฐ›์•„์™€์„œ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

 

๐Ÿ“ฃ  CORS

โœ”๏ธ Cross-origin Resource Sharing

โœ”๏ธ '๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ '

โžฐ ์ถ”๊ฐ€ HTTP ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, ํ•œ ์ถœ์ฒ˜์—์„œ ์‹คํ–‰ ์ค‘์ธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์„ ํƒํ•œ ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋„๋ก ๋ธŒ๋ผ์šฐ์ €์— ์•Œ๋ ค์ฃผ๋Š” ์ฒด์ œ

โžฐ ์ด ์—๋Ÿฌ๋Š” SOP ๋•Œ๋ฌธ์ด๊ณ , CORS๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ“ฃ  CORS ๋™์ž‘ ๋ฐฉ์‹

1๏ธโƒฃ ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ(Preflight Request)

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

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

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

โž• ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์„ ์™œ ์‚ฌ์šฉํ• ๊นŒ?

๋”๋ณด๊ธฐ

โžฐ ์‹ค์ œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „์— ๋ฏธ๋ฆฌ ๊ถŒํ•œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ ์š”์ฒญ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ํ†ต์งธ๋กœ ๋ณด๋‚ด๋Š” ๊ฒƒ ๋ณด๋‹ค ๋ฆฌ์†Œ์Šค ์ธก๋ฉด์—์„œ ํšจ์œจ์ ์ด๋‹ค.

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

 

2๏ธโƒฃ ๋‹จ์ˆœ ์š”์ฒญ(Simple Request)

โœ”๏ธ ํŠน์ • ์กฐ๊ฑด์ด ๋งŒ์กฑ๋˜๋ฉด, ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์„ ์ƒ๋žตํ•˜๊ณ  ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ

     โžฐ GET, HEAD, POST ์š”์ฒญ ์ค‘ ํ•˜๋‚˜์—ฌ์•ผ ํ•œ๋‹ค.

     โžฐ ์ž๋™์œผ๋กœ ์„ค์ •๋˜๋Š” ํ—ค๋” ์™ธ์—, Accept, Accept-Language, Content-Language, Content-Type ํ—ค๋”์˜ ๊ฐ’๋งŒ ์ˆ˜๋™์œผ๋กœ ์„ค์ • ์ˆ˜ ์žˆ๋‹ค.

          โžฐ Content-Type ํ—ค๋”์—๋Š” application/x-www-form-urlencoded, multipart/form-data, text/plain ๊ฐ’๋งŒ ํ—ˆ์šฉ๋œ๋‹ค.

 

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

โœ”๏ธ ์š”์ฒญ ํ—ค๋”์— ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด์•„ ๋ณด๋‚ด๋Š” ์š”์ฒญ์ด๋‹ค.

โœ”๏ธ ๋ฏผ๊ฐํ•œ ์ •๋ณด์ด๊ธฐ ๋•Œ๋ฌธ์— ์ถœ์ฒ˜๊ฐ€ ๋‹ค๋ฅผ ๊ฒฝ์šฐ์—๋Š” ๋ณ„๋„์˜ ์„ค์ •์„ ํ•˜์ง€ ์•Š์œผ๋ฉด ์ฟ ํ‚ค๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์—†๋‹ค.

โœ”๏ธ ํ”„๋ก ํŠธ, ์„œ๋ฒ„ ์–‘์ธก ๋ชจ๋‘ CORS ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค.

โžฐ ํ”„๋ก ํŠธ ์ธก์—์„œ๋Š” ์š”์ฒญ ํ—ค๋”์— withCredentials : true๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค.

โžฐ ์„œ๋ฒ„ ์ธก์—์„œ๋Š” ์‘๋‹ต ํ—ค๋”์— Access-Control-Allow-Credentials : true๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค.

โžฐ ์„œ๋ฒ„ ์ธก์—์„œ Acces-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 ์„ค์ •์„ ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.