hayu's 개발 일지

[WIL]240317 CORS & 주특기 프로젝트 회고 본문

항해99/회고

[WIL]240317 CORS & 주특기 프로젝트 회고

hayu00 2024. 3. 17. 11:11

CORS란?

  • CORS(Cross-Origin Resource Sharing)는 출처가 다른 자원들을 공유한다는 뜻으로, 한 출처에 있는 자원에서 다른 출처에 있는 자원에 접근하도록 하는 개념이다.(다른 출처의 리소스 공유에 대한 허용, 비허용 정책이다.)
  • 교차되는 자원들의 공유라는 뜻도 있다. 다른 출처에 있는 자원을 요청한다고 하면, 이를 교차 출처 요청이라고 부른다.
  • HTTP 요청은 기본적으로 교차 출처 HTTP( Cross-Site HTTP Requests) 가 가능하다. 교차 출처 HTTP는 프로토콜, 호스트명, 포트가 같아야한다. 그러나 Front 와 Back 사이에 도메인이 달라지는 경우가 많은데 이 경우에 CORS 허용 정책이 필요하다.

다른 출처 요청

  • <img>, <script>, <video>, <audio> 등이 웹에 등장하면서 페이지 로딩 후 브라우저에서 이런 자원들을 가져올 수 있게 되었다. 동일 출처(Same-origin), 다른 출처(Cross Origin) 모두 호출이 가능하게 되었다.

출처

  • 교차 출처 HTTP에서 출처는 무엇일까?
  • 프로토콜: http, https
  • Host: 사이트 도메인
  • Port: 포트번호
  • Path: 사이트 내부 경로
  • Query String: 요청의 key와 value값
  • Fragment: 해시 태그
  • 프로토콜(Protoco), 호스트(Host), 포트(Port)를 합친 URL을 출처(Origin)라 한다. 그리고 이 세가지가 같으면 통일 출처(Origin)라고 한다.

동일 출처 정책 (Same-Origin Policy)

  • SOP(Same Origin Policy) 정책은 단어 그대로 동일한 출처에 대한 정책을 말한다. 그리고 SOP 정책은 동일한 출처에만 리소스를 공유할 수 있다. 라는 법률을 가진다.
  • 동일 출처(Same - Origin) 서버에 있는 리소스는 자유롭게 가져올 수 있지만, 다른 출처(Cross - Origin) 서버에 있는 이미지나 유뷰브 영상 같은 리소스는 상호작용이 불가능하다.

동일 출처 정책의 장점

  • 동일 출처 정책은 CSRF(Cross-Site Request Forgery)나 XSS(Cross-Site Scripting) 등의 보안 취약점을 노린 공격을 방어할 수 있습니다. 하지만 외부 리소스를 참고하는 것은 필요하기 때문에 외부 리소스를 가져올 수 있는 방법이 존재해야 한다.
  • 외부 리소스를 사용하기 위한 SOP의 예외 조항이 CORS이다.

동일 출처 예시

  • https://www.domain.com:2000의 예시
https://www.domain.com:2000/about 프로토콜, 호스트, 포트 번호가 동일하다.
https://www.domain.com:2000/about?username=yuha 프로토콜, 호스트, 포트 번호가 동일하고, Path부터 다르므로 동일 출처이다.

 

다른 출처 예시

  • https://www.domain.com:2000의 예시
https://www.domain.com:2000 프로토콜이 다르다.
https://www.another.co.kr:2000 호스트가 다르다.
https://www.domain.com:3000 포트가 다르다.

 

다른 출처 요청일 경우, CORS 정책에 준수하여 요청해야만 정상적으로 응답을 받는다.

CORS 작동 방식

예비 요청(Preflight Request)

https://beomy.github.io/tech/browser/cors/#cors-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95

  • 예비 요청을 보내 서버와 잘 통신되는지 확인한 후 본 요청을 보낸다.
  • 예비 요청의 역할은 본 요청을 보내기 전에 브라우저 스스로 안전한 요청인지 확인하는 것이다.
  • 브라우저가 예비 요청을 보내는 것을 Preflight라고 부르며 예비 요청의 HTTP 메서드를 GET, POST가 아닌 OPTIONS라는 요청을 보낸다.
  • 단점: 실제 요청에 걸리는 시간이 늘어나게 되어 어플리케이션 성능에 영향을 미친다.

단순 요청(Simple Request)

https://beomy.github.io/tech/browser/cors/#cors-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95

  • 예비 요청을 생략하고 바로 서버에 직행으로 본 요청을 보낸 후, 서버가 이에 대한 응단의 헤더에 Access-Control-Allow-Origin 헤더를 보내주면 브라우저가 CORS정책 위반 여부를 검사하는 방식이다.
  • 단순 요청은 특정 조건을 만족하는 경우에만 가능하다.
  1. 요청의 메서드는 GET, HEAD, POST 중 하나여야 한다.
  2. Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width 헤더일 경우에만 적용된다.
  3. Content-Type 헤더는 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나여야 한다.
  • 위 조건을 모두 만족하여 단순 요청이 일어나는 경우는 드물다. 2번 조건은 사용자 인증에 사용되는 Authorization 헤더도 포함되지 않아 까다로운 조건이며, 3번 조건은 많은 REST API들이 Content-Type으로 application/json을 사용하기 때문이다.

CORS 해결 방법

프록시 사이트 이용

  • 프록시(Proxy)는 클라이언트와 서버 사이의 데이터를 전달해주는 서버이다.
  • 프론트에서 직접 서버에 리소스를 요청했는데 서버에서 따로 설정을 안해서 CORS 에러가 뜬다면 프록시를 이용하여 요청을 하면 된다.
  • 그러나 무료 프록시 서버 대여 서비스는 악용 사례 때문에 api 요청 횟수 제한을 두어 실전에서는 사용하기 힘들다.

Access-Control-Allow-Origin 헤더

  • 직접 서버에서 HTTP 헤더 설정을 통해 출처를 허용하게 설정하는 방법이다.
  • 가장 많이 사용하는 방법으로 각 서버의 문법에 맞게 HTTP 헤더를 추가하면 된다.
// 헤더에 작성된 출처만 브라우저가 리소스를 접근할 수 있도록 허용함.
// * 이면 모든 곳에 공개되어 있음을 의미한다. 
Access-Control-Allow-Origin : <https://naver.com>

// 리소스 접근을 허용하는 HTTP 메서드를 지정해 주는 헤더
Access-Control-Request-Methods : GET, POST, PUT, DELETE

// 요청을 허용하는 해더.
Access-Control-Allow-Headers : Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization

// 클라이언트에서 preflight 의 요청 결과를 저장할 기간을 지정
// 60초 동안 preflight 요청을 캐시하는 설정으로, 첫 요청 이후 60초 동안은 OPTIONS 메소드를 사용하는 예비 요청을 보내지 않는다.
Access-Control-Max-Age : 60

// 클라이언트 요청이 쿠키를 통해서 자격 증명을 해야 하는 경우에 true. 
// 자바스크립트 요청에서 credentials가 include일 때 요청에 대한 응답을 할 수 있는지를 나타낸다.
Access-Control-Allow-Credentials : true

// 기본적으로 브라우저에게 노출이 되지 않지만, 브라우저 측에서 접근할 수 있게 허용해주는 헤더를 지정
Access-Control-Expose-Headers : Content-Length

 

참고 자료

우리조 이번주도 고생했다..ㅜㅜ

이번주 배운 내용

    • 이번주는 프로젝트를 진행했다. 저번 주 spring 에 대한 내용을 배우고 프로젝트를 진행했는데 이번 주는 그것을 바탕으로 프론트엔드팀과 프로젝트를 진행했다.

새로 알게된 점

    • CORS에 대해 알게되었다. 아직은 어려운 개념이지만 프로젝트를 하면서 공부하니 조금은 알 것 같았다. 
    • AWS 배포에 대해서도 알게되었다. 처음에는 버벅거리고 어려웠는데 지금은 조금씩 할 수 있게 되었다.

어려웠던 점

    • CORS도 어려웠지만 AWS 배포가 너무 어려웠다. 2024년 2월부터 바뀐 부분으로 요금이 과금되었다. 그런데도 지금까지 HTTPS 배포는 성공하지 못했다. 추후 도전할 예정이다.

아쉬웠던 점

    • CORS 문제가 프로젝트에 나타나면서 공부하는 부분은 좋았지만, 이 문제를 해결하는 담당이 아니었다. 그래서 조금은 이해가 힘들었던 점이 아쉬웠다.

회고

    • 코드를 이해하면서 조금씩 코드를 짤 수 있다는 자신감이 생겼다. 물론 다른 사람들은 이미 다 잘하시지만... 그래도 나 하나를 놓고 봤을 때는 오늘이 내가 가장 잘하는 날이 아닐까.
    • 프로젝트를 진행하면서 프론테엔드와 협업하는 것을 공부했다. 어떤 부분을 신경써야 하는지, 그리고 협업 시작할 때 그라운드 룰이나 와이어 프레임, 커밋 컨벤션, 깃 플로우 컨벤션까지 중요한 약속이라는 것을 알게 되었다.
    • spring으로 프로젝트를 진행할 때는 코드나 DB부분에 신경을 많이 쓴 것 같다. 그런데 프론트엔드와 협업하면서 서로 입장이 다를 수 있구나를 생각했다.(ex. 로그인 성공 시 반환되는 값을 list로 넣어주었는데 객체로 넣어달라는 요구사항이 있었다.)