[기능 구현][RN] CodePush 적용

Wonhyun Kwon·2023년 8월 16일
1

기능 구현

목록 보기
4/4
post-thumbnail

📌 참고
하기 포스트를 참고하여 작성하였음을 알립니다.
React Native에서 CodePush 사용하기!!!


0. 개요

현재 기준 모바일 크로스 플랫폼 시장에서 React NativeFlutter 가 서로 엎치닥 뒤치락 하며 시장 점유율을 가져가고 있다.
두 스택 모두 장단점이 뚜렷하다. 예를 들면 Third pary의 의존성이 크냐 안크냐가 제일 나뉠 것이다.
그 중 뚜렷한 차이점 중 하나는 바로 'CodePush' 를 지원하냐 안하냐의 차이이다.
이 포스트의 타이틀에서 보면 유추할 수 있듯이, React Native의 가장 큰 장점 중 하나는 바로 CodePush 기능을 지원한다는 것이다.

그렇다면 CodePush 는 무엇일까??




1. CodePush?

CodePush 는 Microsoft의 Visual Studio App Center에서 제공하는 서비스 중 하나로 클라우드 기반의 App 원격 업데이트 서비스이다.

원리는 git 과 유사하다. git 은 코드를 수정하고 우리가 터미널을 통해 수정한 코드를 커밋하고 우리의 git 서버에 push하면 다른 개발자가 pull을 통해 내가 수정한 코드를 내려받을 수 있는 구조다.

CodePush 도 우리가 터미널에서 배포 명령을 실행하면 앱을 bundle 파일로 변환하고 이를 CodePush 클라우드 서버에 저장한다. 그럼 사용자가 기존에 설치한 앱을 실행하면 CodePush 서버에 업데이트 여부를 확인하고 수정된 내용을 병합하는 것이다.

다음과 같이 몇 가지 특징을 지니고 있다.

  1. 심사절차가 필요없다.
    방금 언급했듯이 CodePush는 클라우드를 기반으로 원격으로 App을 업데이트하기 때문에 별도의 스토어 심사절차가 필요하지 않다.

  2. 하지만, JavaScript 단에서 수정한 내용만 반영할 수 있다.
    즉, Third-party의 의존성이 높은 RN은 패키지 수정 사항은 CodePush로 반영하지 못하고 재심사를 거쳐야 한다.

  3. 또한, JavaScript 파일이 중간에 새로 추가되거나 삭제된 경우 역시 CodePush로 올라갈 수 없으며 스토어의 심사를 통해 업데이트 해야 한다.




2. CodePush 설정하기

2-1) appcenter-cli 설치 및 로그인

설치를 위해 하기 커맨드를 실행한다.

$ yarn global add appcenter-cli

App center에 로그인 하기 위해 설치한 appcenter-cli 를 이용하여 다음과 같이 로그인 한다.

$ appcenter login

실행하면 다음과 같이 App center 홈페이지가 열린다.

이 후 로그인을 완료하면 아래 이미지와 같이 토큰값이 가운데 표시된다.

이 토큰을 복사하여 커맨드 창에 나타나는 Enter your token from the browser: 부분에 복붙한다.
(버전에 따라 다르므로 하기 이미지와 일부 상이할 수 있다. 중요한 것은 토큰 값을 붙여넣는 것이다.)


2-2) App center 콘솔에 App 등록

아래 명령어를 따라 입력하여 App center 콘솔에 App을 등록한다.
📌 참고) iOS, Android 따로 등록해야 한다.

$ appcenter apps create -d {앱 이름} -o {os} -p {플랫폼 타입}

예시를 들면 다음과 같다.

# for iOS
$ appcenter apps create -d myapp_ios -o iOS -p React-Native

# for Android
$ appcenter apps create -d myapp_android -o Android -p React-Native

2-3) CodePush를 위한 Key 발급 및 등록

KeyStaging, Production 각각 발급 및 등록한다.

📌 Staging? Production?
Staging : 배포하기 전 단계로 보통 QA(품질 보증) 및 내부 테스터들이 테스트를 해볼 때 사용하는 모드를 뜻한다. Debug 모드라고 봐도 무방하다.
Production : 실제 App을 배포하는 환경을 뜻한다.
보통 Staging 모드에서 Beta 테스트를 진행하고 테스트에 이상이 없으면 Production 모드로 승격시켜 모든 사용자에게 수정된 앱을 배포하는 과정을 지닌다.

등록을 위한 명령어는 다음과 같다.

$ appcenter codepush deployment add -a {user name}/{앱 이름} {Staging or Production)

예시를 들어보자.

$ appcenter codepush deployment add -a developer/myapp_ios Staging
$ appcenter codepush deployment add -a developer/myapp_ios Production
$ appcenter codepush deployment add -a developer/myapp_android Staging
$ appcenter codepush deployment add -a developer/myapp_android Production

참고로 위 4개의 명령어를 '모두 실행해야 한다!!'
명령어를 하나씩 입력할 때마다 각 앱과 모드에 맞는 키가 반환된다.
이 키를 잘 저장해두자 😀
만약 키 값을 잊어버렸다면, 아래 명령어를 실행하자.

$ appcenter codepush deployment list -a {user name}/{앱 이름} -k

2-4) CodePush 패키지 설치

프로젝트 root 경로에서 다음 명령어를 실행한다.

$ yarn add react-native-code-push

2-5) 플랫폼 별 설정

1) iOS

먼저 pod 를 설치해준다.

$ cd ios
$ pod install

다음, info.plist 파일을 열고 아래 코드를 그대로 추가해준다.

<key>CodePushDeploymentKey</key>
<string>$(CODEPUSH_KEY)</string>

그 다음, Xcode로 프로젝트를 실행하여 AppDelegate.m 파일을 열고 최상단에 다음 코드를 추가한다.

#import <CodePush/CodePush.h>

중간에 이러한 코드가 있을 것이다.

return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

이 코드를 다음과 같이 통째로 수정한다.

return [CodePush bundleURL];

다음은 info.plist 에 추가한 CODEPUSH_KEY를 전역 변수로 연결하는 과정이다.

먼저, 아래 이미지와 같이 경로를 따라 간 후 Duplicate "Release" Configuration 을 클릭하여 Staging 이라고 수정 후 저장한다.
(필자는 이미 구현하여 Staging이 만들어진 모습이다.)

다음 그대로 Project 상태에서 상단에 Build Settings 클릭 후 '+' 버튼을 클릭하여 Add User-Defined Setting 을 클릭한다.
새로 추가된 항목의 이름을 Multi_Deployment_Config 라고 짓는다.

그러면 TARGETS/본인 ProjectBuild Settings에 아래 이미지와 같이 Multi_Deployment_Config 가 생성이 되는데, 각 ReleaseStaging에 다음과 같이 작성하면 된다.

# Release
$ $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

# Staging
$ $(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)

⛔️ 여기서 Staging이 Release 로 하드코딩 되어있는데, 이는 다음과 같은 이슈 때문이다. 이렇게 안하면 Staging 환경에서 동작하지 않는다!!

다시 위에서 했던 작업을 반복하여 '+' 버튼을 눌러 Add User-Defined Settings 를 선택하고 이번엔 이름을 CODEPUSH_KEY 라고 선언한다.

동일하게 각 ReleaseStaging에 본인이 앞서 발급 받은 Key값을 알맞게 입력하면 된다.


2) Android

📌 참고) SDK 싱크 문제로 인해 되도록 Android Studio 안에서 진행하도록 하자.


먼저, gradle.properties 파일 하단에 다음과 같은 코드를 추가하자.

CODEPUSH_DEPLOYMENT_KEY_DEBUG=
CODEPUSH_DEPLOYMENT_KEY_STAGING={발급 받은 staging deployment key}
CODEPUSH_DEPLOYMENT_KEY_PRODUCTION={발급 받은 production deployment key}

그 다음, settings.gradle 파일을 열고 하단에 다음 코드를 그대로 복붙한다.

include ':app', ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')

그 다음, MainApplication.java 파일을 열고 상단에 패키지를 import 해준다.

import com.microsoft.codepush.react.CodePush;

그리고 하단에 new ReactNativeHost(this) 내부 스코프 맨 하단에 다음 코드를 추가해준다.

private final ReactNativeHost mReactNativeHost =
  new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) {
  ...
  // 👇 이 부분!
  @Override
  protected String getJSBundleFile() {
      return CodePush.getJSBundleFile();
  }
  // 👆 이 부분!
});

그 다음, build.gradle(app) 으로 들어가서 하단에 다음 코드를 추가해준다.

apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"

같은 파일에서 buildTypes 내부 스코프에 다음과 같이 코드를 추가해준다.
(releaseStaging 은 그대로 복붙하여 새로 만들어줘야 한다!)

buildTypes {
   debug {
      ...
      resValue "string", "CodePushDeploymentKey", CODEPUSH_DEPLOYMENT_KEY_DEBUG //here
   }
   release {
      ...
      resValue "string", "CodePushDeploymentKey", CODEPUSH_DEPLOYMENT_KEY_PRODUCTION // here
   }
   releaseStaging { // releaseStaging 자체를 추가해줘야 함!
      initWith release
      resValue "string", "CodePushDeploymentKey", CODEPUSH_DEPLOYMENT_KEY_STAGING
      matchingFallbacks = ['release']
   }
}

역시 같은 파일에서 defaultConfig 내부 스코프에 다음 코드를 추가해준다.

android {
	...
	defaultConfig {
		...
		resValue 'string', "CODE_PUSH_APK_BUILD_TIME", String.format("\"%d\"", System.currentTimeMillis()) // here
	}
	...
}

마지막으로 if(enableHermes) {...} 로 시작하는 블럭이 있다면, 그 안에 다음 코드도 추가해준다.

releaseStagingImplementation files(hermesPath + "hermes-release.aar") // 이미 있는 경우도 있다.

최종적으로 Android Studio 우측 상단에 Sync now 를 클릭하여 마무리 해준다.


2-6) tsx 코드 단 설정

CodePush프로젝트의 최상단 영역App.tsx 에서 설정되어야 한다.

다음과 같이 코드를 반영해보자.

import React from 'react';
import CodePush from 'react-native-code-push';

const App = ({}) => {
	return (
		...
	);
}

const codePushOptions = {
  checkFrequency: CodePush.CheckFrequency.ON_APP_START,
  updateDialog: { 
    title: '새로운 업데이트', 
    optionalUpdateMessage: '업데이트가 존재합니다. 진행할까요?', 
    optionalInstallButtonLabel: '예', 
    optionalIgnoreButtonLabel: '아니요.' 
  },
  installMode: CodePush.InstallMode.IMMEDIATE 
}

export default CodePush(codePushOptions)(App);

  • CodePush 동작옵션
    • checkFrequency : 업데이트 시기를 지정
      • CodePush.CheckFrequency.ON_APP_START : 앱을 첫 실행할 때
      • CodePush.CheckFrequency.ON_APP_RESUME : 앱을 잠시 나갔다가 다시 들어올 때
      • CodePush.CheckFrequency.MANUAL : 수동 지정
    • deploymentKey(String) : 배포키 지정 (이 포스트에선 Key를 전역 설정했기 때문에 생략)
    • installMode : 선택적 업데이트를 실행할 시기를 선언
      • CodePush.InstallMode.IMMEDIATE : 즉시 업데이트하고 다시 실행
      • CodePush.InstallMode.ON_NEXT_RESTART : 업데이트를 설치하려 하지만 강재로 앱을 재실행하진 않음. 앱이 자연스럽게 재실행되면 자동으로 업데이트를 실행
      • CodePush.InstallMode.ON_NEXT_RESUME : 업데이트를 실행하지만 앱 종료 후 사용자가 앱을 재실행할 때까지 앱이 자동으로 재실행되지 않는다.
    • mandatoryInstallMode : 필수로 설치된 업데이트를 실행할 시기를 선언
    • updateDialog : 업데이트를 실행할 수 있을 때 사용자에게 알려줄 dialog 설정
      • title : dialog 제목
      • optionUpdateMessage : dialog에 띄울 메시지
      • optionalInstallButtonLabel : 업데이틀 실행 버튼 (ex. 예)
      • optionalIgnoreButtonLabel : 업데이트 미실행 버튼 (ex. 아니오)

더 자세한 사항은 여기 공식 문서를 눌러 확인할 수 있다.




3. 사용 방법

기본적으로 App center에 접속하여 로그인을 한다.

원하는 App을 선택하고 들어가면 왼쪽 메뉴에 distribute > CodePush로 들어간다.
그러면 현재 bundle이 배포되어 있는 버전들이 존재한다. (처음이라면 당연히 없을 것이다.)

아래 커맨드를 사용하여 실제 배포를 해보자.
명령어는 다음과 같다.

$ appcenter codepush release-react -a {user name}/{앱 이름} -d {Production or Staging}

이 명령어 끝에 -m 을 붙이면 사용자의 의사와 관계없이 강제 업데이트를 실행하게 된다.


혹여나 Rollback이 필요한 상황이 있을 것이다.
이 때 다음과 같은 명령어를 사용하면 된다.

# 가장 최근 내용을 롤백
$ appcenter codepush rollback -a {user name}/{앱 이름} {Production or Staging}

# 선택적 내용을 롤백
$ appccenter codepush rollback -a {user name}/{앱 이름} {Production or Staging} --target-release {release id}

여기서 release id 는 위 이미지에 보이는 것과 같이 v1, v2 등을 뜻한다.

profile
모든 사용자가 만족하는 UI를 만드는 FE 개발자 권원현입니다.

0개의 댓글