해결 방법
package.json 에서 expo-cli 를 삭제
문제 상황
회사에서 인력이 부족해서 한 두 달정도 다른 프로젝트를 하고 다시 앱 개발하려 돌아오니 expo 48 버전이 릴리즈 되어있었다. 가능하면 최대한 최신 버전을 사용하려고 하기 때문에 큰 걱정 없이 업데이트하고 테스트하고 안드로이드 apk 생성을 위한 빌드를 진행하였다. 그런데 코드는 달라진게 없는데 빌드 에러가 발생하였다.
해결 과정
원인 파악
막연하게 떠오른 이유는 아래와 같다.
- expo 48 버전의 문제
- expo 48 버전으로 업데이트함과 동시에 다른 라이브러리를 업데이트하면서 문제 발생
- 일시적 expo 빌드 시스템의 문제
1번의 경우를 확인하기 위해 github expo issue 에 들어가 확인해보니 다른 사용자는 잘 사용하고 있었다. 그리고 배포된지 대략 한 달정도 되었기 때문에 expo 48 버전의 문제는 아닌 것으로 판단하였다.
2번의 경우를 확인하기 위해 기존 버전으로 돌려놓고 expo 만 48 버전으로 변경하여 빌드해보았다. 그런데 똑같이 빌드 에러가 발생하였다. 즉 expo 48 자체만으로도 에러가 발생하는 것을 확인하였다.
3번의 경우를 확인하기 위해 시간 텀을 두고 대략 3번정도 re-build 를 시도하였는데 에러가 발생하였다. 그래서 expo 빌드 시스템의 문제는 아닌 것으로 판단하였다.
이로써 큰 범주의 문제는 아닌 것으로 판단되었다. 즉 세밀히 들여다볼 필요가 있다. 우선 에러의 문구를 확인해보았다.
[stderr] /home/expo/workingdir/build/app/mymemory/android/app/src/main/java/kr/co/mymemory/MainActivity.java:19: error: package R does not exist
[stderr] setTheme(R.style.AppTheme);
[stderr] ^
[stderr] /home/expo/workingdir/build/app/mymemory/android/app/src/main/java/kr/co/mymemory/MainActivity.java:39: error: cannot find symbol
[stderr] return new ReactActivityDelegateWrapper(this, BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, new DefaultReactActivityDelegate(
[stderr] ^
[stderr] symbol: variable BuildConfig
[stderr] location: class MainActivity
[stderr] /home/expo/workingdir/build/app/mymemory/android/app/src/main/java/kr/co/mymemory/MainApplication.java:26: error: cannot find symbol
[stderr] return BuildConfig.DEBUG;
[stderr] ^
[stderr] symbol: variable BuildConfig
[stderr] /home/expo/workingdir/build/app/mymemory/android/app/src/main/java/kr/co/mymemory/MainApplication.java:45: error: cannot find symbol
[stderr] return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
[stderr] ^
[stderr] symbol: variable BuildConfig
[stderr] /home/expo/workingdir/build/app/mymemory/android/app/src/main/java/kr/co/mymemory/MainApplication.java:50: error: cannot find symbol
[stderr] return BuildConfig.IS_HERMES_ENABLED;
[stderr] ^
[stderr] symbol: variable BuildConfig
[stderr] /home/expo/workingdir/build/app/mymemory/android/app/src/main/java/kr/co/mymemory/MainApplication.java:63: error: cannot find symbol
[stderr] if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
[stderr] ^
[stderr] symbol: variable BuildConfig
[stderr] location: class MainApplication
[stderr] /home/expo/workingdir/build/app/mymemory/android/app/src/main/java/kr/co/mymemory/MainApplication.java:63: error: illegal parenthesized expression
[stderr] if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
[stderr] ^
[stderr] /home/expo/workingdir/build/app/mymemory/android/app/src/main/java/kr/co/mymemory/MainApplication.java:67: error: cannot find symbol
[stderr] ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
[stderr] ^
[stderr] symbol: variable ReactNativeFlipper
[stderr] location: class MainApplication
[stderr] 8 errors
에러 스택에서 가장 하단을 보니 ReactNativeFlipper 에서 에러가 시작되었다. 그렇기에 ReactNativeFlipper 를 토픽으로 검색을 하였는데 대체로는 android 파일을 수정하라는 것이였는데 필자의 경우는 expo managed 를 사용하여 안드로이드 파일이 없다. 그렇기에 다른 해결 방법을 더 찾다보니 눈에 들어온 것은 중복 클래스가 있으면 에러를 발생한다는 것이였다.
그래서 생각한 원인은 package 가 꼬였다는 것이다.
expo 의 경우는 expo doctor
를 통해 프로젝트 진단을 제공한다.
expo doctor 실행하였더니 문제가 여럿 보고되었다.
기대하는 패키지 버전과 다른 것들이 목록으로 출력해주었다.
이를 통해 우선 expo-modules-autolinking 의 문제를 더 들여다보기 위해 npm why expo-modules-autolinking
을 실행하였다.
expo-modules-autolinking 을 사용하고 있는 부분을 찾아보니 아래와 같이 정리할 수 있다.
- expo 안에 expo-modules-autolinking
- @expo/prebuild-config 안에 expo-modules-autolinking
- expo-cli 안에 @expo/prebuild-config
이를 트리로 나타내면 아래와 같다.
- expo
- expo-modules-autolinking
- expo-cli
- @expo/prebuild-config
- expo-modules-autolinking
- @expo/prebuild-config
해결 작업
expo-modules-autolinking 가 충돌나고 있는 것은 expo 와 expo-cli 두 개의 패키지 때문이라는 것을 알 수 있다.
만약 둘 다 필수적이라면 해결 방법이 더 복잡해질 수 있으나 사실 expo-cli 는 전역 패키지로 package.json 에서 관리될 필요 없다.
그렇기에 expo-cli 를 삭제하고 다시금 패키지를 설치하였다. 그 후 다시 expo doctor
를 실행하였다.
그 결과 리포트의 결과가 6개에서 1개로 줄었다. 그래서 다시 expo apk 빌드를 진행하였다.
결과는 성공적으로 expo 버전이 업그레이드 되었다.
결과론적으로 어떤 부분을 놓치고 의식하지 못해 이런 문제가 발생하게 되었는지 돌아보았다. 그 결과 프로답지 못한 부분이 있었는데 빌드 process 에는 expo doctor 를 실행하는 단계가 있다. 이미 빌드 시스템은 문제가 있다고 누차 이야기하고 있었다. 이를 무시하고 진행한 이유는 사실 이전부터 이러한 출력이 있었기 때문이다. 그런데 빌드가 성공적으로 되고 앱 실행이 되니 중요하지 않다고 넘기고 있다가 이제서야 수면 위로 올라오게 된 것이다.
항상 느끼지만 의식하지 못할 때 문제가 생긴다. 지금 당장 넘어가고 불편함이 익숙해질 때 이미 병은 점점 악화되어가고 있다가 큰 문제로 다가온다. 제일 큰 문제는 문제가 생기기 전까지 의식하지 못한다는 것이다. 이럴 때마다 다짐하지만 반복된다. 그렇지만 긍정적인 것은 점점 성장하고 이러한 경험을 잘 정리해서 다음에는 방지하기 위한 토대로 쌓기 때문이다.
문제가 되었던 expo-cli 를 지우니 빌드 시스템에서는 이제 문제가 없다고 알려준다.
결론
에러만 고쳐야할 것이 아니라 warning 도 신경 쓰고 원인 파악을 해야한다. 이 작업이 건강검진이라고 볼 수 있다.