브라우저의 메커니즘인 동일 출처 정책 (Same Origin Policy, SOP)에 대해 알아보자
우리가 예를들어 sns에 로그인을 한 상태라면, 해당 브라우저에는 sns에 대한 세션이 저장돼있을 것이다.
근데, 만약 이때 악성 사이트에 접속하게 된다면,,? 그리고 접속한 악성 사이트에 sns로의 악의적인 요청이 있다면?
-> 브라우저는 특성상 sns의 쿠키와 함께 악의적인 요청을 보낼 것이고, 그렇게 되면 피해가 생길 수 있다.
이렇게 브라우저는 악성 페이지 안에 심어진 타 사이트 요청을 실제로 보낼 수 있고, 경우에 따라 로그인 쿠키도 함께 보낼 수 있다.
그러면 대상 서버는 인증된 응답을 반환할 수 있는데, 해당 응답을 그냥 읽을 수 있다면, 경우에 따라 큰 피해가 발생 할 수 있다.
그래서 이렇게 반환된 응답을 아무나 읽지 못하도록 해주는 장치가 SOP이다.
SOP의 오리진(origin) 구분 방법
브라우저가 가져온 정보의 출처인 origin을 어떻게 구분할까?
오리진 (origin)은
프로토콜(protocol, scheme)
포트 (port)
호스트 (host)
로 구성된다
-> 해당 구성요소가 모두 일치헤야 동일한 오리진이라고 한다.
예를들어서,
https://maru.com/ 이라는 오리진과 비교했을 때
- https://maru.com/ frame.html -> Same Origin : path만 다름
- http://maru.com/ -> Cross Origin : Scheme이 다름
- https://maru-wooin.com/ frame.html -> Cross Origin : host가 다름
- https://maru.com:1234/. -> Cross Origin : Port가 다름
이렇게 SOP는 Same Origin 일 때만 정보를 읽을 수 있도록 해줌
실습
실제로 dreamhack.io 오리진으로
theori.io 막힘

반면에,
동일 사이트는 가능함!

Cross-Origin Resource Sharing (CORS)
SOP 때문에 기본적으로 읽을 수 없는 다른 출처의 응답을, 서버가 허용한 경우에만 브라우저가 자바스크립트에 전달해주는 규칙
(서버가 허락한 출처라면 읽어도 됨!)
CORS의 과정을 한번 살펴보자
먼저, 개발자가 작성한 웹리소스 요청 코드이다
/*
XMLHttpRequest 객체를 생성합니다.
XMLHttpRequest는 웹 브라우저와 웹 서버 간에 데이터 전송을
도와주는 객체입니다. 이를 통해 HTTP 요청을 보낼 수 있습니다.
*/
xhr = new XMLHttpRequest();
/* https://theori.io/whoami 페이지에 POST 요청을 보내도록 합니다. */
xhr.open('POST', 'https://theori.io/whoami');
/* HTTP 요청을 보낼 때, 쿠키 정보도 함께 사용하도록 해줍니다. */
xhr.withCredentials = true;
/* HTTP Body를 JSON 형태로 보낼 것이라고 수신측에 알려줍니다. */
xhr.setRequestHeader('Content-Type', 'application/json');
/* xhr 객체를 통해 HTTP 요청을 실행합니다. */
xhr.send("{'data':'WhoAmI'}");
-> theori.io/whoami에 쿠키를 포함해서 json 형식의 POST요청을 보내고 싶다
이걸, 요청을 보내면 브라우저가 일단 먼저 확인을 함
Cross-Origin 요청인지?
단순한 요청인지, 특별한 요청인지?
근데, POST까지는 괜찮은데 Content-Type: application/json 이건 단순요청은 아님
-> 바로 서버에 요청이 아니라, preflight request라고 서버에 먼저 이런 요청 보내도 됨? 하고 허락 맡는 거 보냄
이렇게, OPTION 메소드로,,
OPTIONS /whoami HTTP/1.1
Host: theori.io
Connection: keep-alive
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Origin: https://dreamhack.io
Accept: */*
Referer: https://dreamhack.io/
-> 브라우저가 개발자가 작성한 웹리소스 코드 보고 자동으로 작성해서 보내는 것임
그러면,
이제 서버에서 CORS에 대해 응답을 주는데,,
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://dreamhack.io
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type
-> dreamhack.io Cross-Origin ㅇㅋ
-> 메소드는 POST, GET, OPTIONS만 ㅇㅋ
-> 쿠키? ㅇㅋ
-> Content-Type? ㅇㅋ
*여기서 credential에 쿠키는 요청대상인 theori.io의 쿠키를 말하는 것임*
이렇게, 허락 맡았으면 이제 실제 POST요청을 전송한다
POST /whoami HTTP/1.1
Host: theori.io
Origin: https://dreamhack.io
Content-Type: application/json
Cookie: theori_session=abc123
여기까지가 preflight가 필요한 CORS 요청이고
그럼, Preflight가 필요없는 단순 요청은 어떤 순서로,,?
1. 개발자가 요청 코드 작성
2. 브라우저가 cross-origin 여부 확인
3. 단순 요청이라고 판단
4. 실제 요청을 바로 전송
5. 서버가 응답
6. 응답의 CORS 헤더 확인
7. 조건이 맞으면 자바스크립트가 응답 읽기 가능
보통 이런순서로 ㄱㄱ 한다
그럼 6번에 적은 것 처럼 응답에 CORS 헤더가 담겨서옴
예를들면,,
Access-Control-Allow-Origin: https://dreamhack.io
이런식으로,,!
--> 이렇게 CORS가 나오기전에 JSONP라는 방식도 많이 사용했었음
JSONP (JSON with Padding)
-> 이미지, 자바스크립트, CSS 등의 리소스는 SOP에 상관없이 외부 출처에 대해 접근을 허용해줌
-> 이걸 이용해 <script></script>태그로 Cross Origin의 데이터를 불러오는 방식
-> 근데, <script>태그 내에서는 데이터를 자바스크릅트의 코드로 인식하기 때문에 Callback 함수를 활용함
*call back함수 -> 나중에 다시 불러서 실행 ,, 이런 느낌함수*
코드 예시로 보면
<script>
/* myCallback이라는 콜백 함수를 지정합니다. */
function myCallback(data){
/* 전달받은 인자에서 id를 콘솔에 출력합니다.*/
console.log(data.id)
}
</script>
<!--
https://theori.io의 스크립트를 로드하는 HTML 코드입니다.
단, callback이라는 이름의 파라미터를 myCallback으로 지정함으로써
수신측에게 myCallback 함수를 사용해 수신받겠다고 알립니다.
-->
<script src='http://theori.io/whoami?callback=myCallback'></script>
이렇게, <script>태그로 외부 스크립트를 불러오고 클라이언트 측 코드에 callback함수로 데이터를 읽는다!
위 코드 처럼 쓰면,
myCallback({
"name": "ina",
"role": "user"
});
json을 이렇게 myCallback으로 감싸서 가져오고, 그럼 내부에서 myCallback함수로 데이터를 읽어낼 수 있게 됨!
순서 정리를 해보면,
1. 내 페이지에 myCallback 함수 정의
2. script src로 외부 서버 요청
3. 요청 URL에 callback=myCallback 전달
4. 서버가 응답을 myCallback(데이터) 형태로 생성
5. 브라우저가 그 응답을 JS 코드로 실행
6. 내 페이지의 myCallback 함수가 호출됨
7. 함수 인자로 데이터 획득
이렇게 된다.
*<script src = '~~~'></script> => 이렇게 쓰는 건 보통 외부 서버에 요청 할때,,,
-> 저 주소에서 자바스크립트 코드 받아와서 실행해야지
*<script>~~~</script> => 내부에 직접 적은 스크립트 실행
현재는 CORS를 사용하기 때문에 JSONP는 거의 사용하지 않는 추세다!
'web2' 카테고리의 다른 글
| docker 사용하기 (run, compose) (0) | 2026.06.17 |
|---|---|
| CSRF(Cross-Site Request Forgery) (0) | 2026.06.04 |
| DOM-based XSS (0) | 2026.06.02 |
| 웹은 어떻게 동작하나요(HTML,JS,CSS,브라우저의 관계) (0) | 2026.05.31 |
| XSS (cross-site scripting) (0) | 2026.05.30 |