Git을 통한 더 쉬운 업그레이드
React Native의 새 버전으로 업그레이드하는 것은 항상 어려운 일이었다. 다음과 같은 상황을 경험해 본 적이 있을 것이다:
이러한 옵션 중 어느 것도 이상적이지 않다. 파일을 덮어쓰면 로컬 변경사항을 잃게 된다. 덮어쓰지 않으면 최신 업데이트를 적용할 수 없다.
오늘 이 문제를 해결할 수 있는 새로운 도구를 소개하게 되어 기쁘다. 이 도구는 react-native-git-upgrade
라고 하며, 가능한 경우 Git을 사용해 자동으로 충돌을 해결한다.
사용법
필수 조건: Git이
PATH
에 설치되어 있어야 한다. 프로젝트가 Git으로 관리되지 않아도 된다.
react-native-git-upgrade
를 전역으로 설치한다:
$ npm install -g react-native-git-upgrade
또는 Yarn을 사용한다:
$ yarn global add react-native-git-upgrade
그런 다음, 프로젝트 디렉터리 안에서 실행한다:
$ cd MyProject
$ react-native-git-upgrade 0.38.0
참고:
react-native
의 새 버전을 설치하기 위해 'npm install'을 실행하지 않는다. 이 도구는 이전과 새로운 프로젝트 템플릿을 비교할 수 있어야 정상적으로 작동한다. 위에서 보여준 대로 앱 폴더 안에서 실행하면 된다. 이때 아직 이전 버전에 머물러 있어야 한다.
예제 출력:
react-native-git-upgrade
를 인수 없이 실행하면 React Native의 최신 버전으로 업그레이드한다.
Android와 iOS 빌드 파일에서 변경 사항을 보존하려고 노력하므로, 업그레이드 후 react-native link
를 실행할 필요가 없다.
구현을 최대한 간섭하지 않도록 설계했다. 임시 디렉터리에 생성된 로컬 Git 저장소를 기반으로 작동한다. 프로젝트 저장소에 영향을 미치지 않는다 (Git, SVN, Mercurial 등 어떤 VCS를 사용하든 상관없다). 예기치 않은 오류가 발생하면 소스가 복원된다.
어떻게 동작하나요?
핵심 단계는 Git 패치를 생성하는 것이다. 이 패치는 앱이 사용 중인 버전과 새로운 버전 사이의 React Native 템플릿에 적용된 모든 변경 사항을 포함한다.
이 패치를 얻으려면 node_modules
디렉토리 내부의 react-native
패키지에 포함된 템플릿으로 앱을 생성해야 한다. 이 템플릿은 react-native init
명령어가 사용하는 것과 동일하다. 그런 다음 현재 버전과 새 버전의 템플릿으로 각각 네이티브 앱을 생성한 후, Git은 프로젝트에 맞게 조정된 패치를 생성할 수 있다. 이 패치는 앱 이름과 같은 프로젝트별 정보를 포함한다.
[...]
diff --git a/ios/MyAwesomeApp/Info.plist b/ios/MyAwesomeApp/Info.plist
index e98ebb0..2fb6a11 100644
--- a/ios/MyAwesomeApp/Info.plist
+++ b/ios/MyAwesomeApp/Info.plist
@@ -45,7 +45,7 @@
<dict>
<key>localhost</key>
<dict>
- <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
+ <key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
[...]
이제 이 패치를 소스 파일에 적용하기만 하면 된다. 이전 react-native upgrade
프로세스는 작은 차이점도 사용자에게 물어보곤 했지만, Git은 3-way 병합 알고리즘을 사용해 대부분의 변경 사항을 자동으로 병합할 수 있다. 결국 익숙한 충돌 구분자를 남긴다.
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
<<<<<<< ours
CODE_SIGN_IDENTITY = "iPhone Developer";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/HockeySDK.embeddedframework",
"$(PROJECT_DIR)/HockeySDK-iOS/HockeySDK.embeddedframework",
);
=======
CURRENT_PROJECT_VERSION = 1;
>>>>>>> theirs
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)/../node_modules/react-native-code-push/ios/CodePush/**",
);
이러한 충돌은 일반적으로 이해하기 쉽다. 구분자 ours는 "여러분의 팀"을 의미하고, theirs는 "React Native 팀"으로 볼 수 있다.
새로운 글로벌 패키지를 도입하는 이유
React Native는 기본적으로 전역 CLI(react-native-cli 패키지)를 제공한다. 이 CLI는 node_modules/react-native/local-cli
디렉토리에 내장된 로컬 CLI로 명령을 위임한다.
앞서 언급했듯이, 이 프로세스는 현재 사용 중인 React Native 버전에서 시작해야 한다. 만약 이 기능을 로컬 CLI에 내장했다면, 이전 버전의 React Native를 사용할 때 이 기능을 활용할 수 없게 된다. 예를 들어, 0.29.2 버전에서 0.38.0 버전으로 업그레이드하려면 이 새로운 업그레이드 코드가 0.38.0 버전에서만 출시되었다면 업그레이드가 불가능하다.
Git 기반의 업그레이드는 개발자 경험을 크게 개선하며, 모든 사람이 이를 사용할 수 있도록 하는 것이 중요하다. 전역으로 설치되는 별도의 패키지인 react-native-git-upgrade를 사용하면 현재 프로젝트가 어떤 React Native 버전을 사용하든 상관없이 이 새로운 코드를 바로 활용할 수 있다.
또 다른 이유는 Martin Konicek의 최근 Yeoman 제거이다. 패치를 생성하기 위해 이전 템플릿을 평가하려면 react-native
패키지에 Yeoman 의존성을 다시 추가해야 하는데, 이를 원하지 않았다.
직접 사용해 보고 피드백을 제공하세요
결론적으로, 이 기능을 즐기고 개선 사항을 제안하거나 문제를 보고하고 특히 풀 리퀘스트를 보내주세요. 각 환경은 조금씩 다르고, 각 React Native 프로젝트도 다릅니다. 여러분의 피드백이 필요하니, 이 기능이 모두에게 잘 동작할 수 있도록 도와주세요.
감사의 말
이 모든 것이 가능하도록 도와주신 멋진 회사 Zenika와 M6 Web (archived)에게 깊은 감사를 드립니다!