[RN] react-native-dotenv에서 개발환경에 따른 빌드 방법

2024. 2. 26. 09:22React-native

| react-native-dotenv 란

babel 플러그인을 사용하며 여러 환경에 대해 dotenv를 사용하여 환경 변수를 자바스크립트 환경에 주입할 수 있다.

리액트 네이티브와 함께 사용하기에 가장 적합하며 웹을 포함한 모든 버전에서 작동하는 npm 모듈이다.

https://github.com/goatandsheep/react-native-dotenv

 

GitHub - goatandsheep/react-native-dotenv: Load react native environment variables using import statements for multiple env file

Load react native environment variables using import statements for multiple env files. - goatandsheep/react-native-dotenv

github.com

 

| react-native-config

react-native-config라는 환경변수를 관리하는 비슷한 모듈이 존재한다.

dotenv는 process.env 로 환경변수에 접근할 수 있어서 주로 사용한 방식과 유사해 react-native-dotenv를 택했다.

react-native-config는 라이브러리를 설치하면 .env 파일을 Config 객체를 통해 접근할 수 있다.

react-native-dotenv보다 많은 기능을 지원한다.

또한 네이티브 측에서 관리를 해야하는것이라면 이 라이브러리를 사용하는게 정답? 인것같다.

* 왜 이 생각을 못했을까... *

 

| 문제

프로젝트의 초기에는 신경을 안써도될 정도로 잘 사용을 했다.

그 당시에는 개발만 진행하던 단계라서 서버도 하나로 작업을 진행을 했었고 다른 키가 추가가 되지 않는 이상 .env를 건들 필요가 없었다.

하지만 점점 프로덕션으로 올라가는 기간이 다가오자 여러 상황이 벌어졌다.

development 서버는 개발자들이 테스트와 신규 작업을 진행하는 서버로 사용을 했다.

또한 production 서버는 항상 존재한다.초기세팅을 쉽게 하려고 멀리 보지않은 내 문제가 가장 큰 듯하다.그리고 production에 올라가기 전 다른 테스터들이 테스트를 진행하는 staging 서버가 탄생했다.이때부터 머리가 아파오기 시작했다.3가지의 서버에 따라서 릴리즈 / 디버그 또한 달라질거고 사실 해결책이 완전히 없는 상태는 아니다..env 파일을 릴리즈 / 디버그 환경에 따라 변경하면 정상적으로 작동한다.이럴 때 발생할 수 있는 상황을 생각해보자.

 

??? : 지후 씨 스테이징 버전으로 apk 하나만 뽑아주세요!나 : 네 뽑았습니다!??? : 이거 데브버전인데요?나 : 죄송합니다.

 

이런 상황이 100번중에 1번이 안나올까...?

 

그래서 곧바로 개발환경에 따른 빌드 방법을 서치 해보았다.

 

{
	"start:staging": "TYPE=staging npx react-native start",
	"start:development": "TYPE=development npx react-native start",
}

 

이런식으로 하면 staging은 .env.staging 파일의 환경변수를 읽어서 프로젝트를 실행한다.

물론 Babel은 따로 설정을 해주어야 한다.

module.exports = {
	presets: ['module:metro-react-native-babel-preset'],
	plugins: [
		[
			'module:react-native-dotenv',
			{
				envName: "TYPE",
				moduleName: '@env',
				path: '.env',
				blacklist: null,
				whitelist: null,
				safe: true,
				allowUndefined: true,
			},
		],
	],
};

 

 

여기서 또 다른 문제에 직면했다.

apk를 뽑을 때는 어떻게 적용을 해야하는것인가 였다.

결국 해결된게 하나도 없었다.

그래서 곧바로 dotenv 깃헙, 문서, 이슈 를 뒤져보았다.

답변 중 가장 많았던 답변은 "react-native-config로 가봐! 거기는 이런 기능이 있어!" 라는 소리를 했다.

물론 정답이겠지만

정상적으로 프로젝트가 켜지다가 다음날 출근하면 안켜지는 이 요상한 RN에서 다시 세팅을 진행 한다는것은 시간상 불가능이라고 생각했다.

 

빌드를 하면 무조건 .env.staging, .env.development 파일을 무시하고 .env 파일만을 따라간다는것을 생각했다.

그래서 내가 생각한 방법은 .env.staging, .env.development 파일을 작성하고

번들링 하기전에 staging 모드로 빌드를 하려면 .env.staging에 있는 내용을 .env로 붙여넣고 진행을 하면 이 문제가 해결 될 수 있다고 생각했다.


그래서 바로 .js 파일을 하나 생성하고 node 코드를 짜기 시작했다.

// build_env.js

const fs = require('fs');

const type = process.argv[2];

fs.copyFile(`.env.${type}`, '.env', err => {
    console.log(err);
})

 

위에 코드를 작성했다. 

여기서 type 변수가 하는일은 예를 들어서 node build_env test 라는 명령어를 입력하면 

node[0] build_env[1] test[2] 이렇게 분할을 해서 배열로 뱉어준다.

결국 저 test라는 단어만 필요하고 2번째 요소는 파일명에 맞춰서 입력하게 설정을 해준다.

그리고 번들링 명령어와 묶어서 번들링 되기 전에 저 작업을 먼저 진행하게 하였다.

"script" : {
	"release-dev": "node build_env development && rm -rf android/app/src/main/res/drawable-* && rm -rf android/app/src/main/res/raw/* && cd android && ./gradlew clean && cd .. && react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/build/intermediates/res/merged/release/ && cd ..",
	"release-staging": "node build_env staging && rm -rf android/app/src/main/res/drawable-* && rm -rf android/app/src/main/res/raw/* && cd android && ./gradlew clean && cd .. && react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/build/intermediates/res/merged/release/ && cd ..",
	"release-product": "node build_env production && rm -rf android/app/src/main/res/drawable-* && rm -rf android/app/src/main/res/raw/* && cd android && ./gradlew clean && cd .. && react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/build/intermediates/res/merged/release/ && cd android && ./gradlew assembleRelease && cd .."
}

 

이렇게 스크립트를 수정하고 저 명령어로 항상 env를 초기화 하여 빌드하는 방법으로 정답은 아니지만 우회하는 방법을 선택했다.

다음부터는 초기부터 라이브러리에 대한 고민을 충분히 해봐야겠다.

배우고 반성했던 시간..