๐Ÿ”ฌComputer Science/๋„คํŠธ์›Œํฌ

CORS ์™€ SOP, CORS ๋™์ž‘ ๋ฐฉ์‹, ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ (Preflight Request)

hellohailie 2022. 6. 16. 00:44

SOP๋ž€?

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

 

https://shinystarforever.tistory.com:443

https:// => ํ”„๋กœํ† ์ฝœ

shinystarforever.tistory.com => ํ˜ธ์ŠคํŠธ

443 => ํฌํŠธ

 

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

 

**์•Œ์•„๋‘๊ธฐ**

http ํ”„๋กœํ† ์ฝœ์˜ ๊ธฐ๋ณธ ํฌํŠธ๋Š” 80

https ํ”„๋กœํ† ์ฝœ์˜ ๊ธฐ๋ณธ ํฌํŠธ๋Š” 443

 

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

 


ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ์ผ์ด ๋งŽ๋‹ค. ์˜ˆ๋ฅผ๋“ค๋ฉด, ์นด์นด์˜ค ์ง€๋„ api, github ์ •๋ณด ๋ฐ›์•„์„œ ์“ฐ๊ธฐ ๋“ฑ๋“ฑ

์–ด๋–ป๊ฒŒํ•˜๋ฉด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ์„๊นŒ?

๐Ÿ‘‡

CORS (Cross-Origin Resource Sharing) / ๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ 

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

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

 

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

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

 


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

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

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

 

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

 

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

 

 

ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ (Preflight Request)์„ ์™œ ์“ธ๊นŒ?

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

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

CORS์— ๋Œ€๋น„๊ฐ€ ๋˜์–ด์žˆ์ง€ ์•Š์€ ์„œ๋ฒ„๋ผ๋„ ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์„ ๋จผ์ € ๋ณด๋‚ด๊ฒŒ ๋˜๋ฉด, ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ์—์„œ CORS ์—๋Ÿฌ๋ฅผ ๋„์›Œ์„œ Cross-Origin ์š”์ฒญ์ด ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•œ๋‹ค.

 


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 ๋ฅผ ๋„ฃ์–ด์•ผํ•œ๋‹ค.
  • ์„œ๋ฒ„ ์ธก์—์„œ Access-Control-Allow-Origin ์„ ์„ค์ •ํ•  ๋•Œ, ๋ชจ๋“  ์ถœ์ฒ˜๋ฅผ ํ—ˆ์šฉํ•œ๋‹ค๋Š” ๋œป์˜ ์™€์ผ๋“œ์นด๋“œ(*)๋กœ ์„ค์ •ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ค๋ฃจ๋Š” ๋งŒํผ ์ถœ์ฒ˜๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์„ค์ •ํ•ด์ฃผ์–ด์•ผ ํ•จ!!

 


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

1. Node.js ์„œ๋ฒ„

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

const http = require('http');

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

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

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

2. Express ์„œ๋ฒ„

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

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

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

//ํŠน์ • ๋„๋ฉ”์ธ
const options = {
  origin: "https://shinystarforever.tistory.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" });
});

 

 

 

 

๐Ÿ˜ƒ ์ž˜๋ชป๋œ ๊ฐœ๋… ์ „๋‹ฌ์ด ์žˆ๋‹ค๋ฉด ๋Œ“๊ธ€ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ์ €์˜ ์„ฑ์žฅ์— ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค๐Ÿค“