CORS

Socra·2026년 6월 9일
post-thumbnail

CORS (Cross-Origin Resource Sharing)란?

CORS(Cross-Origin Resource Sharing)는 서로 다른 Origin 간의 리소스 요청을 허용하기 위한 브라우저 기반의 보안 정책이다.

여기서 Origin은 다음 세 가지 조합으로 정의된다.

  • 프로토콜 (http / https)
  • 도메인 (example.com)
  • 포트 (80, 443, 3000 등)

즉, 이 세 가지 중 하나라도 다르면 서로 다른 Origin으로 간주된다.

CORS는 서버 간 통신이 아니라 브라우저가 적용하는 보안 정책이라는 점이 핵심이다.


CORS가 필요한 이유

웹 애플리케이션 구조가 발전하면서 프론트엔드와 백엔드가 서로 다른 도메인에서 동작하는 경우가 많아졌다.

프론트엔드: https://frontend.com
백엔드 API: https://api.backend.com

이 상태에서 브라우저는 기본적으로 보안 정책인 Same-Origin Policy(SOP)에 의해 cross-origin 요청을 차단한다.

이러한 제한이 없을 경우 다음과 같은 문제가 발생할 수 있다.

  • 악성 사이트가 사용자의 브라우저를 통해 다른 사이트의 API 호출
  • 인증 정보 탈취
  • 의도하지 않은 데이터 요청

CORS는 이러한 제한을 “선별적으로 허용”하기 위해 존재한다.


Same-Origin Policy (SOP)

Same-Origin Policy는 브라우저 보안의 기본 원칙이다.

이 정책에 따르면, 동일한 Origin에서만 다음이 허용된다.

  • AJAX 요청 결과 접근
  • DOM 접근
  • 응답 데이터 읽기

반대로 Origin이 다르면 요청 자체는 가능할 수 있지만, 응답 데이터를 JavaScript에서 읽는 것이 차단된다.

즉, SOP는 “요청 차단”이 아니라 “응답 읽기 차단”이라는 점이 중요하다.

CORS는 SOP의 예외 허용 규칙을 정의하는 메커니즘이라고도 볼 수 있다.


CORS 동작 방식

CORS는 요청을 두 가지 방식으로 처리한다.

Simple Request

다음 조건을 만족하면 Preflight 없이 바로 요청이 전송된다.

  • GET, POST, HEAD 메서드
  • 제한된 헤더만 사용
  • 커스텀 헤더 없음

이 경우 브라우저는 바로 요청을 보내고, 서버의 응답 헤더를 보고 허용 여부를 판단한다.

Preflight Request

조건을 만족하지 않는 요청은 먼저 OPTIONS 요청을 보낸다.

예를 들어 다음과 같은 경우이다.

  • Authorization 헤더 사용
  • PUT, DELETE, PATCH 사용
  • Custom Header 사용

흐름은 다음과 같다.

브라우저가 OPTIONS 요청 전송
서버가 허용 메서드 및 헤더 응답
허용된 경우 실제 요청 전송

즉, 실제 요청 전에 “허용 여부를 사전 확인” 하는 과정이다.

Preflight가 발생하지 않는 GET, POST는 CORS 적용이 안되나?

Preflight와 CORS는 별개다.

Preflight Request가 발생하지 않는다고 해서 CORS가 적용되지 않는 것은 아니다.

GET과 같은 Simple Request도 CORS 환경에서 동작하며, 응답에 적절한 CORS 헤더가 없으면 브라우저가 응답 접근을 차단한다.

Preflight Request는 CORS 환경에서 브라우저가 실제 요청을 보내기 전에 해당 Origin, 메서드, 헤더가 허용되는지 서버에 사전 확인하는 과정이다.

CORS로 CSRF 공격을 방지할 수 있나?

CORS는 CSRF 공격을 막기 위해 존재하는 것이 아니다.

CORS는 다른 Origin의 스크립트가 응답 데이터를 읽는 수 있는지만 제어할 뿐, 요청 전송 자체는 보호하지 않는다.

"다른 Origin의 JavaScript가 응답 데이터를 읽을 수 있는지 제어하기 위한 메커니즘" 이다.


CORS 주요 헤더

CORS는 서버가 다음 헤더를 통해 정책을 결정한다.

Access-Control-Allow-Origin
→ 허용할 Origin 지정
Access-Control-Allow-Methods
→ 허용 HTTP 메서드 정의
Access-Control-Allow-Headers
→ 허용 헤더 정의
Access-Control-Allow-Credentials
→ 쿠키/인증 정보 허용 여부
Access-Control-Expose-Headers
→ 클라이언트에 노출할 응답 헤더 정의


Preflight 발생 조건

Preflight는 다음 조건 중 하나라도 만족하면 발생한다.

GET/POST/HEAD 외의 메서드 사용
Authorization, X-Custom-Header 등 커스텀 헤더 사용
Content-Type이 application/json 등 단순하지 않은 경우
credentials 포함 요청

즉, “단순 요청이 아닌 경우” 모두 Preflight 대상이 된다.


CORS에서 인증 정보는 중요한 이슈이다.

  • Cookie 기반 인증
  • SameSite 정책 영향을 받는다
  • SameSite=None + Secure 설정 필요
  • Authorization 헤더 기반 인증
  • Preflight 발생 가능성이 높다
  • 서버에서 Allow-Headers에 포함해야 한다

또한 다음 조건이 필요하다.

  • Access-Control-Allow-Credentials: true
  • Allow-Origin: * 사용 불가

CORS 에러 해결 방법

CORS 에러는 대부분 서버 설정 문제이다.

대표적인 해결 방법은 다음과 같다.

  • Access-Control-Allow-Origin 정확히 설정
  • 필요한 메서드 허용 추가
  • Preflight OPTIONS 처리
  • Allow-Headers 설정 추가
  • credentials 설정 일치

프론트에서 해결할 수 있는 문제는 거의 없다.

혹은 Reverse Proxy를 적용해서 같은 Origin으로 만들고,
애초에 CORS 환경이 되지 않도록 만드는 방법도 있다.


CORS vs CSRF vs XSS

혼동되지만 다른 것들

CORS (브라우저 정책)
Cross-Origin Resource Sharing

  • 브라우저의 보안 정책
  • cross-origin 요청 제어

CSRF (요청 위조)
Cross-Site Request Forgery

  • 사용자의 의도와 다른 요청을 보내는 공격
  • 인증 쿠키 기반 시스템에서 발생

XSS (스크립트 삽입)
Cross-Site Scripting

  • 악성 스크립트를 삽입하는 공격
  • 브라우저 내부에서 코드 실행

XSS는 내 컴퓨터(브라우저)에서 남의 스크립트가 내 정보를 훔쳐가는 것이고, CSRF는 내가 로그인한 은행이나 사이트 서버에 나쁜 짓(요청)을 몰래 시키는 것이다.

XSS 쿠키 및 세션 토큰 탈취, 개인정보 유출, 피싱이 목적인 클라이언트 대상 공격
CSRF 비밀번호 변경, 글 삭제, 불법 결제 등 권한 도용이 목적인 서버 대상 공격


정리

CORS는 서버 간 통신 문제가 아니라 브라우저가 적용하는 보안 정책이다.

  • Same-Origin Policy를 기반으로 동작한다
  • 서버는 허용 여부만 응답한다
  • Preflight는 안전성 검증 과정이다

CORS 로 문제를 겪는다면?

즉 정리하자면, CORS 문제를 해결하는 방법은

    1. 서버에서 응답에 CORS 헤더를 추가하는 방법
    1. Reverse Proxy를 적용해 같은 Origin으로 구성해 CORS 환경이 아니게 만들어버리기

Preflight 자체의 이점이 있긴 하지만, 백엔드와 프론트엔드를 따로 구성할 땐 오히려 Preflight를 줄이는 게 성능을 개선하는 방향이라고 볼 수 있다.

프론트, 백엔드를 나눠서 개발을 진행할 땐 애초에 Reverse Proxy를 두어 같은 Origin처럼 보이게 구성해 CORS 환경이 아니게 만드는게 더 좋다고 생각한다.

약간의 복잡성이 추가되지만 단순히 백엔드에서 CORS를 신경쓰지 않아도 되는 개발 편의성 외로도 많은 장점이 있다.

  • Preflight 요청이 줄어들어 응답 속도가 개선되고
  • Cookie 관리가 쉬워져 인증 관리가 쉬워지고
  • 백엔드 구조를 숨길 수 있으며
  • API Gateway로 활용해서 로드 밸런싱, 무중단 배포 적용 등

0개의 댓글