출처
참고한 글
https://hannut91.github.io/blogs/infra/cors
읽으면 좋을 것 같은 글
https://docs.tosspayments.com/resources/glossary/cors#%EC%84%9C%EB%B2%84%EC%97%90%EC%84%9C-access-control-allow-origin-%EC%9D%91%EB%8B%B5-%ED%97%A4%EB%8D%94-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0
CORS가 뭐냐면
- Cross-Origin Resource Sharing
- origin은 '기원', '근원', '출신' 등의 의미보다는 '출처'를 의미한다.
- 그래서 요약하면 '교차 출처 자원 공유'인데, 교차되는 출처 간의 자원 공유...가 뭘까?
Cross-Origin
cross-origin이란 다음 중 한 가지라도 다른 경우를 의미한다.
- 프로토콜이 다른 경우
- 도메인이 다른 경우
- domain.com과 other-domain.com은 다르다.
- 포트 번호
그래서 Tomcat 기본 포트인 8080을 사용하는 백엔드에서 3000 또는 5173 포트를 따로 허용해줘야 하는 것이다.
도대체 이 귀찮은 게 왜 필요한가?
CORS가 없다면
- 다른 웹 서버에서 나의 WAS에게 요청할 수 있게 되고, 나는 누군지도 모르는 사람에게 내가 가진 데이터를 주게 된다.
- 즉 백엔드 서버 입장에서는 나에게 요청할 수 있는 사람을 제한할 필요가 있다.
어떻게 동작하냐면
Simple request인 경우
- 서버로 요청한다.
- 서버의 응답이 왔다면
- 브라우저가 요청한 Origin과 응답한
Access-Control-Request-Headers header
의 값을 비교한다.
- 유효한 요청이라면 리소스를 응답한다.
- 유효하지 않은 요청이라면 브라우저에서 이를 막고 에러가 발생한다.
Simple request
- HTTP method가
GET
, HEAD
. POST
중 하나다.
- 자동으로 설정되는 header는 제외한다.
- 설정할 수 있는 header인
Accept
, Accept-Language
, Content-Language
만 변경한다.
Content-Type
이 다음 중 하나다.
application/x-www-form-urlencoded
multipart/form-data
text/plain
위의 4가지 조건을 모두 만족하면 Simple request고, 이런 요청은 추가적인 확인 절차 없이 바로 본 요청을 보낸다.
preflight request인 경우
Origin
헤더에 현재 요청 중인 origin을 설정한다.
Access-Control-Request-Method
헤더에 내가 요청하는 HTTP method와 Access-Control-Request-Headers
요청 시 사용할 헤더를 OPTIONS
메서드로 서버로 요청한다.
- 브라우저는 서버에서 응답한 header를 보고 유효한 요청인지 확인한다.
- 유효하지 않은 요청이라면 요청은 중단되고 에러가 발생한다.
- 유효한 요청이라면 원래 요청으로 보내려던 요청을 다시 요청하여 리소스를 응답받는다.
preflight request
- Simple request가 아닌 모든 cross-origin 요청은 모두 preflight 요청을 먼저 보낸다.
- 실제 요청을 보내는 것이 안전한지 확인하기 위한 요청
OPTIONS
메서드를 사용해 cross-origin
HTTP 요청을 보낸다.
- 이렇게 하는 이유는 사용자 데이터에 영향을 미칠 수 있으므로 미리 확인하기 위함이다.
- 즉 실제 요청을 보내도 괜찮은지 '사전 비행'을 해보는 것이다.
Origin
Access-Control-Request-Method
- preflight 요청에서 쓰인다.
- 실제 요청에서 어떤 method를 쓸지 서버에게 알린다.
Access-Control-Request-Headers
- preflight 요청에서 쓰인다.
- 실제 요청에서 어떤 header를 쓸지 서버에게 알린다.
응답 헤더 목록
Access-Control-Allow-Origin
- 브라우저에게 접근 가능한 origin을 명시한다.
*
은 credentials를 요구하지 않는 요청에 한해 모든 origin에서의 접근을 허용한다(wildcard).
Access-Control-Expose-Headers
- 브라우저가 액세스할 수 있는 서버 헤더를 허용한다(whitelist).
Access-Control-Max-Age
- preflight 요청이 얼마나 오래 cache에 남아있을 수 있는지를 나타낸다.
Access-Control-Allow-Credentials
- Credentials를 요구하는 요청에 대해 요청에 대한 응답의 노출 가능 여부를 나타낸다.
- preflight 요청에 대한 응답의 일부로 사용되는 경우 실제 credential을 사용하여 실제 요청을 수행할 수 있는지를 나타낸다.
- 간단한 GET 요청의 preflight 요청을 하지 않으므로 고려할 사항이 있다.
- Credentials를 요구하는 요청 시 있는 리소스 요청 시 header가 리소스와 함께 반환되지 않으면 브라우저에서 응답을 무시하고 web contents로 반환하지 않는다.
Access-Control-Allow-Methods
- preflight 요청에 대한 대한 응답으로 허용되는 메서드들을 나타낸다.
Access-Control-Allow-Headers
- preflight 요청에 대한 대한 응답으로 실제 요청 시 사용할 수 있는 HTTP header를 나타낸다.