SOP (Same-Origin Policy)
동일 출처 정책이라고 한다. 말 그대로 같은 출처에서만 리소스를 공유하게 하는 정책이다. 그러나 웹에서 다른 출처에 있는 리소스를 가져와 사용하는 일은 흔한일이라 예외 조항을 두고 허용하는데, 그중 하나가 cors정책을 지킨 리소스 요청이다.
CORS
CORS란, 기존의 동일 출처 정책에 의존하는 응용프로그램의 호환성을 유지하면서, 다른 출처의 자원을 공유할 수 있도록 한다. CORS는 오히려 보안을 지키면서 동시에 교차 출처를 가능하도록 하는 사양이다.
api 주소에서 로컬 주소로 가져오기 위한 엑세스가 cors 정책에 의해 차단되었다는 내용이다.
CORS 접근 제어 시나리오
- 간단한 요청 (simple request)
- 사전 점검 요청(prefilght request)
- 인증정보를 포함한 요청(credential request)
간단한 요청(simple request)
특정 조건을 만족하는 경우에는 허락 없이도 다른 출처에 HTTP 요청을 보낼 수 있다. 이는 요청을 보내면서 해당 요청이 교차 출처인지 확인하는 것이다. 이는 세 가지 조건을 만족해야 요청을 보낼 수 있고, 그렇지 못한 경우 프리플라이트 요청을 먼저 날리고 허락이 되면 본 요청을 보내야 한다.
methiods : get, post, head중 하나
content-type : application/x-www-form-unlencoded, multiplart/form-data, text/plain중 하나
headers: accept, accpet-languate, content-language, content-type 중 하나
cors에서 간단한 요청의 조건을 충족하지 못할 경우, 실제 요청 전에 사전에 허락을 받는 '사전점검요청'에 들어간다. 브라우저는 서버에 요청을 하기전 preflight라는 http 요청을 먼저 전송한다. 사전 점검을 받고나서 요청이 가능함을 확인하고 나면 본요청을 보낸다.
preflight 요청 정보
origin : 요청 출처
access-control-request-method : 실체 요청의 메소드
access-control-request-headers : 실제 요청의 추가 헤더
이렇게 세가지가 프리플라이트 요청 시 헤더에 필요한 것들이다. 브라우저가 내가 요청한 헤더, 메소드를 읽고 자동으로 이렇게 프리플라이트 헤더에 넣어서 요청을 보낸다.
prefilght 응답 정보
access-control-request-origin : 서버 측 허가 출처
access-control-request-method : 서버 측 허가 메서드
access-control-request-headers : 서버 측 허가 헤더
access-control-max-age : 프리플라이트 응답 캐시 시간
preflight 를 처음 보낼때, option이라는 메서드를 보낸 적이 없는데, 왜 백엔드 분이 계속 보냈다고 하는지 이해할 수 없었다. 백엔드 쪽에서 응답 헤더에 access-control-allow-methods에 options 를 추가하여 해결되었다. 만약 이 요청이 거부된다면, 실제 요청이 보내지지 않는다.
인증정보를 포함한 요청
http나 쿠키 등의 인증에 사용되는 요청 헤더가 자동으로 전송되지 않는다. 인증 관련 헤더를 보내는 경우 클라이언트와 서버 측 모두 약속한 듯이 설정을 해줘야 한다. 쿠키나 jwt를 클라이언트에서 자동으로 담아서 보내고 싶을 때, 클라이언트에서는 credential:true 설정을 해 주고, 서버 측에서는 access-control-allow-credential:true로 설정해 줘야 한다.
프리플라이트가 필요한 이유
프리플라이트가 필요한 이유는, cors 문제가 있는지 모르고 있는 서버를 위해서다. 즉, cors에 대한 아무런 설정이 없는 서버에서는 cors에 대한 확인 없이 내가 요청한 정보를 가지고 온다. 브라우저에서는 응답을 확인하고 클라이언트에 대해 교차 출처 리소스 라는 에러를 띄운다. 이미 응답 get, post, delete응답에 대한 cors를 내렸다고 해도, 이미 클라이언트에서 수행할 요청을 행한 상태이기 때문에, 프리플라이트 요청을 먼저 보내서 확인한다.
프리플라이트 요청을 먼저 날린다면, 먼저 클라이언트가 브라우저에 요청을 보내면 브라우저 입장에서는 서버의 응답에 allow-origin 이 없기 때문에, cors에러가 났다고 클라이언트에게 응답을 내려준다. 브라우저가 교차 출처 에러를 낸 시점에 서버는 아무 행동도 하지 않은 상태이다.
cors는 동일 출처 정책과 호환성을 유지하면서 안전성을 유지해 교차 출처 접속을 구현한 사양이다.
- api 서버로의 접근에서 cors 문제가 발생했을 때
해당 api 서버에서 access-control-allow-origin 헤더에 출처를 명시한다. - 외부 api 서버로의 접근에서 cors 문제가 발생했을 때
- 브라우저를 통하지 않고(클라이언트에서 외부 서버로 바로 요청을 하지 않고) 프록시 서버에서 외부 서버로 리소스를 요청한다.
- 프록시 기능을 제공하는 라이브러리를 통해 우회한다.
- 웹 브라우저 실행 옵션이나 플러그인을 통해 동일 출처 정책(sop)을 회피한다.
webpack dev server 로 리버스 프록싱
백엔드에서 access-control-allow-origin 헤더가 세팅되어있더라도, 일반적으로 localhost 같은 범용적인 출처를 넣어주지 않기 때문에 가장 많이 발생한다.
로컬 환경에서 /api로 지삭하는 url로 보내는 요청에 대해 브라우저는 localhost:8080/api 로 요청을 보낸 것으로 알고 있지만, 사실 뒤에서 웹팩이 api/domain.com으로 요청을 프록싱 해주기 때문에 마치, cors 정책을 지킨 것처럼 브라우저를 속이면서도 우리가 원하는 서버와 자유롭게 통신할 수 있다. 즉 프록싱을 통해 cors 정책을 우회할 수 있다.
'프론트엔드 개발자로 일하기' 카테고리의 다른 글
browser rendering (0) | 2024.09.17 |
---|---|
vue, proxy, cors 또 모르면 문신 새기자.. (0) | 2024.09.17 |
이벤트 버블링, 이벤트 캡처링 (0) | 2024.09.17 |
tui-editor 에서 customHTMLSanitizer 커스텀해서 사용하기 (0) | 2024.09.10 |
thymeleaf에서 fragment로 vue 컴포넌트 만들기 (0) | 2024.09.03 |