본문 바로가기
프로그래밍 개발/React Native

React Native - 코드 푸쉬(Code Push) 정의 / 개발 환경 세팅 / Staging 환경 세팅

by Jinseok Kim 2023. 8. 10.
반응형

코드 푸시(Code Push) 정의

CodePush는 마이크로소프트의 Visual Studio App Center에서 제공하는 서비스 중 하나로, 클라우드 기반의 앱 원격 업데이트 서비스입니다.

 

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

 

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

 

 

 

 

 

 

Code Push를 통해 얻는 이점

React Native 앱은 JavaScript 파일과 함께 제공되는 이미지로 구성되며, 이러한 파일은 메트로 번들러에 의해 함께 번들로 구성되며 플랫폼 별 binary 파일(예:. ipa 또는. apk 파일)의 일부로 배포됩니다.

 

보통 앱이 출시하기 위해선 JavaScript 코드(예: 버그 수정, 새 기능 추가) 또는 이미지를 업데이트하려면 전체 binary를 다시 컴파일하고 재배포해야 합니다. 그리고 배포할 앱은 스토어와 심사 및 검토 시간까지 필요합니다.

 

하지만 CodePush 플러그인JavaScript 및 이미지를 CodePush 서버에 릴리스한 업데이트와 동기화하여 최종 사용자 앞에서 즉시 제품 개선 효과를 얻을 수 있도록 지원합니다.

 

이러한 방식은 웹과 같은 배포를 앱에서 할 수 있게 되었습니다.

 

 

 

 

 

 

Code Push 업데이트 관리

CodePush 플러그인은 앱의 사용자가 안전하게 항상 오류가 없는 작동 중인 버전의 앱을 사용할 수 있도록 이전 업데이트의 복사본을 유지 관리하여 코드푸시를 통해 앱의 충돌이 포함된 업데이트를 실수로 푸시하는 경우 자동으로 RollBack 할 수 있게 되어 있습니다.

 

이러한 시스템이 서버에서 롤백하기 전에 사용자가 새로운 릴리스 업데이트로 인해 앱이 차단되는 것을 방지할 수 있습니다.

 

 

 

 

Code Push 업데이트의 한계

앱의 모든 코드를 업데이트를 할 수 없습니다. **Native 코드(예: AppDelegate.m/MainActivity.java 파일 수정, 새 플러그인 추가)**를 건드리는 모든 코드 변경은 CodePush를 통해 배포할 수 없으므로 기본적인 스토어를 통해 업데이트해야 합니다.

 

이유로는 Native 코드단에서 앱 실행될때 가져와야 하는 <앱 JS 번들파일>을 가져올때의 로직과 매소드를 재정의하여 CodePush을 사용하는 원리이기 때문에 Native 코드들은 업데이트할 수가 없습니다.

 

 

 

Android의 MainApplication.java

...

import com.microsoft.codepush.react.CodePush;

public class MainApplication extends Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        ...
	// 여기서 앱 JS 번들파일을 파싱합니다.
        @Override
        protected String getJSBundleFile() {
            return CodePush.getJSBundleFile();
        }
    };
}

 

Ios의 AppDelegate.m

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
  #if DEBUG
    return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
  #else
	// 여기서 앱 JS 번들파일을 파싱합니다.
    return [CodePush bundleURL];
  #endif
}

 

 

 

 

 

 

React Native Code Push 환경세팅

 

1. 코드 푸쉬 전용 라이브러리를 Install 합니다.

 

GitHub - microsoft/react-native-code-push: React Native module for CodePush

React Native module for CodePush. Contribute to microsoft/react-native-code-push development by creating an account on GitHub.

github.com

npm install --save react-native-code-push

 

 

 

 

2. OS별 Native단 환경설정을 따로 해줘야 합니다.


빈번하게 코드 푸쉬 라이브러리가 업데이트되며 환경세팅 법이 달라질 수 있으니 공식 깃허브 Docs을 보시는 것을 추천합니다. 

 

링크

 

 

 

 

3. React Native 프론트단 코드 설정

 

첫 번째로 App.tsx에서 App을 아래와 같이 코드 푸시 메서드를 감싸줘야 합니다.

 

App.tsx

//CodePush
import codePush from 'react-native-code-push';

...

// Code Push의 codePush.Sync() 메소드 컨트롤 호출을 위한 checkFrequency maunal화 설정
export default codePush({checkFrequency: codePush.CheckFrequency.MANUAL})(App);

 

이때 코드 푸쉬 업데이트 시점을 커스텀으로 핸들링을 하고 싶다면 'codePush.CheckRequency.MANUAL'로checkFrequency을 설정해줘야 합니다.

 

따로 설정해주지 않는다면 앱을 실행시켰을 때 코드 푸시 업데이트 번들링 파일을 자동으로 인스톨하게 됩니다. 즉, 다른 곳에서 코드 푸쉬 번들링 파일 인스톨 메소드를 호출하면 중복 호출되어 치명적인 충돌이 발생할 수 있으니 주의하시길 바랍니다.

 

 

 

 

저는 Context API을 사용하여 코드 푸쉬 이벤트를 관리하였습니다. 각자 운영하는 서비스, 기획에 따라 핸들링이 필요한 시점과 설정은 다르니 각자 서비스를 고려하여 설정해 주세요.

 

ContextProvider.tsx

  const codePushAction = useCallback(async () => {
    if (__DEV__) return;
    try {
      const update: RemotePackage | null = await codePush.checkForUpdate(); // Code Push 업데이트가 있는지 알기 위한 Code Push 서비스 서버 체크 호출
      if (update) {
        const updateType = update?.isMandatory ? 'mandatory' : 'option'; // Mandatory(강제) 업데이트 or Option(선택) 업데이트
        await codePush.sync(
          {
            installMode: codePush.InstallMode.ON_NEXT_RESTART, // Code Push 다음번 앱 실행시 업데이트 하도록 설정
            mandatoryInstallMode: codePush.InstallMode.ON_NEXT_RESTART, // Code Push Mandatory(강제) 업데이트시 다음번 앱 실행시 업데이트 하도록 설정
            rollbackRetryOptions: {
              delayInHours: 0, // Code Push 업데이트 Rollback시 업데이트 재시도 대기 시간 0시간으로 설정하여 바로 다시 업데이트 하도록 설정
              maxRetryAttempts: 1000, // Code Push 업데이트 Rollback시 재시도 횟수 설정
            },
          },
          (status: codePush.SyncStatus) => {
            // Code Push 업데이트를 위한 번들 Install 완료시 if문 조건식 true
            if (status === codePush.SyncStatus.UPDATE_INSTALLED) {
              // 업데이트를 위한 Install이 성공한 것으로 간주됨을 Code Push 런타임에 알리기
              codePush.notifyAppReady().then(() => {
                AsyncStorage.setItem(
                  'CodePushVersion',
                  JSON.stringify(update?.label), // Code Push 업데이트 Release 버젼 표시를 위한 로컬스토리지 저장
                );
                setUpdateModal({isOpen: true, type: updateType}); // 업데이트 완료 알림 및 업데이트를 위한 앱 재실행 버튼 모달 등장
              });
            }
          },
          (progress: DownloadProgress) => {
            // Code Push 업데이트를 위한 번들 Install Progress 진행 수치
          },
          (update: RemotePackage) => {},
        );
      }
    } catch (error) {
      console.log(error);
    }
  }, []);

 

위의 코드 푸시 이벤트 함수는 제가 운영하는 서비스에 최적화된 로직입니다.

 

 

특징을 정리하자면

  • 코드 푸시 업데이트 특성상 앱을 완전히 재실행 해야하는데 이때 강제적으로 재실행이 디폴트 설정이어서 재실행이 강제가되면 사용성이 매우 떨어져 번들 앱 인스톨에 성공시 즉시 재실행이 아닌 다음 앱 실행시 업데이트 되도록 설정하였습니다.
  • 코드 푸쉬 업데이트 인스톨이 완료되면 커스텀 알럿을 등장하도록 설정 두었습니다. 사용자가 업데이트를 인지하게 하고 버튼을 직접 눌러 앱을 재실행 및 업데이트하게 하도록 하여 사용성을 최대한 자연스럽게 하였습니다.
  • 번들 앱 인스톨 업데이트가 실패하여 RollBack이 되면 계속해서 다시 업데이트 재시도되도록 설정해 두었습니다.
  • 코드 푸시 업데이트 내용이 중요하면 '강제', 아니면 '옵션'으로 분기처리 하였습니다.




더 추가해야 하거나 수정이 필요하면 공식 Docs을 보시면서 설정하시면 더욱 좋을 것 같습니다.

 

React Native 클라이언트 SDK 시작 - Visual Studio App Center

React Native SDK & CodePush 시작

learn.microsoft.com

 

 

 

 

 

 

 

 

Code Push 테스트를 위한 Staging 환경 세팅 및 테스트 방법

 

예를 들어 코드 푸시로 업데이트하는데 한계가 있는 라이브러리가 관련된 코드를 코드 푸쉬 업데이트 하게 되면 앱이 치명적 충돌을 발생하는 불상사가 발생할 수 있습니다.


이러한 이슈 상황을 방지하기 위해 웹에서 Staging 환경 / Production 환경을 나눠 단계적으로 검증을 걸쳐 배포하듯이 코드 푸시도 Staging 환경을 구축할 수 있습니다.

 

 

Staging과 Production 따로 분리되어 있어 안전하게 테스트가 가능합니다.

 

 

 

  • 로컬 개발 환경의 스크립트에 Staging, Production 코드푸시 업데이트 명령어를 분리해 두었습니다.
  • 요점은 빌드 자체를 Staging 모드로 하여 빌드하여 코드 푸시 업데이트 명령어를 Staging으로 명령하는 것입니다.
  • iOS는 Xcode로 빌드, Android는 스튜디오로도 가능한데 직접 터미널에서 빌드하는 것이 편하여 터미널에서 명령어를 직접 입력하여 APK로 빌드합니다. (그래서 스크립트단에 코드 푸시용 Staging 빌드 APK 명령어를 설정해 둠)

 

 

 

Staging 환경을 사용하려면 OS별 세팅이 또 필요합니다. 조금 번거롭지만 앞으로의 안전한 배포 버전 관리를 위해서는 필수인 것 같습니다.

 

아래 잘 정리해 둔 블로그 글이 있으니 참고 부탁드립니다.

 

링크

 

 

반응형

댓글