·3분 분량

About에서 카공지도를 분리했더니 다섯 레이어 중 네 개가 뒤섞여 있었다

카공지도를 따로 출시하려고 저장소를 복제한 지 약 석 달, 처음 열어보고서야 무엇이 안 바뀌었는지 알았다.

React Native트러블슈팅모바일

카공지도(카페 공부 지도)를 About에서 떼어내 별도 앱으로 출시하려고 두 저장소, app과 cafe-map-app을 열었다. 둘 다 이미 분리되어 있었고 빌드도 각자 돌아갔다. 그런데 각 저장소가 실제로 무엇을 About으로, 무엇을 카공지도로 알고 있는지 레이어를 하나씩 열어보니, 앱을 구별하는 값 다섯 개 — Android applicationId, Android 네이티브 패키지, iOS Firebase Bundle ID, React Native 컴포넌트 등록명, 딥링크 URL 스킴 — 중 네 개가 두 앱에서 같은 값을 쓰고 있었다.

처음 가정한 것

이름 하나만 다르게 바꾸면 두 앱이 나뉜다고 가정했다. app.json의 name 필드만 보고 시작했다.

그런데 당시 About이 되어야 할 저장소의 app.json은 name: "카공지도"였고, 같은 저장소의 Android MainActivity.getMainComponentName()은 "어바웃"을 요청하고 있었다.

// android/app/src/main/java/.../MainActivity.java
protected String getMainComponentName() {
  return "어바웃";
}

React Native는 JS 쪽에서 AppRegistry.registerComponent로 등록한 이름과 네이티브가 요청하는 모듈명이 같아야 부팅한다. 두 이름이 다르면 화면이 뜨기 전에 번들 로드부터 실패한다. 이름 하나 바꾸는 걸로 끝날 문제가 아니었다.

실제로 측정한 것

두 저장소의 다섯 레이어를 전부 읽었다.

레이어app (→ About)cafe-map-app (→ 카공지도)
app.json name카공지도어바웃
Android strings.xml app_name어바웃카공지도
Android applicationIdcom.about.studyaboutclubappclub.about20s.cafemap
Android 네임스페이스(패키지 경로)com.about.studyaboutclubappcom.about.studyaboutclubapp
iOS Firebase Bundle IDclub.about20s.cafemapclub.about20s.cafemap
iOS URL 스킴kagongmapkagongmap
WebView 진입 URIstudy-about.club/study-about.club/cafe-map

일곱 개 값 중 마지막 WebView URI 하나만 제대로 갈라져 있었다. 나머지는 두 앱이 서로 반대 값을 들고 있거나(첫 두 줄), 아예 같은 값을 공유하고 있었다(뒤 네 줄).

git으로 각 레이어에 언제 café-map 값이 들어왔는지 추적했다. build.gradle, app.json, App.tsx 세 파일 모두 같은 커밋(6월 6일, 메시지는 .) 하나에서 들어와 있었다. 카공지도를 급하게 만들려고 About 저장소를 복제하면서, 세 레이어를 한 번에 café-map 값으로 바꿔 넣은 흔적이었다.

그 시점 카공지도는 인스타그램에서 콘텐츠가 유행하며 누적 조회수 1,000만 회를 넘기고 있었다. 하루 접속자가 수만 명 단위로 뛰었고, 카페 프랜차이즈 ‘카공족’과의 제휴도 준비하던 때였다. 커밋 메시지를 .으로 남기고 세 레이어를 한 번에 바꿔 넣은 건, 트래픽이 이미 몰리는 상황에서 정식 앱을 최대한 빨리 스토어에 올려야 했기 때문이다.

판단과 근거

폴더 이름은 믿지 않기로 했다. 대신 네이티브 레이어의 모듈명을 기준으로 삼았다. app.json은 café-map을 만들 때 복사되며 자주 바뀌지만, MainActivity.java나 AppDelegate.mm은 초기 세팅 이후 손대는 일이 드물어서 신뢰도가 더 높다고 판단했다.

  • app의 네이티브 모듈명은 "어바웃" → 이 저장소가 About이어야 한다.
  • cafe-map-app의 네이티브 모듈명도 "어바웃"이었다 — 즉 이 저장소는 아직 café-map으로 전환된 적이 없고, About을 그대로 복제한 상태였다.

두 저장소를 각자 다른 방향으로 고쳤다. app은 JS 레이어(app.json, App.tsx)를 네이티브가 요청하는 About 값에 맞춰 되돌렸다. App.tsx에 하드코딩돼 있던 kagongmap 열두 곳을 about20s로 바꾸고, AndroidManifest.xml에 위치 권한(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION)을 추가했다. 지도 기능이 About 쪽에도 일부 남아 있었기 때문이다.

cafe-map-app은 반대 방향이다. applicationId를 club.about20s.cafemap으로, 딥링크 스킴을 kagongmap으로 바꿨다. 다만 여기서는 네이티브 모듈명("어바웃")까지는 건드리지 않았다 — app.json의 name과 네이티브 모듈명 두 값이 서로 일치하기만 하면 앱은 정상 부팅하기 때문에, 브랜드명이 틀려도 빌드와 배포는 막지 않는다.

우선순위 밖에 둔 것

두 가지는 그 자리에서 고치지 않기로 했다.

cafe-map-app의 RN 컴포넌트 등록명은 "어바웃"으로 남겨뒀다. 딥링크 스킴은 kagongmap으로 바뀌었지만 앱 내부 컴포넌트 이름표는 그대로 둔 것이다. 두 저장소의 Android 네임스페이스(Java 패키지 경로)도 com.about.studyaboutclubapp으로 같게 뒀다 — applicationId가 다르므로 플레이스토어에는 별개 앱으로 올라가지만, 소스 트리 안에서는 같은 패키지 아래 있다.

둘 다 부팅 크래시로 이어지는 값이 아니었다. applicationId, 딥링크 스킴, Firebase 등록처럼 사용자가 체감하는 값은 이미 갈라진 상태였고, 남은 두 개는 코드를 여는 개발자만 보는 값이었다. 트래픽이 몰리는 상황에서 순서를 정해야 했고, 부팅을 막는 값부터 고쳤다.

결과

같은 날, 두 앱 모두 AAB 빌드를 올렸다. 버전 코드 충돌(169, 172, 175)을 세 번 겪으며 번호를 올렸다. 카공지도 쪽에서 타겟 API 35 관련 오류가 떴고, About 쪽은 오류 없이 통과했다. 카공지도 오류를 마저 잡은 뒤 두 앱 다 커밋·푸시로 마무리했다.

이전이후
applicationId두 앱이 공유앱마다 별도
네이티브 모듈명 불일치로 인한 부팅 실패 (app)있음해소
App.tsx에 하드코딩된 kagongmap (About 쪽)12곳0곳

다섯 레이어 중 부팅과 직결된 셋을 그 자리에서 바로잡았다. 나머지 둘은 사용자가 체감하지 않는 값이라 다음 순서로 넘겼다.

Share:
Back to Blog