React-native 빌드 환경 구성하기 — 1. Concept

Ethan Lee
6 min readDec 2, 2023

--

Photo by Laura Ockel on Unsplash

이번 글에서는 모바일 개발에서 왜 빌드 환경을 분리해야하는지, 그리고 그에 대한 많은 컨셉 중 하나를 다루려고 한다.

먼저 몇 개의 사례를 통해서 우리는 어떤 상황에서 모바일 개발을 하고 있는지부터 들여다보자.

사례1. 혼자서 개발하는 개발자 A

개발자 A는 혼자 일한다. 하나의 어플리케이션으로 개발을 할 때는 디버그 모드로, 배포하기 전에 잘 빌드 되었는지 확인할 때에는 릴리즈 모드로 새로 설치해서 사용한다. 이러한 과정이 꽤나 번거롭고, 종종 디바이스에 저장된 데이터가 유실되는 경우도 많다.

사례2. 팀으로 일하는 개발자 B

개발자 B는 팀에 소속되어 일한다. 디버그 모드로 개발을 하고, 문제가 없다면 릴리즈 모드로 빌드해서 팀원들이 테스트 하도록 앱을 제공한다. 종종 팀원들은 지금 테스트 하는 앱의 동일한 이름, 아이콘으로 인해 실행하고 있는 앱이 스테이지 환경인지, 프로덕션 환경인지 헷갈려한다. 데이터를 보고 구분하거나 개발자 B에게 묻는 경우가 많다.

사례3. 무료버전, 유료버전

무료버전의 앱과 유료버전의 두 개의 앱을 개발하려고 한다. 유료 버전에서는 무료버전에서 제공하지 않는 몇 가지 기능을 포함하고 있다고 해보자. 대부분의 기능이 비슷하지만 서로 다른 앱을 빌드하려면 어떻게 해야할까?

위의 사례들은 초기에 개발을 하다가 환경 분리에 대한 니즈가 시작되는 시점에 대한 사례이다. RN으로 개발을 하는 경우, 기본 설정되어있는 Debug, Release 환경 만으로도 충분히 개발과 배포가 가능하다. 하지만 시간이 흐르면서 조금 더 분화된 환경에 대한 요구가 생기게 된다.

이 글에서는 크게 3가지의 스텝을 따라 모바일 환경을 구성하는 컨셉을 소개한다.

1. 어떻게 모바일 환경을 정의할 것인가

2. 네이티브 플랫폼에서는 어떻게 환경을 다루는가

3. RN에서는 각 플랫폼 별 환경을 어떻게 구성할 것인가

1. 어떻게 모바일 환경을 정의할 것인가

모바일 어플리케이션의 환경은 크게 두 가지 요소로 구성할 수 있다.

용도

어플리케이션의 사용 목적을 의미하며, 개발용(Debug)과 상용(Release)으로 구분한다. 테스트용(Staging)을 추가하기도 한다.

  • Debug: 개발자 도구, 로깅, 실시간 디버깅을 포함한 개발 용도
  • Release: Debug 기능을 제외한 사용자에게 배포될 프로덕트 용도, 어플리케이션 서명

환경 변수

환경에 따라 변하는 값으로 이를 통해 사용자가 바라보는 어플리케이션의 UI, 기능, 정보 등이 달라질 수 있다.

  • 실행 간 사용할 정보: API Endpoint, Credentials, ENV_NAME 등
  • 빌드 간 사용할 정보: 앱 이름, 앱 아이콘, 스플래시 이미지

위와 같이 용도와 환경 변수에 따라 모바일 환경을 정의할 수 있다. 일반적으로 개발, 테스트, 상용 등의 환경으로 구분하지만 이번 글에서는 개발(dev) 및 상용(production) 버전의 환경으로만 제한하여 접근한다.

2. 네이티브 플랫폼에서는 어떻게 환경을 다루는가

환경 변수를 다루기 위해 dotenv 를 사용하는 것을 전제로 한다.

Android

https://developer.android.com/build/build-variants

Android 에서는 buildTypesproductFlavors 를 조합하여 buildVariants 를 만든다. 하나의 buildVariants 은 하나의 어플리케이션을 빌드한다.

buildTypes

  • 기본 구성은 Debug, Release 이다.
  • 동일한 어플리케이션이지만 용도에 따른 빌드를 위해 사용한다.
  • 예) 디버깅 도구, ProGuard 적용, 앱 서명(signing) 등

productFlavors

  • 서로 다른 어플리케이션을 빌드하기 위한 지침을 포함한다.
  • 예) applicationId, 앱 이름/아이콘, 스플래쉬 스크린
  • dev, production 으로 구성한다.

buildVariants

  • productFlavors + buildTypes의 조합을 통해 구성되고, 이를 통해 하나의 어플리케이션이 빌드된다. (devDebug, devRelease, productionDebug, productionRelease)
  • buildVariants 별로 .env 파일을 지정하여 값을 전달받는다.

iOS

https://developer.apple.com/documentation/xcode/configuring-a-new-target-in-your-project

iOS에서는 ConfigurationTarget 을 조합하여 Scheme 을 만든다. 하나의 Scheme 은 하나의 어플리케이션을 빌드한다.

Configuration

  • Android 의 buildTypes 과 비슷한 개념이다.
  • 기본 구성은 Debug, Release 이다.
  • 동일한 어플리케이션이지만 용도에 따른 빌드를 위해 사용한다.
  • 예) 디버깅 도구, 앱 서명, Profile 지정 등

Target

  • 개별 프로덕트를 빌드하기 위한 지침들을 포함한다. 하나의 Target은 하나의 Info.plist 를 가질 수 있다.
  • Target 에 정의된 빌드 지침에는 Configuration 별 설정이 포함된다.
  • 예) Bundle Identification, 앱 이름/아이콘, 스플래쉬 스크린
  • App.dev, App.production 으로 구성한다.

Scheme

  • Xcode 에서 취급하는 실행(build, run, test, profile, archive) 단계에서 ConfigurationTarget 을 사용할 것 인지에 대한 지침을 포함한다.
  • Android 의 buildVariants 와 비슷한 개념이다.
  • build 시 사전 실행(pre-actions)을 통해 .env 파일을 지정하여 값을 전달받는다.

3. RN에서는 각 플랫폼 별 환경을 어떻게 구성할 것인가

  1. 구분된 환경변수 파일(.env.dev, .env.production)을 생성하고 값을 기입한다.
  2. package.json 에 원하는 플랫폼과 빌드 구성에 대한 실행 스크립트를 작성한다. (yarn run-android, yarn run-ios)
  3. 어플리케이션에서 환경 변수를 참조할 수 있도록 코드 및 타입을추가한다.

지금까지 모바일 환경에 대한 정의부터 Android 와 iOS 에서는 어떻게 환경을 다루는지, 마지막으로 RN에서는 각 네이티브 플랫폼에 환경 변수를 어떻게 전달할 지, 그리고 참조할 지에 대한 개략적인 컨셉에 대해서 이야기를 했다.

많은 삽질을 해보면서 정답은 없다는 결론을 내렸다. Android 의 productFlavors 를 쓰지 않고 모든 구성을 buildTypes 에 몰빵하는 케이스도 있었다. 그렇게 해도 구성은 잘 된다. 스택오버 플로우에는 둘의 차이점을 묻는 질문도 있다.

그만큼 플랫폼에서 권장하는 방식을 최대한 따르고 이를 RN 구성까지 잇는 컨셉을 이해하고, 각자의 방식에 맞게 유연하게 사용하는 것이 좋다고 생각한다.

다음 글에서는 실제 코드를 통해 어떻게 구현할 것인지 이야기하겠다.

--

--