CORS(Cross Origin Resources Sharing)
cors 발생 상황부터 봅시다
프론트 2명과 백엔드 2명이 같이 프로젝트를 하는 상황입니다.
프론트 서버(react나 vue)와 백엔드 서버(spring)로 나눠 진행하여 서버를 띄웁니다.
프론트(localhost:3000), 백엔드(localhost:8080) 이라고 예를 들어 봅시다.
백엔드에서 api 구현이 마친 뒤 api 문서(swagger)가 나와 프론트에서 요청, 응답 테스트를 진행하려고 합니다.
여기까지 잘 그려지시나요?
이제 프론트에서 브라우저를 통해서 화면을 렌더링하고 백엔드 서버에 데이터를 요청할 것입니다.
이때 원하는 데이터가 전달되지 않고 개발자 모드로 보면 403 cors 에러가 있을 것 입니다.
프론트 분들은 당황해서 백엔드 분들에게 cors 문제가 났어요! 어떡하죠~! 도움을 요청합니다...
결론부터 말하자면 백엔드 분들이 백엔드 서버에서 cors 설정을 통해 cors 문제를 해결해줘야 합니다.
(물론 서버가 어떻게 띄워져 있는지에 따라 추가 설정들이 필요할 수 있습니다. 절대적인 정답은 없어요.)
자, 여기까지 알게되었으면 자바 스프링을 하시는 분들은 스프링 시큐리티 cors 설정을 서치하여 프론트 서버를 등록하러 가시면 됩니다.
이제 왜 cors 가 발생하였는지 이해해봅시다.
CORS(Cross Origin Resources Sharing)란 뭘까요?
cors는 다른 출처에서 보낸 요청을 허용해주면서 자원을 공유하는 메커니즘을 말합니다.
다른 출처? 자원 공유? 가 뭘까요?
cors가 왜 필요한지 살펴보면서 이해해봅시다
CORS가 왜 필요한가요?
브라우저에서는 SOP(Same Origin Policy) 가 디폴트로 설정되어 있어요. 즉, 같은 출처가 보낸 요청이 아니면 브라우저가 이를 체크해서 요청을 막습니다.
하지만 백엔드 서버와 프론트 서버가 나눠져 있어 프론트에서 보낸 요청까지 SOP에 의해 막히면 백과 프론트 사이에 소통이 이루어 질 수 없게 되죠. 이를 허용하기 위해 cors 가 필요한 것입니다!
슬슬 다른 출처, 같은 출처, 자원 공유, SOP 가 뭔지 이해가 되나요?
corss origin이란?
1. 프로토콜 - http, https
2. 도메인 - temp.com, temp2.com
3. 포트 - 3000, 8080
이 중 하나라도 다르면 다른 출처(cross origin)이라고 합니다.
자 이제 처음에 안내했던 예시에서 왜 cors 에러가 발생했는지 대답할 수 있을까요?
잘 이해하셨는지 몇가지 질문을 드려볼게요
1. A서버(localhost:8080)과 B서버(localhost:3000)이 있고 A서버에서 직접 B서버로 요청을 보냈다. cors 에러가 발생할까요?
정답은...! 발생하지 않습니다!!
이유는 cors는 브라우저에서 요청하는 요청에 대해 발생합니다. 따라서 위 질문처럼 서버와 서버사이의 직접 요청에 대해서는 cors가 발생하지 않습니다.
브라우저에서 요청하는 부분을 더 자세히 알아봅시다. 프론트에서 작성한 스크립트 코드를 브라우저가 가지고 있고 그 스크립트를 실행하면서 보내는 요청에 대해서 브라우저가 다른 출처로 요청을 보내는 것을 막는 것입니다. 이제 브라우저가 어떻게 다른 출처로 보내는 요청을 막는지 확인해봅시다.
CORS는 어떻게 동작하나요?
두가지 방법의 절차가 있다. (브라우저가 보내는 요청이에요!)
1. Simple-Request
아래 특정 조건을 만족할때 해당 요청을 보낸다 (preflight보다 간단한 요청)
1) HTTP method가 get, head, post 중 하나
2) 자동 설정 헤더 제외하고 Accept, Accept-Language, Content-Language 만 변경할때
3) Content-Type이 application/x-www-form-urlencoded, multipart/form-data, text/plain 일때
이 요청은 추가적인 확인없이 바로 본 요청을 보낸다. (서버 데이터에 영향을 미치기 힘든 요청이므로 믿고 본 요청을 바로 보낸다)
2. preflight
simple-requeset가 아닌 요청은 preflight방법으로 보내진다.
서버에 예비 요청을 보내서 검증을 먼저 진행한 뒤 본 요청을 보낸다. (본 요청을 보내 이미 서버의 데이터에 영향을 준 뒤 아차차 하고 막아도 이미 늦기 때문에 예비 요청으로 미리 거르는 작업을 하는 것)
# 요청 헤더 목록
Origin
Access-Control-Request-Method
- preflight 요청때 어떤 메소드 형태로 보낼지 서버에게 보냄
Access-Control-Request-Headers
- preflight 요청때 어떤 헤더들로 보낼 것인지 서버에게 보냄
# 응답 헤더 목록
Access-Control-Allow-Origin
- 브라우저가 해당 origin이 자원에 접근할 수 있도록 함 또한 *은 credential이 없는 한 모든 origin을 허용함
Access-Control-Allow-Methods
- preflight에 대한 응답으로 허용된 메서드들을 보냄
Access-Control-Expose-Headers
- 브라우저가 접근할 수 있는 서버 화이트리스트? 헤더 허용
Access-Control-Allow-Headers
- preflight에 대한 응답으로 실제 요청에 대한 허용 헤더들을 나타냄
Access-Control-Max-Age
- 얼마나 오랫동안 preflight에 대한 캐싱이 허용되는지
Access-Control-Allow-Credentials
- true로 되어 있으면 브라우저는 요청에 대한 응답을 노출함
참고
'Computer Science > 네트워크' 카테고리의 다른 글
| [ACL] ACL이 뭔데요? (3) | 2024.04.07 |
|---|---|
| [JWT] - 이론편 (2) | 2024.03.31 |