일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 경주로 건설
- HTML 기초
- 수식 최대화
- 프로그래머스
- 베스트엘범
- 백준 알고리즘
- 거울 설치
- 12869번
- 19238번
- 15686번
- 빛의 경로 사이클
- SW ExpertAcademy
- 2020 카카오 인턴십
- 9095번
- QueryDSL 기초
- 스타트 택시
- pkce
- 1789번
- 1038번
- 17144번
- 파이썬
- 미세먼지 안녕!
- 16234번
- 보석 쇼핑
- 14499번
- SW Expert Academy
- python
- 12865번
- 키패드 누르기
- 감소하는 수
- Today
- Total
보물창고 블로그
CORS(Cross-Origin Resource Sharing) 파헤치기 본문
CORS(Cross-Origin Resource Sharing)는 브라우저가 웹 페이지의 원본이 아닌 다른 출처(도메인, 프로토콜, 포트)로부터 리소스를 로드하는 것을 허용하기 위한 HTTP 헤더 기반의 메커니즘입니다. 왜 CORS가 필요할까요? 이것을 이해하려면 동일 출처 정책(Same-Origin Policy)" 개념부터 이해해야 합니다.
Same-Origin Policy는 웹 브라우저의 보안 정책 중 하나로, "서로 다른 출처(origin)의 리소스 간 접근을 제한"합니다.
이는 사용자의 데이터를 악의적인 웹사이트로부터 보호하기 위한 기본 장치입니다. 여기서 간단하게 출처에 대해 알아보겠습니다.
✅ "출처(origin)"란?
출처(origin)는 다음 세 가지로 정의됩니다:
- 프로토콜 (http, https)
- 호스트 (도메인 이름, IP 주소)
- 포트 번호
출처가 다르면 SOP는 제한을 걸게 됩니다. URL 동일 출처?
https://example.com:443 vs https://example.com:443 | ✅ 동일 |
http://example.com vs https://example.com | ❌ 다름 (프로토콜 다름) |
https://example.com vs https://api.example.com | ❌ 다름 (서브도메인 다름) |
https://example.com:443 vs https://example.com:8443 | ❌ 다름 (포트 다름) |
그럼 왜 SOP가 필요할까요?
웹사이트는 로그인 상태 유지를 위해 쿠키나 세션을 사용합니다. 이 정보는 같은 도메인에서 요청할 때 자동으로 전송됩니다.
예를 들어:
- 사용자가 https://bank.com에 로그인하면, 쿠키에 인증 정보가 저장됩니다.
- 이후 사용자가 https://evil.com을 방문했을 때, 그 사이트가 자바스크립트를 통해 https://bank.com/transfer로 요청을 보내면?
- 브라우저는 쿠키를 자동으로 첨부해서 은행에 요청을 보냅니다!
이걸 허용하면 해킹이 매우 쉬워집니다. 그래서 브라우저는 "다른 출처(origin)"로의 요청을 막습니다. 이 공격을 CSRF(Cross-Site Request Forgery)라고 부릅니다.
CSRF 예시)
<!-- 악성 사이트에 숨겨진 폼 -->
<form action="https://bank.com/transfer" method="POST">
<input type="hidden" name="to" value="hacker_account">
<input type="hidden" name="amount" value="10000">
</form>
<script>document.forms[0].submit();</script>
사용자가 이 페이지를 보기만 해도, 은행 계좌에서 돈이 빠져나갈 수 있습니다. 이걸 막는 방법 중 하나가 Same-Origin Policy입니다. 그렇다면 웹앱(FE)은 https://myapp.com에 있고, API(BE)는 https://api.myapp.com에 있을 수 있다고 가정할 때, SOP를 어떻게 해결해야 할까요? 이 경우 브라우저가 기본 정책으로는 API 요청을 차단하므로, 서버가 "괜찮아! 너 요청해도 돼!"라고 말할 수 있는 수단이 필요합니다. 👉 그게 바로 CORS (Cross-Origin Resource Sharing)입니다. 이제 CORS의 작동 방식에 대해 알아보겠습니다.
CORS 기본적인 흐름은 다음과 같습니다.
- 클라이언트가 다른 출처로 HTTP 요청을 보냄
- 브라우저가 요청을 중간에서 가로채고, 서버가 CORS 허용을 했는지 확인
- 서버가 응답에 Access-Control-Allow-Origin 등의 CORS 관련 헤더를 포함
- 브라우저가 응답을 허용하거나 차단
위 흐름 중 2번 단계에서 브라우저가 자바스크립트 코드로 cross-origin 요청을 보낼 때, 단순요청인지 아닌지에 따라 브라우저는 preflight(사전요청)을 자동으로 수행합니다. 그렇다면 preFlight는 무엇일까요?
🚦 Preflight Request (사전 요청)
조건:
- 메서드가 GET, POST, HEAD 외의 것
- Content-Type이 application/json 등 "단순하지 않은 타입"
- 커스텀 헤더 포함
- 쿠키 포함
동작:
브라우저가 먼저 OPTIONS 요청을 보내, 서버가 허용하는지 확인 → 허용되면 실제 요청 전송
예를 들면 웹앱(FE)은 https://myapp.com에 있고, API(BE)는 https://api.myapp.com에 있을 수 있다고 가정할 때,
웹앱에서 아래와 같이 요청을 보낸다고 가정해 보겠습니다.
fetch('http://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'John' }),
credentials: 'include'
});
여기서 브라우저는 다음을 보고 판단합니다.
- 메서드: POST → 괜찮음
- Content-Type: application/json → ❌ "단순 요청 아님!" → Preflight 요청 필요!
preflight가 필요하므로 브라우저에서 서버로 Preflight 요청 (OPTIONS) 을 하게 됩니다.
OPTIONS /data HTTP/1.1
Host: api.example.com
Origin: http://localhost:3000
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
브라우저에서 preflight 요청을 받은 서버는 해당 요청을 받아서 CORS요청이 허용된 요청인지를 확인한 후, 허용된 CORS요청이면 다음과 같이 응답을 합니다.
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Credentials: true
서버에서 온 preflight에 대한 응답 이후엔 브라우저에서 본 요청(actual request)을 하고, 서버에선 본 요청에 대한 응답을 하게 됩니다.
이번 시간에는 CORS에 대해서 알아보았습니다.
'웹 개발 > Computer Science Note' 카테고리의 다른 글
Spring Interceptor 파헤치기 (0) | 2025.05.11 |
---|---|
Spring filter 파헤치기 (0) | 2025.05.10 |
JWT 파해치기 (0) | 2025.05.03 |
Oauth 파헤치기 (1) | 2025.05.02 |