"Access-Control-Allow-Origin을 추가했더니 API가 동작했는데 — 이거 안전한가?" CORS는 "추가하면 끝"이 아니라, 핵심은 누구를 허용할지 좁히는 것입니다. 작동 원리와 안전하게 설정하는 법을 살펴봅니다(공격 절차는 다루지 않습니다).
먼저, 작동 원리
브라우저는 **동일 출처 정책(same-origin policy)**을 강제합니다: 다른 오리진의 JS는 다른 사이트의 응답을 자유롭게 읽을 수 없습니다. CORS는 그 예외를 서버가 명시적으로 허용한 대상에게만 여는 것입니다.
| 응답 헤더 | 의미 |
|---|---|
Access-Control-Allow-Origin | 어떤 오리진이 응답을 읽어도 되는가 |
Access-Control-Allow-Credentials | 자격 증명(쿠키)이 포함된 요청을 허용하는가 |
Access-Control-Allow-Methods / -Headers | 어떤 HTTP 메서드/헤더를 허용하는가 |
핵심: CORS는 "제한을 푸는" 쪽입니다. 잘못 풀면 읽혀서는 안 될 데이터가 제3자에게 읽히게 됩니다.
무엇이 설정을 위험하게 만드는가
위험한 설정(흔함)
- 요청의 Origin을 그대로 허용으로 반사
Access-Control-Allow-Origin: *와 자격 증명 허용 병용- 필요 없는 API를 광범위하게 크로스 오리진으로 개방
안전한 설정
- 허용 목록(고정된 신뢰 오리진만)
- 그 외 모두에 대한 기본 거부
- 자격 증명 요청에는
*가 아닌 특정 오리진
안전한 설정의 기본
허용 목록 사용(가장 중요)
Origin을 무분별하게 반사하지 않기
Origin을 Access-Control-Allow-Origin에 그대로 되돌려주지 마세요. 허용 목록과 일치할 때만 반환하세요.* 와 자격 증명을 절대 병용하지 않기
Access-Control-Allow-Origin: *를 Allow-Credentials: true와 함께 쓰지 마세요. 대신 특정 오리진을 명시하세요.여는 범위를 최소화
본 사이트의 견해: CORS는 '방어'가 아니라 '여는 방식'이다 — 누구에게 열지를 좁혀라
흔한 오해는 "CORS 헤더를 추가하면 안전해진다"입니다. 사실은 그 반대로 — CORS는 브라우저의 제한을 느슨하게 풉니다. 그래서 요령은 "어떻게 추가하느냐"가 아니라 "누구에게, 어디까지 여느냐를 최소화하는 것"입니다. 본 사이트는 외부에서 읽혀도 되는 데이터와 그렇지 않은 데이터를 분리하고, 기본 거부에 허용 목록으로 예외만 여는 방식을 권장합니다. XSS(읽기 전제를 무너뜨림)와 CSRF(상태 변경을 노림)는 별개의 결함임에 유의하세요 — CORS 하나로 전부를 덮을 수는 없습니다.
다음으로 읽기
FAQ
QCORS는 무엇을 위한 것인가요?
브라우저는 동일 출처 정책(same-origin policy)을 강제합니다: 한 오리진(사이트)의 JavaScript는 다른 사이트의 응답을 자유롭게 읽을 수 없습니다. CORS(Cross-Origin Resource Sharing)는 서버가 그 예외를 — 단, 명시적으로 허용한 대상에게만 — 여는 방식입니다. Access-Control-Allow-Origin 같은 응답 헤더가 어떤 오리진이 응답을 읽어도 되는지를 선언합니다.
QCORS 설정 오류는 무엇을 노출하나요?
지나치게 느슨한 권한은 공격자의 사이트가 JavaScript로 사용자의 로그인된 API 응답을 읽게 할 수 있습니다. 전형적인 경우: 요청의 Origin을 그대로 허용으로 반사하거나, 자격 증명(쿠키)도 허용하면서 Access-Control-Allow-Origin을 *로 설정하는 것. 그 결과 개인 데이터나 토큰이 제3자 사이트에 도달할 수 있습니다.
Q안전한 설정의 기준은 무엇인가요?
허용 목록(allowlist)입니다. 미리 정한 신뢰 오리진만 허용하고 나머지는 거부하세요(기본 거부). 요청의 Origin을 무분별하게 반사하지 마세요. 자격 증명이 포함된 요청에는 Access-Control-Allow-Origin에 *를 쓰지 말고 특정 오리진을 명시하세요. 그리고 정말로 크로스 오리진이 필요한 엔드포인트만 노출하세요.