React Native CLI 프로젝트에서 "앱 이름"은 하나가 아니다. 홈 화면에 보이는 이름, 번들 내부 식별용 이름, JS에 등록된 컴포넌트 이름이 각각 따로 존재한다. 이 셋을 구분하지 못하면 이름을 바꿔도 반영되지 않거나 앱이 아예 실행되지 않는다.
| 구분 | 위치 | 역할 |
|---|---|---|
| 표시 이름(Display Name) | iOS Info.plist, Android strings.xml | 사용자가 홈 화면에서 보는 이름 |
| 프로젝트 이름 | Xcode 타겟명, Gradle 모듈명 | 네이티브 빌드 산출물 식별자 |
| 컴포넌트 이름 | AppRegistry.registerComponent() | JS 루트 컴포넌트 등록 키 |
표시 이름만 바꾸는 경우는 안전하다. 프로젝트 이름이나 컴포넌트 이름을 건드리면 네이티브 코드까지 함께 수정해야 한다.
ios/<ProjectName>/Info.plist에 CFBundleDisplayName 키를 추가한다.
<key>CFBundleDisplayName</key>
<string>내 앱</string>
CFBundleDisplayName이 없으면 iOS는 CFBundleName을 대신 사용한다. CFBundleName은 15자 제한이 있고 번들 내부 식별에 쓰이므로, 표시 이름은 반드시 CFBundleDisplayName으로 지정하는 것이 맞다.
한글이나 공백, 이모지도 그대로 넣을 수 있다.
ios/<ProjectName>.xcworkspace를 열고 타겟 선택 → General 탭 → Display Name 필드를 수정한다. 내부적으로 Info.plist의 CFBundleDisplayName을 갱신하는 것과 동일하다.
기기 언어에 따라 이름을 다르게 하려면 InfoPlist.strings를 사용한다.
ios/
ko.lproj/InfoPlist.strings
en.lproj/InfoPlist.strings
// ko.lproj/InfoPlist.strings
"CFBundleDisplayName" = "내 앱";
// en.lproj/InfoPlist.strings
"CFBundleDisplayName" = "My App";
생성한 .strings 파일은 Xcode에서 타겟의 Copy Bundle Resources에 포함되어 있어야 한다. 파일을 파인더로만 만들면 빌드에 포함되지 않는다.
android/app/src/main/res/values/strings.xml을 수정한다.
<resources>
<string name="app_name">내 앱</string>
</resources>
AndroidManifest.xml에서 이 값을 참조하고 있는지 확인한다. 기본 템플릿은 이미 그렇게 되어 있다.
<application
android:label="@string/app_name"
...>
app_name과 컴포넌트 이름의 혼동MainActivity.kt의 getMainComponentName()이 반환하는 문자열은 표시 이름과 무관하다. 이 값은 index.js의 AppRegistry.registerComponent()에 넘긴 이름과 일치해야 한다.
// android/app/src/main/java/.../MainActivity.kt
override fun getMainComponentName(): String = "MyApp"
// index.js
AppRegistry.registerComponent('MyApp', () => App);
strings.xml의 app_name을 바꿨다고 이쪽까지 바꾸면 앱이 흰 화면으로 뜬다. 둘은 별개다.
로케일별 리소스 디렉터리를 추가한다.
android/app/src/main/res/
values/strings.xml # 기본(영어)
values-ko/strings.xml # 한국어
dev / staging / prod를 구분해 설치하는 경우, 소스셋을 나누는 방식이 가장 깔끔하다.
android/app/src/
dev/res/values/strings.xml # "내 앱 (개발)"
main/res/values/strings.xml # "내 앱"
build.gradle의 productFlavors나 buildTypes 이름과 디렉터리명이 일치하면 자동으로 병합된다. applicationIdSuffix를 함께 지정하면 개발 빌드와 배포 빌드를 한 기기에 동시에 설치할 수 있다.
app.json의 displayName은 무엇인가{
"name": "MyApp",
"displayName": "내 앱"
}
react-native init 시점에 네이티브 파일을 생성하기 위한 템플릿 값이다. 프로젝트 생성 이후에 이 파일을 수정해도 앱 이름은 바뀌지 않는다. Expo와 달리 RN CLI에서는 런타임에 읽지 않는다. 이름을 바꿀 때는 네이티브 파일을 직접 수정해야 한다.
이름 변경은 네이티브 리소스 변경이므로 Metro 리로드로는 반영되지 않는다. 재빌드가 필요하다.
# iOS
cd ios && rm -rf build && cd ..
npx react-native run-ios
# Android
cd android && ./gradlew clean && cd ..
npx react-native run-android
기기에 이전 이름이 계속 보이면 앱을 삭제하고 다시 설치한다. iOS 홈 화면 캐시가 남아 있는 경우가 있다.
표시 이름이 아니라 프로젝트/번들 식별자까지 통째로 바꾸는 작업은 수정 지점이 수십 곳이다. Xcode 타겟, 스킴, Podfile, applicationId, 패키지 디렉터리 구조, settings.gradle 등이 모두 얽힌다.
수동으로 하기보다는 도구를 쓰는 편이 실수가 적다.
npx react-native-rename@latest "새이름" -b "com.example.newapp"
실행 전에 반드시 커밋해 두고, 실행 후에는 pod install과 클린 빌드를 거쳐 iOS/Android 양쪽에서 실행을 확인해야 한다. 특히 Android는 패키지 디렉터리 경로가 변경되므로 MainActivity, MainApplication의 package 선언과 실제 경로가 일치하는지 확인한다.
New Architecture(Fabric / TurboModules / Bridgeless)를 활성화해도 앱 이름 설정 방식은 동일하다. CFBundleDisplayName과 app_name은 순수 네이티브 리소스이므로 렌더러나 브릿지 구현과 무관하다.
다만 Bridgeless 모드에서는 루트 뷰 생성 경로가 달라지므로, 컴포넌트 이름(moduleName / getMainComponentName())이 AppRegistry 등록 이름과 어긋났을 때 나타나는 오류 메시지가 기존과 다를 수 있다. 흰 화면이 뜬다면 표시 이름이 아니라 이쪽을 먼저 의심하는 것이 좋다.