api 서버와 데이터베이스를 개발과 실제 프로덕션 환경에 따라 나누게 되면서, 클라이언트에서도 환경변수 분리가 필요했다.
예전에 회사에서 dotenv-cli
라이브러리를 통해 분리해본 적이 있었으나, 이번에는 cross-env
라이브러리와 vite 공식문서를 참고해 분리해 보았다.
cross-env
설치기존 우리 프로젝트는 .env
파일 하나로 환경변수가 관리되고 있었지만, 분리를 위해 env 파일을 나눠 주었다.
.env.local
: 로컬 개발 환경.env.dev
: 개발 환경.env.production
: 실제 프로덕션 환경windows와 unix 운영체제 (max, linux)는 환경변수 설정하는 방법이 달라 맥에서는 동작하지만 윈도우에서는 동작하지 않을 수 있다. 이러한 호환성 문제를 해결해주는 cross-env
라이브러리를 설치한다.
npm install --save-dev cross-env
https://www.npmjs.com/package/cross-env
이런식으로 각 env 파일에 배포 환경에 따른 변수를 작성해준다.
참고로 vite를 사용할 경우, 앞에 VITE_
를 꼭 붙여주어야 한다.
ex : VITE_SERVER_HOST=xxx.xxx
# .env.local
VITE_SERVER_HOST=localhost:5432/mydb
API_KEY=local-api-key
# .env.dev
VITE_SERVER_HOST=dev-db:5432/mydb
API_KEY=dev-api-key
# .env.production
VITE_SERVER_HOST=prod-db:5432/mydb
API_KEY=prod-api-key
Vite 공식문서를 참고해 로컬, dev, prod를 구분해보자.
기존 커맨드
"scripts": {
"dev": "vite --host",
"build": "tsc -b && vite build",
"preview": "vite preview"
},
production 환경으로 로컬에서 테스트 해보고 싶을 경우를 대비해서 start:pro
를 추가해 주었는데,
이때 React에서 프로덕션 환경으로 실행했을 때에 대한 에러가 났다.
찾아보니 vite --host
커맨드와 함께 --mode production
으로 실행시키면 에러가 나고, 무조건 프로덕션으로 빌드한 파일 을 실행시켜야만 에러가 사라지는것을 확인할 수 있었다.
그래서 프로덕션 빌드가 이루어진 뒤, vite preview
라는 빌드파일을 미리 볼 수 있는 커맨드를 실행해서 로컬에서 실행시킬수 있도록 만들어 주었다.
(그냥 로컬에서 프로덕션으로 빌드한 뒤 pnpm run preview
해도 결과는 같다.)
맥에서는 문제가 없었지만 윈도우에서는
NODE_ENV
은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는 배치 파일이 아닙니다. 라는 에러가 난다. 그래서cross-env
를 앞에 붙여주면 해결할 수 있다.
변경 커맨드
"scripts": {
"start:local": "cross-env NODE_ENV=.env.local vite --host --mode development",
"start:dev": "cross-env NODE_ENV=development vite --host --mode development",
"start:pro": "tsc -b && cross-env NODE_ENV=production vite build --mode production && vite preview",
"build:dev": "tsc -b && cross-env NODE_ENV=development vite build --mode development",
"build:pro": "tsc -b && cross-env NODE_ENV=production vite build --mode production",
},
필수는 아니지만, 간혹 오타나 참조 에러 등 여러 케이스로 인해 undefined
를 반환하는 경우가 있으니 나는 이런식으로 log를 찍어서 실행환경마다 제대로 변경되는지 테스트했다.
console.log('host :', import.meta.env.VITE_SERVER_HOST);
console.log('mode :', import.meta.env.MODE);