๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ•ธ๏ธ ์›น ํ•ดํ‚น

์›น ๋ธŒ๋ผ์šฐ์ € ๋ณด์•ˆ ์ •์ฑ… SOP, CORS, JSONP ๊ฐœ๋… ์ •๋ฆฌ

by ๋ถˆํƒ€๋Š” ์ฐธ์ƒˆ 2025. 3. 5.

๐Ÿ›ก๏ธ Same Origin Policy (SOP)๋ž€?

SOP(๋™์ผ ์ถœ์ฒ˜ ์ •์ฑ…)๋Š” ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ณด์•ˆ ๊ฐ•ํ™”๋ฅผ ์œ„ํ•ด ์ ์šฉํ•˜๋Š” ์ •์ฑ…์œผ๋กœ, ๋‹ค๋ฅธ ์ถœ์ฒ˜(Origin)์—์„œ ๋ถˆ๋Ÿฌ์˜จ ๋ฆฌ์†Œ์Šค๊ฐ€ ํ˜„์žฌ ์›น ํŽ˜์ด์ง€์˜ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜์ง€ ๋ชปํ•˜๋„๋ก ์ œํ•œํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”น Origin(์ถœ์ฒ˜) ์ •์˜

Origin์€ ๋‹ค์Œ ์„ธ ๊ฐ€์ง€ ์š”์†Œ๊ฐ€ ์™„์ „ํžˆ ์ผ์น˜ํ•ด์•ผ ๋™์ผํ•œ ์ถœ์ฒ˜๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค.

์š”์†Œ ์˜ˆ์‹œ

ํ”„๋กœํ† ์ฝœ (Protocol / Scheme) http:// vs. https://
ํ˜ธ์ŠคํŠธ (Host / Domain) example.com vs. api.example.com
ํฌํŠธ (Port) http://example.com:80 vs. http://example.com:8080

 

โœ… ๊ฐ™์€ Origin์˜ ์˜ˆ์‹œ

https://www.example.com:443
https://www.example.com:443/somepage

 

โœ… ๋‹ค๋ฅธ Origin์˜ ์˜ˆ์‹œ

https://www.example.com:443 โŒ http://www.example.com:443  (ํ”„๋กœํ† ์ฝœ ๋‹ค๋ฆ„)
https://www.example.com:443 โŒ https://api.example.com:443 (ํ˜ธ์ŠคํŠธ ๋‹ค๋ฆ„)
https://www.example.com:443 โŒ https://www.example.com:8080 (ํฌํŠธ ๋‹ค๋ฆ„)

๐ŸŒ SOP ์˜ˆ์™ธ: ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š” ์š”์†Œ

์›น ํŽ˜์ด์ง€์—์„œ ์™ธ๋ถ€ ์ž์›์„ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ SOP๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
<img>, <script>, <link>์™€ ๊ฐ™์€ ํƒœ๊ทธ๋“ค์€ ์™ธ๋ถ€ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ๋งŒ ๊ฐ€๋Šฅํ•  ๋ฟ, JS์—์„œ ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

→ ์ด๋Ÿฐ ๋ฆฌ์†Œ์Šค๋“ค์€ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ง์ ‘ ๋กœ๋“œํ•˜๊ธฐ ๋•Œ๋ฌธ์— SOP ์ œํ•œ ์—†์ด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ”„ SOP ์˜ˆ์™ธ: Cross-Origin Resource Sharing (CORS)

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ณด์•ˆ ์ •์ฑ…์„ ์™„ํ™”ํ•ด ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ—ˆ์šฉํ•ด์•ผ ํ•  ๊ฒฝ์šฐ,
CORS (๊ต์ฐจ ์ถœ์ฒ˜ ๋ฆฌ์†Œ์Šค ๊ณต์œ ) ๋ผ๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”น CORS ์ž‘๋™ ๋ฐฉ์‹

1๏ธโƒฃ ํด๋ผ์ด์–ธํŠธ(์›น ๋ธŒ๋ผ์šฐ์ €) ๊ฐ€ https://api.example.com์— ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•จ.
2๏ธโƒฃ ์„œ๋ฒ„(api.example.com) ๊ฐ€ ํŠน์ • ์ถœ์ฒ˜์˜ ์š”์ฒญ์„ ํ—ˆ์šฉํ•˜๋ฉด ์‘๋‹ต ํ—ค๋”์— Access-Control-Allow-Origin์„ ํฌํ•จ์‹œํ‚ด.

Access-Control-Allow-Origin: https://www.example.com

3๏ธโƒฃ ํ—ˆ์šฉ๋œ Origin์—์„œ ์˜จ ์š”์ฒญ์ด๋ผ๋ฉด, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•จ.

 

โœ… CORS ํ—ˆ์šฉ ์˜ˆ์‹œ

GET /data HTTP/1.1
Host: api.example.com
Origin: https://www.example.com
---
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.com

โš ๏ธ CORS Preflight (์‚ฌ์ „ ์š”์ฒญ)

POST, PUT, DELETE ๋“ฑ์˜ ๋ฏผ๊ฐํ•œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ฑฐ๋‚˜, ํŠน์ • ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•  ๊ฒฝ์šฐ
๋ธŒ๋ผ์šฐ์ €๋Š” OPTIONS ์š”์ฒญ์„ ๋จผ์ € ๋ณด๋‚ด์„œ ์„œ๋ฒ„๊ฐ€ ํ—ˆ์šฉํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ณผ์ •(CORS Preflight)์„ ๊ฑฐ์นฉ๋‹ˆ๋‹ค.

โœ… Preflight ์š”์ฒญ ์˜ˆ์‹œ

OPTIONS /data HTTP/1.1
Origin: https://www.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

โœ… ์„œ๋ฒ„ ์‘๋‹ต ์˜ˆ์‹œ

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: Content-Type

 

โœ”๏ธ ์„œ๋ฒ„๊ฐ€ POST ๋ฉ”์†Œ๋“œ์™€ Content-Type ํ—ค๋”๋ฅผ ํ—ˆ์šฉํ•œ๋‹ค๊ณ  ์‘๋‹ตํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๋Š” ๋ณธ ์š”์ฒญ์„ ์ง„ํ–‰ํ•จ.


โš™๏ธ JSONP (JSON with Padding)

๐Ÿ’ก JSONP๋Š” CORS๊ฐ€ ์—†๋˜ ์‹œ์ ˆ ์‚ฌ์šฉ๋˜๋˜ ์šฐํšŒ ๋ฐฉ๋ฒ•์œผ๋กœ, <script> ํƒœ๊ทธ๊ฐ€ SOP์˜ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š” ์ ์„ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

โœ… JSONP ์š”์ฒญ ๋ฐฉ์‹

<script src="https://other.com/data?callback=myCallback"></script>
  • ์„œ๋ฒ„๊ฐ€ callback์— ํ•ด๋‹นํ•˜๋Š” ํ•จ์ˆ˜๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์‹ธ์„œ ๋ฐ˜ํ™˜ํ•จ. ์ฆ‰, ์„œ๋ฒ„์—๊ฒŒ "myCallback์ด๋ผ๋Š” ํ•จ์ˆ˜๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์‹ธ์„œ ๋ณด๋‚ด๋‹ฌ๋ผ" ๋ผ๊ณ  ์š”์ฒญํ•˜๋Š” ๊ฒƒ.

โœ… ์„œ๋ฒ„ ์‘๋‹ต ์˜ˆ์‹œ

myCallback({"name": "Alice", "age": 25});
  • ์ผ๋ฐ˜์ ์ธ JSON ์‘๋‹ต์ด ์•„๋‹ˆ๋ผ, myCallback() ํ•จ์ˆ˜ ํ˜ธ์ถœ ํ˜•ํƒœ๋กœ ๊ฐ์‹ธ์ ธ ์žˆ์Œ

โœ… ํด๋ผ์ด์–ธํŠธ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ

function myCallback(data) {
    console.log(data.name);  // "Alice"
}

 

โœ”๏ธ ๋ธŒ๋ผ์šฐ์ €๋Š” <script> ํƒœ๊ทธ์˜ ์‘๋‹ต์„ ์‹คํ–‰ํ•˜๋ฉด์„œ myCallback({name: "Alice"})์„ ์‹คํ–‰ํ•จ.
โœ”๏ธ ๊ฒฐ๊ณผ์ ์œผ๋กœ, myCallback ํ•จ์ˆ˜๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋จ.

 

โ›” ํ•˜์ง€๋งŒ JSONP๋Š” ๋ณด์•ˆ ์ทจ์•ฝ์ (XSS ๊ณต๊ฒฉ ๋“ฑ)์ด ์žˆ์–ด ํ˜„์žฌ๋Š” ๊ฑฐ์˜ ์‚ฌ์šฉ๋˜์ง€ ์•Š์œผ๋ฉฐ, CORS๊ฐ€ ๋Œ€์ฒดํ•˜๊ณ  ์žˆ์Œ.


โœ… ์ •๋ฆฌ

SOP (Same Origin Policy) ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ์ œํ•œํ•˜๋Š” ๋ณด์•ˆ ์ •์ฑ…
CORS (Cross-Origin Resource Sharing) ์„œ๋ฒ„์—์„œ Access-Control-Allow-Origin ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋‹ค๋ฅธ ์ถœ์ฒ˜์˜ ์š”์ฒญ์„ ํ—ˆ์šฉ
CORS Preflight ์š”์ฒญ OPTIONS ์š”์ฒญ์„ ํ†ตํ•ด ์„œ๋ฒ„๊ฐ€ ํ—ˆ์šฉํ•˜๋Š” ๋ฉ”์†Œ๋“œ์™€ ํ—ค๋”๋ฅผ ํ™•์ธํ•˜๋Š” ๊ณผ์ •
JSONP (JSON with Padding) <script> ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋Š” ์˜›๋‚  ๋ฐฉ์‹ (ํ˜„์žฌ ๊ฑฐ์˜ ์‚ฌ์šฉ ์•ˆ ํ•จ)

 

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