Dotenv와 Webpack DefinePlugin을 활용하여 개발/배포 환경의 환경 변수 설정을 분리하였습니다.
들어가며
웹 개발 환경에서는 여러 가지 환경 변수(상수)를 선언하여 개발을 진행할 환경이 종종 생깁니다.
Dotenv를 사용하여 환경 변수를 선언할 수 있는 환경을 구성합니다.
보통 웹 페이지 개발을 할 때 개발 서버에서 개발과 테스트를 마친 뒤 개발 서버 배포 후 라이브 서버에 배포하는 프로세스로 일을 진행하게 되는데 개발 서버의 상수 변수와 배포 서버의 상수 변수가 따로 설정되어야 하는 상황이 있습니다. (예로 API 서버 호스트를 들 수 있겠습니다.)
이러한 상황을 환경 변수로 관리하기 위해서 설정한 환경 변수를 Webpack에 넘겨주어 JS context에서 사용할 수 있습니다.
Webpack Environment Variable을 적용하여 개발/배포 환경에 각각 적용할 환경 변수 파일을 설정하고, Webpack DefinePlugin을 사용하여 JS context에서 사용합니다.
구성
Webpack구성은 생략합니다.
게시글 하단의 Github Link를 참조하시거나,
이전 게시글을 참조해주세요
1
Dotenv 패키지를 설치합니다.
npm i --save-dev dotenv앞서 말씀드렸듯이, Dotenv는 `<NAME>=<VALUE>` 포맷으로 만들어져 있는 환경 변수 설정 파일을 읽어와서 Node runtime에서 사용 가능하게 만들어 줍니다.
npm i --save-dev dotenv
2
환경 변수를 선언합니다.
". env" 파일을 생성한 후 `<NAME>=<VALUE>` 포맷의 환경변수를 선언합니다.
한 라인의 하나의 환경 변수만 선언할 수 있습니다.
". env"이라는 파일의 이름은 Dotenv가 읽는 기본 값입니다.
3
웹팩 설정 파일(webpack.config.js)에서 환경 변수를 불러옵니다.
require 함수로 dotenv모듈을 가져옵니다.
가져온 dotenv모듈의 method인 config method를 통해 .env파일을 읽어 와 환경 변수를 세팅합니다. (앞서 말씀드렸듯이 dotenv가 가져오는 기본 파일 이름은 ". env"입니다.)
이제 process.env 객체를 참조하여 환경 변수를 사용할 수 있습니다.
process.env. <VARIABLE_NAME>
응용 구성
여기서부터는 개발/배포 환경을 구분하여 환경 변수를 세팅하는 방법을 설명합니다.
4
개발/배포 환경을 구분해 줍니다.
Webpack Environment Variable을 적용합니다.
프로젝트 설정 파일(package.json)에서 Webpack을 실행할 때 환경 변수를 넘겨줍니다. (저의 프로젝트 세팅은 webpack serve 커맨드로 개발 서버를 실행시키기 때문에 해당 커맨드에 파라미터를 넣었습니다.)
그리고 개발 환경의 환경 변수 설정 파일인 "dev.env"와 배포 환경의 환경 변수 설정 파일인 ".env"를 생성하여 API 서버 호스트를 뜻하는 API_SERVER_HOST를 설정해주세요 (예제와 같이 따옴표는 적지 마세요!)
5
웹팩 설정 파일(webpack.config.js)에서 Webpack Environment Variable을 가져옵니다.
웹팩 설정 파일의 exports를 함수로 바꾸어, 첫 번째 파라미터로 `env`를 받습니다.
`env`파라미터는 앞 4번에서 추가해준 --env 파라미터들이 객체로 바뀌어 옵니다.
여기까지 구성했을 때, env.<ENVIRONMENT_VARIABLE_NAME> 환경 변수를 참조할 수 있습니다.
그리고 Environment Variable로 가져온 개발/배포 값에 따라 가져올 환경 변수 파일을 다르게 설정해 주세요
6
DefinePlugin을 적용합니다.
현재 Node runtime에서만 사용할 수 있는 환경 변수를 JS context에서도 사용하기 위해선 Webpack build time에 선언해 주어야 합니다.
자세히 설명하면 Webpack이 Build 될 때 entry script file부터 compile을 실행하게 되는데, 이때 DefinePlugin으로 Webpack build time에 전역 변수(환경 변수)를 선언하여 Webpack이 Scripts 상에 존재하는 해당 변수 문자열을 Replace(대체) 할 수 있습니다.
이때 Webpack은 Script 상에 "변수로써" 사용이 된 부분만 캐치하여 Replace 합니다. 일반 문자열도 변수로 인식하여 대체해버리면 에러 없는 에러가 될 수 있기 때문입니다.
(Global String Scope?🤔)
위 내용을 완벽히 이해하셨다면 DefinePlugin을 사용하여 Browser runtime에서도 사용 불가하다는 결론도 도출시킬 수 있습니다.
정리하면, DefinePlugin으로 선언한 전역 변수는 Webpack의 Build time에만 사용 가능합니다 Broswer runtime에서는 사용할 수 없습니다.
7
스크립트 파일에서 테스트 코드를 작성합니다.
위와 같이 일반 전역 변수처럼 사용할 수 있습니다.
하지만 위와 같이 일반 전역 변수처럼 편리하게 사용할 수 있는 이유가 따로 있습니다.
앞서 DefinePlugin에 작업하셨던 내용을 보시면
환경 변수 설정 파일에 따옴표를 적지 않았고,
웹팩 설정 파일에서 process.env 객체를 참조하여 가져온 환경 변수에 JSON.stringify 함수를 사용하였는데요
첫 번째는 환경 변수 설정 파일의 가독성을 위함이고,
두 번째는 Script 상에서 환경 변수를 편리하게 사용하기 위함입니다.
두 번째의 과정을 왜 해야 하는 것인지 자세히 살펴보겠습니다.
웹팩 설정 파일에서 JSON.stringify 함수를 사용하지 않고 Webpack을 실행해 보겠습니다.
그러면 위와 같이 Syntex Error가 표시됩니다. 왜 표시될까요?
예제에서 사용한 Tempalte literal 문법은 ${} 안에 존재하는 변수의 이름을 찾아 해당 변수의 내용을 위치에 넣습니다.
하지만 위 테스트 처럼 JSON.stringify 함수를 통해 따옴표가 없는 데이터로 Replace로 할 경우 해당 데이터 자체를 Tempalte literal이 변수로 인식하여 에러가 발생합니다.
> `Hello ${DEVELOPMENT} World` // Template literal
/* Replace by webpack ... */
> `Hello ${https://google.com} World`
/* Run in browser runtime ... */
> `Hello ${https://google.com} World`
> !Syntex Error Occurred!
이때 Template literal 문법은 ${} 안에 따옴표가 존재하면, 변수로 인식하지 않고 그냥 적용시킵니다.
이러한 Syntex Error를 유연하게 처리하기 위해 Webpack build time에서 미리 따옴표를 추가해 주고, 편리하게 사용할 수 있게 하는 것입니다.
> `Hello ${DEVELOPMENT} World` // Template literal
/* Replace by webpack ... */
> `Hello ${"https://google.com"} World`
/* Run in browser runtime ... */
> `Hello ${"https://google.com"} World`
> Return "Hello https://google.com World"
다른 경우도 살펴볼까요?
아래의 예제는 JSON.stringify 함수를 웹팩 설정 파일에서 적용하지 않았습니다.
Webpack이 적용되지 않은 경우에는(No build), 변수가 String과 합성되어 정상적으로 출력되어야 할 것입니다.
하지만 Webpack에서는 해당 위치에 있는 문자열인 API_SERVER_HOST가 변수로 사용되었다는 것을 인식하고, Replace 합니다.
이때 해당 데이터는 따옴표 처리가 되어있지 않아 따옴표 없이 아래와 같이 문자열이 삽입되게 됩니다.
그렇게 Build 된 JS 파일은 Browser runtime에서 실행되고, Syntex Error가 발생하게 됩니다.
어쨌거나 최종적으로 말하고 싶은 것은 JSON.stringify를 적용하지 않고 아래와 같이
"\"" + process.env.API_SERVER_HOST + "\""
직접 쌍 따옴표를 붙혀줄 수도 있고, JS context에서 직접 쌍 따옴표를 찍어 처리할 수도 있습니다. 하지만 편리성을 위해 사전 Webpack build 과정에서 따옴표 처리를 해 주는 것입니다.
후기
기존에는 프로젝트 환경 변수를 JS 파일 안에 넣어 관리하고 있었는데, Dotenv와 Webpack Environment Variable, DefinePlugin를 적용하여 구조적인 프로젝트를 구성할 수 있었습니다.
그리고 Webpack의 Build 과정 등을 더욱 이해할 수 있는 계기가 되었습니다.
프로젝트 소스코드 링크
https://github.com/SungeunP/Dotenv
피드백은 언제나 환영합니다!
틀린 정보가 있는 부분이 있을 수 있습니다. 발견하실 경우 알려주시면 감사드리겠습니다.
'Front-End' 카테고리의 다른 글
[회고] WPF 프로젝트 (0) | 2021.04.07 |
---|---|
[JS 코딩 테크닉] AND, OR 연산자를 사용한 코딩 테크닉 (0) | 2021.03.30 |
Webpack 개발환경 기초 셋업 (0) | 2021.03.14 |
Polyfill 이란? (0) | 2021.03.09 |
JS NodeSelector 살펴보기 (0) | 2021.03.07 |