웹 개발을 하다보니, 가끔 접속부터 아무 창이 뜨지 않는(내가 만든 페이지가 보여지지 않는) 상황이 발생한다. F12를 눌러 개발자 모드로 들어가서 오류 문구를 확인해보면, CORS 에러를 종종 만나곤 한다. 그럴 때는 옆자리의 백엔드 개발 담당자에게 CORS 뜬다고 "이거 왜 이래요?" 하면 해결해주기도 한다. 이참에 CORS가 뭐고, 왜 오류가 나는 것인지 찾아보도록 하겠다.
CORS(Cross-Origin Resource Sharing)는 웹 브라우저가 보안상의 이유로 동일 출처 정책(SOP, Same-Origin Policy)을 우회할 수 있도록 허용하는 메커니즘이다. 웹 페이지에서 외부 도메인(출처)의 자원에 접근할 때, CORS를 통해 서버가 명시적으로 해당 도메인에서의 요청을 허용해야만 브라우저가 그 요청을 수행할 수 있다. 일단은 쉽게 이해하기 위해서, "브라우저에서 현재 보고 있는 화면과 무관한 서버의 파일들을 아무거나 막 열람할 수 없게 해야 하지 않을까?"라는 의문을 가져볼 수 있겠다. 그럼 일단 동일 출처 정책(Same-Origin Policy)가 무엇인지 보자.
동일 출처 정책(Same-Origin Policy)란?
SOP(Same-Origin Policy)는 웹 보안 모델 중 하나로, 한 출처(origin)의 웹 페이지가 다른 출처의 리소스에 임의로 접근하는 것을 방지하는 브라우저 보안 기능이다. 출처는 Scheme(프로토콜), Host(도메인), Port의 조합(우리가 흔히 아는 주소)으로 정의된다. 동일 출처 정책은 악의적인 웹사이트가 사용자의 중요한 정보를 무단으로 도용하거나 조작하는 것을 방지하기 위해 도입되었다. 예를 들어,
- https://luceeverde.tistory.com과 https://luceeverde.tistory.com은 동일 출처
- http://luceeverde.tistory.com과 https://luceeverde.tistory.com은 다른 출처(프로토콜 차이)
- https://luceeverde.tistory.com과 https://tistory.com은 다른 출처(서브도메인 차이)
- https://luceeverde.tistory.com:3000과 https://luceeverde.tistory.com:4000은 다른 출처(포트 차이)
라고 이해할 수 있겠다. 그렇다면 위에서 CORS는 SOP(동일 출처 정책)을 우회할 수 있도록 허용하는 메커니즘이라고 했으니, 왜 우회를 해야하는 상황이 생기는 걸까?
CORS의 필요성
SOP(동일 출처 정책)는 보안 측면에서 매우 중요하지만, 실제 애플리케이션에서는 여러 출처에 걸쳐 데이터를 공유해야 하는 경우가 많다. 예를 들어, 프론트엔드 애플리케이션과 API 서버가 다른 도메인에서 실행되는 경우, 웹 페이지는 API 서버에 요청을 보내 자원을 가져와야 한다. 이때, 동일 출처 정책에 의해 차단될 수 있는데, CORS는 이를 우회하는 방법을 제공한다.
CORS의 작동 방식
CORS는 서버가 클라이언트로부터 요청을 받을 때, 해당 요청을 허용할지 결정하는 방식으로 동작한다. 서버는 브라우저가 요청한 출처(origin)에 대해 응답 헤더를 통해 요청을 허용할지 명시적으로 지정해야 한다.
- 프리플라이트 요청(Preflight Request): 클라이언트가 서버로 특정 조건에 해당하는 요청을 보내기 전에 OPTIONS 메서드를 사용하여 사전 요청(프리플라이트 요청)을 한다. 이를 통해 서버가 해당 요청을 허용하는지 확인한다. 프리플라이트 요청 예시와 응답 예시를 한번 보자.
- 실제 요청: 프리플라이트 요청이 성공하면, 클라이언트는 실제 요청을 서버로 전송할 수 있다.
/*
프리플라이트 요청 예시
OPTIONS /api/data HTTP/1.1
Host: api.example.com
Origin: http://mydomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
프리플라이트 응답 예시
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http://mydomain.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
프리플라이트 요청 성공 이후
실제 요청 예시
POST /api/data HTTP/1.1
Host: api.example.com
Origin: http://mydomain.com
Content-Type: application/json
실제 응답 예시
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://mydomain.com
*/
그런데 이러한 CORS 관련 문제는 프론트 개발을 하는 내가 뭔가 작업을 진행해서 문제를 고치는 영역이 아닌 걸 보면, 서버에서 어떠한 처리를 통해 문제를 해결했다는 것인데, (실제로 프리플라이트 요청을 내가 만들어서 서버로 쏘도록 한 것은 아닌데 CORS 오류 문제가 해결되었다.)
CORS 응답 헤더
CORS 사용 예시 (서버 측 설정)
CORS 관련 문제와 해결 방법
마무리
'🔨 개발 > 🖥️ 웹개발' 카테고리의 다른 글
자바스크립트에서 큐(Queue) 사용하기 (3) | 2024.09.27 |
---|---|
로컬 스토리지(LocalStorage)란 무엇인가?, 어떻게 사용하는가? (1) | 2024.09.19 |
JWT 로그인 인증 방식: Stateful vs Stateless (1) | 2024.09.06 |
메뉴 드롭다운 구현하기 (1) | 2024.09.03 |
textarea의 blur 이벤트와 click 이벤트 발생 순서 문제 (0) | 2024.08.11 |