%EC%A0%95%EC%B1%85_%ED%9E%88%EC%96%B4%EB%A1%9C_%EC%9D%B4%EB%AF%B8%EC%A7%80.jpg)
들어가며
CORS 정책 위배 이슈는 웹 개발자라면 한 번쯤 만나는 문제라고 합니다.
저 역시 최근 ‘Cookie에 저장된 정보를 요청 헤더에 넣어서 전달하는 과정’을 구현하기 위해 테스트 도중 CORS 정책 이슈를 만났습니다. 나중에 CORS 정책 이슈를 만나도 더 유연하게 문제를 해결하기 위해서는 한 번쯤 정리가 필요하다는 생각이 들었습니다. 따라서 이번 글에서는 CORS 정책에 대해 정리하려 합니다.
CORS(교차 출처 리소스 공유) 정책이란?
교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다.
MDN에서는 CORS에 대해서 위와 같이 설명되어 있다. 기본적으로 같은 출처에 있는 리소스에만 접근할 수 있다.(이를 SOP 정책 , 동일 출처 정책이라고 한다.) 다른 출처의 리소스를 이용하기 위해서는 CORS 정책을 준수하는 내용이 응답 헤더에 포함돼야 한다.
💡같은 출처(Origin)란?
-
요청 URL의 scheme, host, port 번호가 모두 같은 URL이다.
-
예를들어 아래 두 URL은 같은 출처로 구분된다.
// URL1http://victor-log.com// URL2http://victor-log.com/posts -
같은 출처에 대한 조금 더 자세한 예시는 MDN 문서에서 확인 가능하다.
SOP정책과 CORS 정책이 필요한 이유?
SOP 정책의 정의에 대해서 MDN는 아래와 같이 정리되어 있다.
동일 출처 정책(same-origin policy)은 어떤 출처에서 불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하는 중요한 보안 방식입니다.
출처가 불분명한 웹 애플리케이션이 제약 없이 서버에 리소스를 요청하고 사용한다면 보안상의 문제가 발생할 여지가 더 많아진다. SOP 정책이 있으면 신뢰되지 않은 출처에서 리소스에 접근하고 이용하는 상황을 어느 정도 예방할 수 있다.
CORS 정책은 출처가 서로 다른 웹 애플리케이션과 서버가 리소스를 주고받을 수 있도록 관련된 내용이 정의된 정책이다. CORS 정책을 준수하는 리소스 요청은 출처가 다르더라도 응답 받은 리소스를 활용할 수 있다.
CORS를 정책을 준수하는 방법
가장 쉬운 해결 방법은 요청에 대한 응답 헤더에 Access-Control-Allow-Origin
key에 *
값을 지정하는 방법이다. 위는 ‘모든 출처에서 해당 리소스의 사용을 허용하겠다’는 의미를 가진다.
json-server를 이용한 예시 코드는 아래와 같다.
server.get("test", (req, res) => {...res.setHeader("Access-Control-Allow-Origin", "*");...});
MDN 문서에 의하면 CORS 정책과 관련해서 세 가지 시나리오가 있는데, 위 해결 방법은 단순 요청 시나리오에 관한 해결 방법이다.
따라서 해당 방법으로 모든 이슈가 해결되는 것은 아니다.
쿠키 전달 시 CORS 정책 위배 이슈
쿠키를 전달하는 요청의 경우 CORS 정책과 관련된 시나리오 중 인증정보를 포함한 요청 시나리오에 해당된다.
- 서버에서 브라우저로 set-cookie 헤더를 전달하는 경우
- 서버에서 전달하는 응답 값의 헤더에
Access-Control-Allow-Credential: true
옵션이 있어야한다.- 해당 옵션에 대한 자세한 설명은 공식 문서에서 확인 가능하다.
브라우저가 Chrome 브라우저인 경우 별도의 cookie 옵션이 필요할 수 있다.
- 서버에서 전달하는 응답 값의 헤더에
- 브라우저에서 저장하고 있는 cookie를 cookie 헤더에 담아 전달하는 경우
- fetch API를 이용해서 요청의 헤더의 쿠키를 보내기 위해서는 별도의 credential 옵션이 필요하다. 관련된 내용은 공식 문서에서 확인 가능하다.
fetch(URL, {credential: 'include' // 또는 'same-origin'});
- 만약 fetch API 이용시
crendential: ‘include'
옵션을 사용했다. 서버의 응답 값의 ``Access-Control-Allow-Origin에는
*(와일드 카드)` 값을 사용할 수 없다. 즉, 명확한 출처를 명시해야한다.
- fetch API를 이용해서 요청의 헤더의 쿠키를 보내기 위해서는 별도의 credential 옵션이 필요하다. 관련된 내용은 공식 문서에서 확인 가능하다.
참고 자료
동일 출처 정책 - MDN
교차 출처 리소스 공유(CORS) - MDN
CORS는 왜 이렇게 우리를 힘들게 하는걸까? - Evan Moon