[ERR_LOG] Vercel 배포 시, Mixed Content 에러 해결

배성규·2023년 8월 25일
2

프로젝트

목록 보기
4/10

1. 문제 인식

로컬에서 구현을 완료하고 버셀에 배포하려는데 아래와 같은 에러가 출력되었다.

문제가 발생한 이유는 아래와 같았다.

  • vercel은 https로 서비스되는 사이트다.
  • 내가 받아오는 API는 http로 받아오고 있었다.
  • 따라서 Mixed Content가 발생하고 있었다.

Mixed content?

  • 초기 HTML이 https연결을 통해 로드되지만 다른 리소스(이미지, 스크립트 등)는 http 연결을 통해 로드될 때 발생.

  • 안전하지 않은 http 프로토콜을 사용하게 되면 전체 페이지의 보안이 약화된다. ==> 공격자가 네트워크 연결을 도청하고 통신을 보거나 수정하는 등의 경로 내 공격에 취약해진다.

2. 접근

해당 문제를 해결하기 위해서는 몇 가지 방법이 있다.

2-1. http로 받아오는 API를 https로 받아오기

  • 메타 태그에 <meta httpEquiv="Content-Security-Policy" content="upgrade-insecure-requests" />를 넣으면 http요청을 https로 바꿔준다고한다.
  • 그러나, 나는 next 13버전을 사용하여 해당 프로젝트를 진행 중이였는데, Metadata를 설정하는 과정에서 http-equiv옵션은 아직 지원하지 않는다고 한다. next docs

사실 위에꺼를 할 필요없이 https API를 받아오면 되는데,
서울 열린 데이터광장에서는 https데이터를 지원하지 않는다.

결론적으로는 첫 번째 방법은 실패

2-2. getServerSideProps

getServerSideProps는 서버에서 렌더링을 하고 브라우저에서는 실행되지 않는다.
해당 방법을 사용하면 서버에서 렌더링하여 브라우저로 쏘기 때문에 백엔드 서버를 사용하는 것과 같은 효과를 볼까 싶어서 사용해보고자 했다.

사용 방법은 아래 코드와 같다.

export const getServerProps = async() => {
 	try{
    	const res = await fetch('api code');
      	if(res.status === 200){
        	const user = await res.json();
          	return {props: {user}}
        }
      	return {props:{user}}
    }catch(err) // code.. 
}

const getUser = ({user}) => {
	const userName = user && user.name;
  	return <p>{userName}</p>
}

그런데 데이터가 다 undefined로 넘어가지는 문제가 발생했다.
예제와 똑같이 테스트를 만들어서 실행해봐도 왜인지 모르겠는데 계속 undefined만 출력이 되었다.
해당 방법은 다음에 사용해보기로 하고 마지막 남은 방법을 사용해보고자 했다.

2-3. rewrites

해당 경로로 요청이 들어오면 다른 대상 경로에 매핑하는 기능이다.
URL 프록시 역할을 하고, 대상 경로를 마스킹하여 사용자가 사이트에서 자신의 위치를 변경하지 않은 것처럼 보이게 한다.

// next.config.js
/** @type {import('next').NextConfig} */

const nextConfig = {
  reactStrictMode: true,
  async rewrites() {
    return [
      {
        source: "/api/dataList", // 요청한 경로 
        destination: `https://jsonplaceholder.typicode.com/users`, // 내가 사용할 경로 
      },
     
    ];
  },
};

module.exports = nextConfig;

처음에는 저 source경로가 라우팅 소스경로인가 싶어서 라우팅 주소를 사용했는데 계속 에러를 뱉어내서 몇 시간을 허비했는데 라우팅 주소가 아닌 내가 요청하는 api경로를 적는 부분이였다.

3. 해결방법

세번째 방법은 rewrites를 사용하여 해결했다.

/** @type {import('next').NextConfig} */

const nextConfig = {
  reactStrictMode: true,
  async rewrites() {
    return [
      {
        source: "/api/parkingList/:start/:end",
        destination: `${process.env.NEXT_PUBLIC_API_URL}/:start/:end`,
      },
    ];
  },
};

module.exports = nextConfig;
 const response = await fetch(`api/parkingList/${startIndex}/${endIndex}`);

위와 같이 fetch를 하면 source부분의 경로에 맞는 경우 내가 호출하고 싶은 API로 재작성하여 호출한다.

뒤에 붙어있는 :start부분은 경로가 일치할 경우를 적은 것이다.

와일드카드 경로로 일치하고 싶으면 /:slug*와 같은 방식으로 적으면 된다.

++ 추가적으로 vercel환경과 local환경을 다르기때문에 환경마다 설정을 어떻게 해줘야하나 싶었는데 다음과 같은 방법으로 해결했다.

//.env
공통으로 사용하는 환경변수 
NEXT_PUBLIC_API_URL = code.. 

//.env.local 
로컬환경에서 실행되는 환경변수 
NEXT_PUBLIC_BASE_URL = http://localhost:3000

//.env.production
NEXT_PUBLIC_BASE_URL = https://parking-good.vercel.app

  • vercel settings - Environment Variables에 들어가면 환경변수를 설정할 수 있는데 Production, Preview, Development 본인이 필요한 조건에 따라 설정하고 등록해두면 로컬에서 실행할 때, 배포환경에서 실행할 때 추가적으로 코드를 지웠다 배포하지 않고 문제없이 같은 결과를 확인할 수 있다.

결과 화면

4. 마무리

Parking-issue1
해당 이슈 해결하려고 3일정도 걸린거 같은데, Next.js를 사용해서 프로젝트는 처음 진행하다 보니까 next.js로 공부하고 해당 이슈도 찾아보고 하면서 시간을 많이 사용한 것 같다.
그래도 직접 해결하려고 찾아보면서 .env관리에 대해서도 공부하고 rewrites와 더불어 redirects도 같이 공부하는 경험이였다.

getServerSideProps는 왜 안되는지 아직 잘 모르겠는데, 추후에 해당 메소드를 또 써야할 때가 올 수 있으므로 프로젝트가 끝난 뒤에 다시 한번 도전해봐야할 것 같다.


참고자료

what-is-mixed-content?
hoontae24
next js docs

profile
FE 유망주🧑‍💻

0개의 댓글