CORS 정책 관련 참고글
https://evan-moon.github.io/2020/05/21/about-cors/
대충 요약하면..
- 기본적으로 SOP(Same-Origin-Policy)라는 '같은 출처에서만 리소스를 공유할 수 있다는 정책이 있음.
- 여기서의 '출처'는 'Scheme', 'Host', 'Port' 세 가지가 동일하다면 같은 출처로 봄. 더 자세한 내용은 상기 링크 참조
- 그러나 현실적으로 서로 다른 출처에서 리소스를 공유해야할 필요성이 큼.
- 때문에 SOP에 예외사항을 둔다. CORS라는 정책을 만족한다면 다른 출처라도 리소스를 공유할 수 있도록 함
- 다만, 출처를 비교하는 로직이 브라우저측에 있다.
- 때문에 서버끼리 통신을 할 때는 CORS 정책이 적용되지 않는다. CORS 때문에 에러가 발생했어도 서버 쪽에는 정상 응답 로그가 남기에, 에러를 찾기 어려워질 수 있다.
다른 출처를 가진 리소스 사용 구조
- 웹 클라이언트 어플리케이션이 HTTP 프로토콜을 통해 리소스를 요청하는데, 이때 요청하는 출처를 담아서 보낸다.
- 그러면 서버는 이 요청에 대해 '우리 리소스에 접근해도 되는 출처'라는 인증 표시를 'Access-Allow_Origin'이라는 값에 담아주고 다시 브라우저로 보낸다.
- 브라우저측에서는 자신이 보냈던 요청 출처와 서버가 보내준 인증을 비교한 후 유효한 응답인지 결정한다.
기본 구조는 이렇지만 CORS 동작 방식은 세 가지의 시나리오에 따라 변경된다.
Preflight Request
- 브라우저가 본 요청을 보내기 전에 예비 요청을 보냄. 이 예비 요청을 Preflight라 칭한다.
- 이 예비 요청의 의의는 이 요청이 안전한 것이지 확인하는 용도이다.
Simple Request
- 예비 요청 없이 바로 본 요청.
- 특정 조건을 만족할 때만 사용 가능.
- 조건이 까다롭기에 잘 사용되지 않는다.
Credentialed Request
- 인증된 요청을 사용하는 방법.
- 다른 출처 간 통신에서 보다 보안을 강화하고 싶을 때 사용하는 방법.
- 기본적으로 브라우저에서 제공하는 비동기 리소스 요청 API인 XMLHttpRequest나 fetch API는 별도의 옵션 없이 브라우저의 쿠키 정보나 인증과 관련된 헤더를 함부로 요청에 담지 않는다. 이때 요청에 인증관 관련된 정보를 담을 수 있게 해주는 옵션이 credentials 옵션이다.
- 여기서의 3가지 옵션 :
- same-origin : 같은 출처 간 요청에만 인증 정보를 담을 수 있다
- include : 모든 요청에 인증 정보를 담을 수 있다
- omit : 모든 요청에 인증 정보를 담지 않는다
만약 same-origin이나 include 같은 옵션을 사용한다면, 브라우저는 다른 출처의 리소스를 요청할 때 좀 더 빡빡한 검사 조건을 추가한다.
Access-Control-Allow-Origin 값으로 *를 설정한다면 다른 출처에서 리소스를 요청할 때 CORS 정책 위반으로 인한 제약을 받지 않는다.
그래서 localhost와 같은 로컬 개발 환경에서도 fetch를 사용하여 마음대로 리소스를 요청하고 받아올 수 있다.
크롬 브라우저에서의 credentials 기본 값은 same-origin이기에 Access-Control-Allow-Origin 값이 *이라면 항상 요청이 안전하다고 판단내린다.
반면, credentials값에 include를 넣는다면, Access-Control-Allow-Origin 값으로 *가 들어있을 때 브라우저는 '인증 모드가 include인데 너는 왜 Access-Control-Allow-Origin 값에 *를 넣냐'라고 에러 메시지를 낸다.
이처럼 요청에 인증 정보가 담겨있는 상태에서 다른 출처의 리소스를 요청하면 브라우저는 CORS 정책 위반 여부를 검사하는 룰에 다음 두 가지를 추가하게 된다.
- Access-Control-Allow-Origin 에는 *를 사용할 수 없고, 명시적은 URL이어야 한다.
- 응답 헤더에는 반드시 Access-Control-Allow-Credentials: true가 존재해야한다.
CORS를 해결할 방법..
- Access-Control-Allow-Origin 값 세팅하기
Access-Control-Allow-Origin : https://~~와 같이 출처를 명시해준다(미들웨어 활용 추천).
- Webpack Dev Server로 리버스 프록싱하기
프록시 기능이 포함된 라이브러리를 이용하여 브라우저로 하여금 같은 출처에서 리소스를 요청한다고 속이는 방법(로컬환경 한정해서..).
이 방법은 prod 환경에서 client-server 간의 출처가 같은 경우에 사용하는 것이 좋다.
댓글을 작성해보세요.