개발 정보

[Tech] CORS 란? - Cross origin resource sharing

Razelo 2023. 1. 1. 16:31

주말이라 블로그를 탐방하면서 백엔드 관련 기술 질문을 보고 있었는데 CORS에 대한 정확한 개념을 알고 있는지 의문이 들었다. 

 

CORS가 다른 도메인의 자원을 요청했을때 거부 당하는 개념이라고 알고 있는데 추가적인 내용은 알지 못했다. 

 

다행히도 우테코에 CORS에 대한 굉장히 좋은 자료가 올라와있었다. 

 

관련 자료들을 보고 요약하고 정리한 내용을 간단하게 써보고자 한다. 

 


Origin이란? 

url의 Protocol, Host, Port를 통해서 같은 출처인지 판단할 수 있다. 

 

SOP란? 

same origin policy의 약어이다. 

다른 출처의 리소스를 사용하는 것에 제한하는 보안 방식이다. 

 

왜 SOP을 사용해야 할까? 

해커가 링크를 담은 메일을 보낸다. 

클릭을 한 곳에 가면 해커가 만든 주소로 간다.

이때 해커는 스크립트로 침투할 수 있다.

선량한 사용자의 인증 토큰을 이용하는 것이다.  

그렇기 때문에 안전한 사이트에선 반드시 origin을 확인하는 것이다.

다른 출처라고 판단된다면 즉 cross origin이라고 판단되면 sop 원칙에 위배되어서 요청을 거부하는 것이다. 

 

그런데 다른 출처의 리소스가 정말 필요한 상황이라면 어떻게 해야할까? 

이 상황에 필요한 것이 CORS이다. 

cross origin resource sharing이다. 즉 다른 출처의 자원을 공유하는 것이다. 

cors는 추가 http 헤더를 사용해서 한 출처에서 실행 중인 

웹 어플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제다. 

 

CORS 접근제어 시나리오 

1. 단순 요청 - simple request

2. 프리플라이트 요청 - preflight request

3. 인증 정보 포함 요청 - credentialed request

 

preflight이란 무엇일까?

사전 확인 작업이다. 

options 메서드를 통해 다른 도메인의 리소스에 요청이 가능한 지 확인하는 작업이다. 

요청 보내도 되는지 미리 서버에 물어보는 거다. 

 

참고로 위에서 preflight로 미리 확인했는데 거부 당하면 그 다음 단계인 actual request는 진행하지 않는다.  

 

Preflight request 

- Origin: 요청 출처

- Access-Control-Request-Method: 실제 요청의 메서드 

- Access-Control-Request-Headers: 실제 요청의 추가 헤더 

 

Preflight response 

- Access-Control-Allow-Origin: 서버 측 허가 출처 

- Access-Control-Allow-Methods: 서버 측 허가 메서드 

- Access-Control-Allow-Headers: 서버 측 허가 헤더 

- Access-Control-Max-Age: Preflight 응답 캐시 기간 

 

Preflight response가 가져야 하는 특징 

응답 코드는 200대여야 한다.

응답 바디는 비워두는게 좋다. 

 

Simple request란 무엇일까? 

preflight 요청 없이 바로 요청을 날린다.

 

아래 조건이 모두 만족되야 한다.  

- GET, POST, HEAD 메서드 중 하나여야 한다.

- Content-Type

    a. application/x-www-form-urlencoded

    b. multipart/form-data

    c. text/plain

- 헤더는 Accept, Accept-Language, Content-Language, Content-Type만 허용됨.  

 

 

 

그런데 왜 굳이 Preflight가 필요할까? 그냥 simple request쓰면 안되나?

CORS를 모르는 서버를 위해서다. 

 

아래 그림을 보자. SERVER는 CORS를 모른다. 

 

만약 위 SERVER에서 do something 즉 뭔가를 하긴 했는데 나중에 CORS 오류라고 말하면 돌이킬 수 없다. 또한 이미 특정 action을 진행한 뒤인데 그 행동을 하고나서 CORS에러라고 말하는 것은 맞지 않다. 

그러니 preflight 요청이 필요한거다. 

 

그래서 아래처럼 Preflight 요청이 필요한 것이다. 

 

위처럼 동작하면 서버는 안전하게 지켜진다. 아무런 action도 하지 않았기 때문이다. 

 

 

Credentialed Request는 뭘까?

인증 관련 헤더를 포함할 때 사용하는 요청이다. 

 

클라이언트 측

credentials: indclude

 

서버측

Access-Control-Allow-Credentials: true

(Access-Control-Allow-Origin: *은 안됀다. 특정하게 명시를 해줘야한다.)

 

CORS 해결하기

1. 프론트 프록시 서버 설정 (개발 환경)

2. 직접 헤더에 설정하기 

3. 스프링 부트를 이용하기 (@CrossOrigin 사용하기)

 

아래 처럼 Front Server를 이용할 수 있다. 

프론트 서버한테 요청을 보내는데 그걸 요청을 살짝만 바꾸는 것이다. 

그러면 브라우저 입장에서는 CORS 이슈랑은 상관없어지는 것이다. (일종의 눈속임인가)

 

스프링부트라면 @CrossOrigin 을 설정해주면 해결 가능하다.

origins 를 설정해줘도 좋다.

 

멱등성이란?

동일한 요청을 한 번 보내는 것과 여러 번 연속으로 보내는 것이 같은 효과를 지니고, 서버의 상태도 동일하게 남을 때, 해당 HTTP 메서드가 멱등성을 가졌다고 말한다. 


아래 영상과 블로그에서 많은 도움을 받았습니다. 이미지는 영상에서 얻었습니다. 

 

좋은 정보 감사합니다. 

 

https://xiubindev.tistory.com/115

 

https://www.youtube.com/watch?v=-2TgkKYmJt4 

 

반응형