pile·
모바일·스캐터랩스캐터랩 (이루다)·

React Native 앱의 배포 트랙 관리하기

React Native 앱에서 CodePush와 플랫폼별 바이너리 배포를 함께 운영하며 prod, alpha, canary 트랙을 분리한 방법을 설명한다. 테스트 설정이 다른 APK·IPA는 스토어 대신 S3에 올리고, iOS adhoc 설치용 manifest와 GitHub Actions release tag를 조합해 12가지 배포 경로를 자동화했다.

핵심 포인트
  • CodePush는 앱에 내장된 JavaScript 런타임이 App Center의 새 JS bundle을 받아 네이티브 바이너리 재배포 없이 기능을 갱신한다.
  • App Center Deployment Key로 prod·alpha·canary 같은 트랙을 구분하고 업데이트 확인·설치 시점을 별도로 정한다.
  • 테스트 트랙마다 서버와 DB가 달라 앱 빌드 시 Android flavor와 iOS Configuration으로 다른 설정과 key를 주입했다.
  • 테스트용 APK·IPA는 스토어 버전을 소비하지 않도록 S3에 저장하고 Slack에 설치 링크를 전달했다.
  • `{배포종류}.{플랫폼}.{트랙}.{버전}` release tag로 binary와 codepush, iOS와 Android, 세 트랙의 12가지 조합을 선택한다.
상세 정리
  • CodePush 원리: React Native에서 화면 구성을 결정하는 JavaScript bundle은 컴파일 없이 런타임에서 교체할 수 있다. 네이티브 의존 변경이 아니면 새 바이너리가 필요 없다.
  • 배포 흐름: Client SDK가 앱 실행 시 App Center에 업데이트를 조회하고, 새 bundle이 있으면 내려받아 교체한다.
  • 호환성 확인: react-native-code-push의 README만 믿지 않고 최신 React Native 지원 이슈와 PR을 찾아 실제 버전 조합을 테스트해야 한다.
  • 트랙 관리: App Center에서 플랫폼별 앱과 Deployment를 만들면 각 트랙마다 key가 생긴다. CLI의 `release-react`에 deployment 이름을 지정해 배포한다.
  • 설치 정책: `checkFrequency`는 시작·resume·수동 조회를, `installMode`는 다음 재시작·resume·suspend·즉시 설치를 선택한다.
  • 환경 분리 대안: 특정 사용자에게 트랙 전환 버튼을 주거나 빌드 시 설정을 주입할 수 있다. 팀은 서버·DB 분리와 네이티브 변경 테스트 때문에 후자를 택했다.
  • 설정 구성: Android는 flavor, iOS는 별도 Configuration으로 트랙별 Deployment Key와 백엔드 환경을 주입한다.
  • 바이너리 보관: 내부 테스트 결과물을 Play Store·App Store에 올리면 버전 코드가 불필요하게 바뀌므로 S3에 APK와 IPA를 올렸다.
  • Android 설치: APK는 다운로드 링크만 있으면 설치할 수 있어 업로드 뒤 Slack에 직접 링크를 보냈다.
  • iOS adhoc: 테스트 기기 UDID를 Apple Developer에 등록하고 해당 기기를 포함한 Provisioning Profile을 만든 뒤 `fastlane match adhoc`으로 인증서를 받는다.
  • manifest 생성: IPA 경로와 bundle identifier를 담은 manifest.plist 템플릿의 최근 저장 경로를 스크립트로 치환한다.
  • iOS 설치 링크: `itms-services` URL이 S3의 manifest를 가리키게 해 웹 링크에서 지정된 테스트 기기에 앱을 설치한다.
  • 배포 행렬: binary·codepush 2종, iOS·Android 2종, prod·alpha·canary 3종으로 총 12개 release를 관리한다.
  • 태그 규칙: `binary.ios.alpha.1.1.0`은 alpha 설정 IPA를 빌드·업로드하고 Slack 링크를 보낸다. 이후 `codepush.ios.alpha.v10`은 같은 앱의 JS bundle만 갱신한다.
  • QA 흐름: 먼저 트랙 전용 바이너리를 설치하고, QA에서 발견한 JavaScript 버그는 같은 Deployment에 CodePush로 빠르게 반복 배포한다.
왜 읽나React Native 팀이 OTA 업데이트와 네이티브 바이너리, 내부 QA 환경을 뒤섞지 않고 하나의 CI/CD 규칙으로 관리하는 구체적 설계를 얻을 수 있다.
스캐터랩
스캐터랩 (이루다) 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 모바일·토스 SLASH토스 SLASH·

    토스의 디바이스 팜 만들기

    토스가 각 팀이 각자 운영하던 작은 디바이스 팜을 하나의 중앙 플랫폼 '네뷸라(Nebula)'로 통합한 과정을 다룬다. Appium 대신 자체 드라이버를 개발해 클릭 13.5배, 텍스트 입력 10배의 성능을 달성했고, Android와 iOS 미러링도 직접 내재화해 실기기 원격 조작과 화면 실시간 공유를 동시에 가능하게 만들었다. 현재 100대를 넘어 수백 대를 향해 24시간 가동 중이다.

    #android#ios#appium+2
  2. 모바일·LY CorporationLY Corporation·

    AI 에이전트를 위한 Android CLI: 대규모 모바일 개발 환경에 적용하기

    LINE Android 팀이 수백 개 Gradle 모듈 규모의 대형 저장소에서 Google의 Android CLI를 AI 에이전트(Claude Code, Codex, Gemini 등)와 함께 운용하며 겪은 토큰 낭비·오작동 문제를 해결한 과정을 다룬다. 얇은 래퍼와 스킬 레이어를 추가해 CLI 출력을 에이전트 친화적으로 정규화하고, Android Studio 연동 기능을 텍스트 검색보다 정확한 시맨틱 심볼 탐색에 활용하는 방법을 소개한다.

    #android#claude-code#mcp+2
  3. 모바일·토스 SLASH토스 SLASH·

    디자이너가 시안 대신 앱을 만든 이유

    토스 UX 디자이너가 AI를 협력자로 삼아 피그마 시안 대신 실제 SwiftUI 코드로 iOS 앱을 직접 구현한 경험을 다룬다. "데드엔드" 화면(송금·결제 완료 등)을 다음 경험의 시작점으로 전환하는 underlay 컴포넌트를 설계하면서 Metal 셰이더 구현까지 디자이너가 주도했고, 완성된 코드를 개발팀에 전달해 협업 방식 자체를 바꿨다.

    #design-system#ai-coding#ios+2