CORS(Cross-Origin Resource Sharing)란?

워니·2025년 11월 14일

이것 뭐예요???

목록 보기
1/1
post-thumbnail

CORS(Cross-Origin Resource Sharing)를 이해하기 위해 한국어로 번역해보면, '교차 출처 자원 공유'입니다.
대충 다른 URL에서 어떤 서버 자원을 요청할 수 있는지를 정해주는 정책 같은데, 막 와닿지는 않습니다. 😫

그러니, 한 단어씩 분해해보겠습니다.

Origin(출처)?

만약, https://www.example.com/login에서 로그인을 한다고 했을 때,
https://api.server.com/auth/login로 로그인 정보를 보낸다고 합시다.

위 주소로 로그인 요청을 보낼 때, 우리는 요청 헤더를 같이 보내게 됩니다.
이때, 요청 헤더는 다음과 같습니다.

POST /auth/login HTTP/1.1
Host: api.server.com
Origin: https://example.com
User-Agent: Mozilla/5.0
Accept: application/json

🧐 위의 예시에서 알 수 있듯, Origin은 어디에서 웹 콘텐츠로 접근했는지를 나타냅니다.


(Source: Toss Payments 개발자센터 문서)

구체적으로는, 웹에서 Origin은 접근한 URL의 프로토콜, 호스트(호스트 이름, 포트)로 정의됩니다.

Cross-Origin(교차-출처)

이렇게 Origin을 이해하였으니, Cross-Origin(교차 출처)이 의미하는 '출처가 교차한다'라는 것이 무엇인지 자연스럽게 이해가 될 것입니다.
정리해보면, Cross-origin은 자원을 주고 받으려는 두 출처가 서로 다르다는 뜻입니다.

만약 프론트엔드가 3000번 포트를, 백엔드가 3001번 포트를 사용한다면
프론트엔드에서 백엔드로 보내는 API 요청 또한 Cross-Origin에 해당하게 됩니다.
이는 URL의 포트가 다르기 때문입니다. 👍

또한, www.example.com에서 api.example.com으로 요청을 보낼 때에도 Cross-Origin에 해당합니다. 이는 호스트 네임(도메인)이 다르기 때문입니다.
즉, 서브 도메인이 다르면 다른 도메인으로 인식합니다.
(⚠️엄밀하게는, 호스트 이름과 도메인 이름은 다릅니다. 이를 다룬 글은 추후에 업로드 하겠습니다.)

정리하자면,

CORS는 자신과 프로토콜 또는 호스트가 다른 출처로부터 자원을 가져오는 것이 되어야겠지만, 그렇지 않습니다. 😠
왜냐하면 CORS는 일종의 메커니즘이기 때문입니다.

그래서 CORS의 정확한 정의는 다음과 같습니다.
브라우저가 자신과 프로토콜 또는 호스트가 다른 출처로부터 자원을 가져오는 것을 허용하도록 서버가 허가해주는 HTTP 헤더 기반 메커니즘입니다.
즉, 사용자가 브라우저 내에서 https://example.com라는 웹사이트를 열었고 웹사이트가 https://server.com에게 "너희한테 있는 사진 하나만 쓸게."라고 요청을 보냈을 때 브라우저가 이를 읽을 수 있게 서버가 허가해주는 HTTP 헤더 기반 메커니즘입니다.

위 문장은 자칫 "서버가 허가한다"는 행위를 중심으로 볼 여지가 있습니다.🫢
그런데 사실 CORS는 브라우저의 보안 모델이기에, 서버가 아닌 브라우저를 중심으로 봐야합니다.

브라우저는 기본적으로 SOP(Same-Origin Policy, 동일 출처 정책)을 따르기에, 다른 출처에서 자원을 받아오면 이것을 차단합니다. 🥲
이 SOP 정책에 예외를 추가해주는 것이 CORS입니다.

즉, CORS라는 메커니즘으로 SOP 정책에 예외를 추가하여 다른 출처에서 자원을 받아오는 것을 허용하는 것입니다.
이러면 이제 CORS가 메커니즘이라는 것이 이해가 됩니다.

그래서 백엔드 개발을 하다보면, 혼자 Postman으로 테스트할 때는 잘 동작하던 코드가 프론트엔드와 연결되는 순간 CORS 에러가 발생하는 것을 볼 수 있습니다. 😭😭😭😭
(제가 그 문제를 마주쳐서 정리할 겸 블로그 글을 작성중이긴 해요...)

CORS의 동작 과정

기본적인 CORS 동작 과정

  1. 브라우저는 교차 출처 요청(Cross-Origin Request)를 보낼 때 자동으로 Origin헤더를 추가합니다.

이 헤더는 CORS 요청을 판단하는 필수 신호입니다.

하지만, POST/PUT 등 일부 요청은 비-CORS 상황(Same-Origin Request)에서도 출처를 나타내는 헤더가 추가되기에 Origin 존재 -> 교차 출처 요청은 아닙니다.⚠️

  1. 서버는 응답에서 다음 헤더들로 " 이 요청들은 공유해도 된다"고 알려줍니다.
Access-Control-Allow-Origin: https://example.com

위 헤더는 https://example.com에서는 응답이 공유 가능하다는 것을 나타냅니다.
만약 어느 사이트에서나 응답을 공유하도록 하고 싶다면, URL 대신 *을 사용합니다.

만약, 요청에 쿠키나 Authorization 등 credentials가 포함된 경우에는 * 사용이 제한되며,

Access-Control-Allow-Credentials: true

헤더가 필요합니다.

복잡한 CORS에서의 동작 과정

하지만 만약 CORS가 복잡한 경우에는 예외적으로 CORS-preflight Request(CORS 사전 요청)을 먼저 보내게 됩니다. 🫨🫨🫨
(이때, CORS-preflight Request는 브라우저에 의해 자동으로 수행됩니다.)

복잡한 CORS?

여기서 복잡한 경우란 다음과 같습니다.

  • Content-Type이 브라우저의 안전 목록(safelist)에 없을 때
  • 브라우저의 안전 목록에 없는 커스텀 헤더를 사용할 때
  • GET/HEAD/POST 외의 메서드를 사용하여 요청을 보낼 때
  • credentials 포함 여부 조건을 충족 할 때.
    즉, 복잡한 CORS 요청이란 <form>으로 실행될 수 없는 요청이거나 브라우저가 보안상 위험하다고 판단하는 요청입니다.

CORS 사전 요청

CORS 사전 요청이란, CORS 프로토콜을 서버가 이해할 수 있는지 확인하는 역할을 하는 CORS 요청입니다. 이 요청은 OPTIONS 메서드를 사용하여 동일 엔드포인트(예: /api)로 보내집지며, 다음 헤더를 포함합니다.

  • Access-Control-Request-Method: 동일한 자원에 대한 실제 CORS 요청이 어떤 HTTP 메서드를 사용할 수 있는지를 확인합니다.
  • Access-Control-Request-Headers: 동일한 장원에 대한 실제 CORS 요청이 어떤 헤더를 사용할 수 있는 지를 확인합니다.

이 중 두번째 Access-Control-Request-Headers는 커스텀 헤더를 사용할 때에만 포함됩니다.

CORS 사전 요청에 대한 서버의 응답은 헤더를 포함할 수 있습니다.

  • Access-Control-Allow-Methods: CORS 프로토콜을 위해 해당 URL이 지원하는 HTTP 메서드를 나타냅니다.
  • Access-Control-Allow-Headers: CORS 프로토콜을 위해 해당 URL이 지원하는 헤더를 나타냅니다.
  • Access-Control-Max-Age: 위 두가지 헤더의 정보를 캐시할 수 있는 시간을 나타냅니다. 단위는 초이며, 기본 값은 5입니다.

서버의 응답이 "허가"일 때, 브라우저가 Preflight에서 요청한 메서드/헤더가 있다면 이에 대응하는 응답헤더는 필수적으로 작성하여야합니다.
서버의 응답이 "불허"일 때는 모든 헤더를 보내지 않아도 됩니다.

또한, CORS 사전 요청에 대한 성공 응답은 200 또는 204와 같은 정상 상태 응답으로 제한됩니다. 상태 코드가 2xx가 아닌 응답은 성공적이지 않은 것으로 간주되며, 실제 요청으로 이어지지 않습니다.

이런 과정을 거쳐 CORS 사전 응답이 성공한다면, 브라우저가 실제 CORS 요청을 다시 보냅니다.


오늘은 팀플하다가 백엔드 API를 프론트엔드에 연결했더니 갑자기 CORS 에러가 뜨길래
이것 뭐예요?????? 하면서 CORS에 대해 정리해보았습니다.

글 적으면서 참고한 문서들은 아래에 적어둘게용.

Reference.
https://docs.tosspayments.com/resources/glossary/cors#웹의-발달과-cors
https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/CORS
https://developer.mozilla.org/ko/docs/Glossary/Origin
https://fetch.spec.whatwg.org/#http-cors-protocol
https://aws.amazon.com/ko/what-is/cross-origin-resource-sharing/

profile
광운대학교 정보융합학부 25.

0개의 댓글