bovo 프로젝트(독서 기록 공유 프로젝트)를 Netlify로 테스트 배포를 진행한 뒤 CORS를 해결하기 전까지 작동을 해보지 않았다. 중간에 서버에 문제가 생겨 local에서도 작동하지 않게 되면서 배포한 플랫폼은 CORS가 해결되고 작동되나 싶어 확인한 찰나 기존에 보지 못했던 에러를 브라우저 console에서 확인하게 되었다.

일반적으로 CORS에러라면 네트워크 탭에서 다음과 같이 CORS 에러임을 확인할 수 있으나

네트워크 탭에서 전혀 다른 종류의 에러임을 알 수 있다.

과연 Mixed Content 에러란 무엇일까?
웹 페이지에서 보안 연결(HTTPS)을 통해 제공되는 페이지에 비해 보안되지 않은 연결(HTTP)을 통해 로드되는 콘텐츠가 있는 경우 발생한다.
잠시 http와 https에 대해 알아보자면
http(Hypertext Transfer Protocol)
데이터를 암호화하지 않고 평문으로 주고받는다. 즉, 웹 브라우저와 서버 간에 전송되는 모든 정보(로그인 정보, 개인 데이터 등)가 네트워크 상에서 그대로 노출될 수 있다.
https(Hypertext Transfer Protocol Secure)
http에 보안 계층인 SSL/TLS (Secure Sockets Layer/Transport Layer Security) 프로토콜을 추가한 것이다. SSL/TLS는 통신 데이터를 암호화하여 전송한다. 따라서 데이터가 전송되는 동안 가로채이더라도 내용을 알아보기 어렵게 만든다.
따라서 https로 서비스되는 웹 페이지가 http로 API 요청을 보내는 것은, "보안이 보장된 공간에서 보안이 보장되지 않는 데이터를 가져오려고 시도하는 것"으로 간주되어 보안 정책 위반으로 차단되는 것이다.

따라서 화면단의 브라우저 주소가 http로 시작하고 서버의 api 경로가 https로 시작하는 반대의 경우에서는 안전하지 않은 웹페이지에 안전이 보장된 리소스가 로드되는 것이기에 이때는 Mixed Content 에러가 발생하지 않는다.
이것을 우리의 상황에 빗대어 생각해보면 bovo 프로젝트의 경우 Netlify로 화면단을 배포함으로써 https url을 사용하고 있지만, 서버의 경우 http를 사용하고 있어 Mixed Content에러를 발생시키고 있는 것이다. 일반적으로 배포된 이후에 발생되는 에러이다.
이 Mixed Content 에러를 해결하는 방법에는 동작원리에 따라 3가지 방법이 존재한다.
현재 서버가 http로 응답하는 것이 문제라면 백엔드 서버의 응답을 https로 바꾸면 된다. 이 방식이 바로 그런 방식이다. 다만 SSL/TLS 인증서를 적용하는 방법 자체는 현재 무료 서비스인 경우도 있는 것으로 보이나 결국 SSL/TLS 인증서를 도입하기 위해서는 도메인을 구입해야 하므로 현재 우리 팀의 상황상 적절치 않은 것으로 생각됐다.

NginX와 apache 같은 proxy 서버를 앞에 두고 화면단에서 api 요청을 https로 요청 받는 대신 내부적으로 proxy 서버는 실제 spring 서버에 http로 요청을 보내는 방식으로 Mixed Content 에러를 해결할 수 있다. 다만 이 방식을 적용하기 위해서는 NginX나 apache 같은 proxy 서버를 다룰 수 있는 팀원이 필요하다

HTML meta 태그를 사용하여 http api 요청을 자동으로 https 로 변경하여 요청을 보내도록 하는 것이다.
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
단, 한가지 주의할 점은 서버가 http가 아닌 https 요청을 받을 준비가 되어있어야지 가능한 방법이다.
내가 적용한 방식은 2. proxy 서버 적용 방법이다.
bovo 팀에는 NginX나 apache를 다룰 줄 아는 인원은 없으나 Netlify로 화면단을 배포함으로써 해결할 수 있게 된 특수한 방식이다.
우선 Netlify로 배포했단 가정하에 설명하자면
① root directory에 netlify.toml 파일을 생성한다.
반드시 이름을 netlify로 설정해야 Netlify가 해당 이름의 파일을 찾아서 설정들을 읽어들이기 때문에 이름 변경을 하면 안됀다!
② netlify.toml 파일을 다음과 같이 설정한다.
[[redirects]]
from = "/api/*"
to = "주소/:splat"
status = 200
force = true
여기서 잠시 toml 파일의 구성을 살펴보면
from
Netlify로 배포된 프론트엔드 애플리케이션의 도메인으로 들어오는 경로중 /api/ 뒤로 오는 모든 경로의 요청을 가로채겠다는 의미이다.
만일, 추가적인 설정 없이 Netlify로 들어오는 모든 경로의 요청을 가로채고 싶다면 "/api/" 이 아닌 "/" 로 설정해주면 된다.
to
from에 해당하는 요청이 들어왔을 때 Netlify가 이 요청을 실제 백엔드 서버의 http주소인 to에 해당하는 경로로 전달한다.
여기서 :splat이란 from 경로에서 일치하는 나머지 부분을 to 경로의 끝에 붙여주는 플레이스홀더이다.
status=200
클라이언트 요청을 받아서 백엔드 서버로 전달하고, 백엔드 서버의 응답을 다시 클라이언트에게 반환하는 프록시 역할을 한다는 것을 의미한다.
force=true
위 규칙을 강제한다는 의미이다.
③ Netlify 사이트에서 Backend API URL을 기존 주소에서 /api로 변경한다.
(위 toml 파일로 설정했을 경우)
④ Netlify의 재배포를 진행한다.
단 이 Netlify 설정을 통해 Mixed Content 에러를 해결하는 방식은 정석적인 방식이 아니고, 현재 테스트로 배포하여 작동되는지 점검하기 위해 사용한 방식이다.
실제 프로덕션 레벨에서는 proxy 서버를 사용하고, https를 사용하는 것이 보안상 적절하다.
주의 사항
Netlify의 proxy 설정은 http 관련해서는 적용되지만, Websocket의ws와wss관련해서는 지원되지 않으므로 적용되지 않는다.