# 1 의문이 발생한 이유

    CORS는 내가 아는 개념 내에서는 '다른 출처(Origin)에서 리소스를 요청할 때 적용되는 보안 정책'이라고 글자로만 알고 있었다. CORS 허용을 백엔드에서 해주고 있기 때문에 깊은 생각 없이 백엔드에서 막아주는 보안 기술이라고 생각했다.

     

     

    따라서 당연하게도 curl을 사용한 팀원이, 왜 curl을 보낸 origin과 백엔드 origin(출처)가 다른데 통신이 되냐는 질문에 대답하지 못 했다.

     

    이후 팀원과 같이 찾아보며 알아간 내용을 정리하려 한다.

    정답보다는 찾아보는 과정에서 알게된 내용들을 순차적으로 작성하였다.

     

    #2 브라우저에서 보낸 request와 curl에서 보낸 request는 무엇이 다른가?

    1. 둘 다 클라이언트에서부터 보낸 request이다.

    브라우저에서 보낸 request에는 CORS가 적용되고, curl에서 보낸 request에는 CORS가 적용되지 않으니 당연히 차이가 있어야 한다고 생각했다.

    결론적으로 말하면 아래와 같은 요소들로 

     

    • User-Agent 헤더
    • Origin, Referer 등의 브라우저 전용 헤더
    • 쿠키/세션 등 인증 정보
    • 기타 요청 구조(폼데이터/JSON/멀티파트 등)나 커스텀 헤더 차이

     

    구분한다.

    그러나 이러한 헤더는 얼마든지 조작할 수 있는 요소 아닌가.

    뭐야, 그럼?

    하나는 보안 정책이 적용되고, 다른 하나는 적용되지 않는데 서로 구분하지 못하게 만들 방법이 있다면 CORS 정책은 무슨 소용이지?

     

    #3 그런 상황에서는 소용없는게 당연하다. 하지만 CORS는 '브라우저'가 주체가 되는 보안 정책이다.

    일단 통신 초반 과정에서는 (DNS 조회와 TCP/SSL 연결) curl과 브라우저 통신 사이에 차이점이 없다.

    1. 클라이언트(브라우저/Postman)가 해당 서버의 도메인(예: api.example.com) IP 주소를 DNS를 통해 조회한다.
    2. IP 주소를 확인한 뒤, TCP 연결을 맺고, HTTPS라면 SSL/TLS 핸드셰이크도 진행한다.
    3. 연결이 성공하면, 클라이언트는 HTTP 프로토콜을 통해 요청을 전송한다.
    브라우저 vs Postman 모두 이 단계에서 큰 차이는 없다.

     

    그러나

    브라우저(프론트엔드)
    CORS 정책상, 브라우저에서 Cross-Origin 요청을 보낼 때는 Origin: http://localhost:3000 등의 헤더가 자동으로 붙는다.

     

    즉, 브라우저 환경에서 주고 받는 통신에서 브라우저가 강제로 자신을 통해 나가는 통신에 헤더를 붙혀서 백엔드로 보내게 한다면?

    브라우저에서부터 나가는 통신은 꼼짝없이 헤더를 붙이고 나갈 수 밖에 없다는 것이다. 즉, 브라우저가 임의로 우회할 수 없다.

     

    그렇다면 왜 브라우저 환경에서만 이러한 보호가 필요할까?

     

    #4 브라우저의 Storage에 여러 출처에서의 정보를 함께 저장하기 때문

    당연히 스레드간 정보를 공유를 차단해두었지만,

    curl 등과 다르게 브라우저는 여러 출처의 정보를 한 곳에 모아둘 수밖에 없고 여기서 보안 위험이 생길 수 있다.

     

    따라서 이 정보들이 탈취 되는 것을 막기 위한 기술인 것.

     

    하지만 여기서 CORS를 이해하기 위한 진짜 핵심은,

    탈취된 정보들은 그 자체로는 쓸모 없음을 가정하는 것이다!

    나는 브라우저에서 정보가 탈취된 순간, 어디든 악성 FE에서 악성 BE로 정보를 보내면 끝 아닌가? 정보가 유출 되었는데? 이제 CORS가 어떻게 보호하지? 라고 생각했다.

     

    하지만 브라우저에서 탈취한 정보들은 암호화된 정보, 암호화된 토큰 등 그 자체로는 쓸모가 없고 '이를 다시 정상 백엔드'에 보냈을 때 가치가 발생하는 정보들이라는 것!

     

    따라서 최종적으로 CORS가 보호하는 건 브라우저 환경 내에서 악성 클라이언트에서 탈취된 정보가,

    다른 출처로부터 왔을 때 방어해주는 것!

    #5 따라서 최종적으로 CORS가 보호 과정은? 

    브라우저에서 백엔드로 요청을 보내기 전에 먼저 보내보는 pre-flight 기술이던가,

    그냥 요청을 보낸다던가.

    어쨋든 이렇게 클라이언트로부터 날아간 정보는 백엔드가 미리 설정해둔 origin이라면

    CORS 헤더를 달아서 브라우저로 respense를 날려준다.

     

    그럼 '브라우저'가 이 데이터를 보여줄지에 대한 여부를 판단해서, CORS 헤더가 적절하면 브라우저에 띄워주고,

    아니면 통신을 쳐내는 것이다.

    즉! CORS는 어디까지나 “응답 열람에 대한 브라우저 측 제약”

    이므로, 사실 DB를 조작하는 요청은 방어할 수 없다!

    CORS는 브라우저를 통해 크로스 도메인 응답을 읽을 수 있는지 없는지를 통제하는 메커니즘이다

     

    #6 Nginx 는 그럼 어떤 기술이길래 CORS 설정을 안 해도 되게 할까?

    FE와 BE는 하나의 Nginx 환경 안에 같이 존재한다.

    따라서 이들은 동일 출처이기 때문에

     

    클라이언트 요청이 Nginx를 거쳐 백엔드로 전달되고.
    Nginx가 Access-Control-Allow-Origin 등의 CORS 헤더를 백엔드의 응답(response)에 추가해준다.


    클라이언트는 Nginx에서 반환한 응답을 받으며, 브라우저는 CORS 허용 여부를 Nginx의 헤더로 판단하게 되는 것이다.

     

     

    • 네이버 블러그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기