오늘 배운 것

오늘은 어제 회고에서 느낀 것처럼 현재 배포에서 막히고 있는 프론트 쪽 이슈를 같이 해결해보려고 한다. 현재 프론트에서 앱 배포를 하다가 막힌 상황이고, 잠시 팀원이 자리를 비운 사이에 조금이라도 일을 진행시키는 것이 오늘과 내일의 목표가 되겠다. 팀원에게 듣기로는 현재 expo를 사용해서, eas build를 production 모드로 진행한 다음 aab(abb?) 파일을 구글 플레이스토어에 업로드하면 된다고 한다.

 

다행히 여러 블로그 글에 관련된 설명이 나와 있었다. 우선 첫 번째로 Keystore를 생성해야 했다. Keystore란 RN에서 안드로이드 용 RN 실행 바이너리 파일을 만드는 데 사용되는 일종의 파일과 관련이 있었다. 생성하는 명령어가 있어서 우선 따라해 보려고 했다.

 

그런데 그 문제는 아닌 듯 하다. 

 

팀원이 말해주기를 이런 과정들은 전부 잘 되고, '스플래시 화면이 두 개 뜨는 문제'와 '특정 안드로이드 버전에서 크래시가 나는 문제'를 해결해야 빌드를 완전히 할 수 있다고 한다. 해당 부분은 구글 플레이 콘솔에서 확인할 수 있었다. 

 

특히 '장애'라고 표시된 에러의 경우 로그는 다음과 같았다. 

Process: com.safezone.onestep
PID: 9158
UID: 10163
Flags: 0x20a8be44
Package: com.safezone.onestep v1 (1.0.1)
Foreground: No
Process-Runtime: 49340
Build: Google/Small Desktop (x86)/SmallDesktop.x86:12/SE2B.220326.027/9241628:userdebug/dev-keys
Loading-Progress: 1.0

java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@aa88f1f rejected from java.util.concurrent.ScheduledThreadPoolExecutor@65a926c[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 5]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2086)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:848)
	at java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor.java:334)
	at java.util.concurrent.ScheduledThreadPoolExecutor.schedule(ScheduledThreadPoolExecutor.java:562)
	at java.util.concurrent.ScheduledThreadPoolExecutor.submit(ScheduledThreadPoolExecutor.java:664)
	at java.util.concurrent.Executors$DelegatedExecutorService.submit(Executors.java:640)
	at io.sentry.android.replay.ScreenshotRecorder.capture$lambda$4$lambda$3(ScreenshotRecorder.kt:125)
	at io.sentry.android.replay.ScreenshotRecorder.$r8$lambda$SsuasLI-_UYp4uMsgoefgMADVBI(Unknown Source:0)
	at io.sentry.android.replay.ScreenshotRecorder$$ExternalSyntheticLambda2.onPixelCopyFinished(Unknown Source:6)
	at android.view.PixelCopy$1.run(PixelCopy.java:191)
	at android.os.Handler.handleCallback(Handler.java:938)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at androidx.test.espresso.base.Interrogator.loopAndInterrogate(Interrogator.java:10)
	at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:7)
	at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:1)
	at androidx.test.espresso.base.UiControllerImpl.loopMainThreadForAtLeast(UiControllerImpl.java:7)
	at androidx.test.espresso.action.Tap$1.sendTap(Tap.java:4)
	at androidx.test.espresso.action.GeneralClickAction.perform(GeneralClickAction.java:4)
	at androidx.test.espresso.ViewInteraction$SingleExecutionViewAction.perform(ViewInteraction.java:2)
	at androidx.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:23)
	at androidx.test.espresso.ViewInteraction.-$$Nest$mdoPerform(Unknown Source:0)
	at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:6)
	at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:1)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at android.os.Handler.handleCallback(Handler.java:938)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at android.app.ActivityThread.main(ActivityThread.java:7870)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

 


우선 우리가 Expo EAS build의 최신 버전에서 앱을 다운받았을 때는 셋 다 아무런 문제가 없었어서, 특정 버전의 문제일 수도 있다고 생각했다. 그렇다면 어떻게 해결해야 할까? 여기서 사용한 안드로이드 에뮬레이터는 SDK 32 버전, 안드로이드 12 버전이었다(Android 12L, SDK 32). 에러를 재현해서 문제를 알아보려면 해당 안드로이드 에뮬레이터로 한번 실행을 시켜봐야 하겠다. 화면 크기나 다른 건 상관없어도, 안드로이드 버전이 12L, SDK 32이면서 ABI가 x86_64인 에뮬레이터를 만들어 보자.

 

그런데 생각해보면 우리가 다 안드로이드 에뮬레이터 설정을 했을 때 API 33 이상으로 했었고, 그 때 나름의 이유가 있었던 것으로 기억한다. 그 모종의 이유 때문에 에러가 난 것은 아니었을까 싶다. 왜냐하면 에러 로그를 봤을 때 java나 android 관련 에러로 보였기 때문이다. 그렇다면 그걸 우리가 해결할 의무가 있을까? 라는 의문이 들었다. 그러다가 출시 개요의 App Bundle을 봤을 때, API 수준이 23 이상이면 사용 가능한 것으로 되어 있었다. 그렇다면 동영상에서 API 32로 테스트하는 것이 말이 된다. 내가 API 수준과 타겟팅 API에 대해서 혼동했던 것 같다. 

 

아무튼 그래서 안드로이드 에뮬레이터를 받아서 실행을 하려는데 실행 자체가 안 된다. 

 

우선 SDK Manager에서 SDK 32를 설치해 줬는데도 같은 에러가 난다. 

 

오류가 발생하는 원인은 여러 가지일 수 있겠다. 우선 x86_64는 Intel 기반 버전이다. mac OS는 기본 apple silicon이기 때문에 intel 기반의 프로그램을 실행하려면 'Rosetta 2'라는 일종의 번역 레이어가 필요하다고 한다. 그래서 이를 설치해서 x86_64 버전의 에뮬레이터를 실행해 보기로 했다. 우선 Rosetta 2는 설치하였으나, 또 같은 에러가 났다. 알고보니 apple silicon에서는 arm 버전의 에뮬레이터를 사용하는 것이 좋다고 한다. 

 

아무튼, 그래서 SDK 32, Android 12L 버전의 arm 에뮬레이터를 다시 설치해봤다. arm 에뮬레이터를 설치해봤더니 앱 설치 및 로그인 화면까지 잘 떴다. 그런데 이러면 안 되는게, 구글 플레이 콘솔의 동영상에서는 아예 앱이 실행조차 안 되었다. 실행이 된다는 것 자체가 문제 상황과 다르다는 거였다. 

 

그런데 여기서 제시하는 방법은 API 버전을 바꾸라거나, x86_64 대신 arm을 사용하라던가 하는, 지금 현재 우리의 상황에는 도움이 되지 않는 방법들이었다. 우선은 멘토님께 도움을 요청해보고, 추가적인 방법을 찾아봐야겠다. 


우선 우리의 목표는 에러 재현을 하고 그 다음에 에러를 해결하는 것이다. 지금 에러 재현이 안 되고 있으니, intel을 사용하는 환경을 만들어 줘야 하겠다. 가장 먼저 생각난 방법은 hypervisor였다. hypervisor란 일종의 소프트웨어로, '단일 물리적 머신에서 여러 개의 가상 머신을 사용할 수 있도록 해 주는 소프트웨어'라고 한다. 이걸 사용해서 mac에서 window 가상 머신을 실행시켜서, 해당 가상 머신에서 또 에뮬레이터를 띄워 보는 것이다... 쓰다 보니 이게 맞나 싶은데, 윈도우 노트북이 없으니 별 수 없다. 

 

맥 환경에서 사용가능한 오픈소스 소프트웨어인 virtualbox를 사용해보기로 했다. 그런데 공식 홈페이지에서는 arm 버전을 제공하는 것이 없었는데, 구글링해서 찾은 한 블로그로부터 테스트 버전으로 arm 버전의 virtualbox가 있다는 것을 알 수 있었다. 

 

무사히 virtualbox를 설치해 주고, 가상환경을 위해 필요한 윈도우 ISO도 설치해 주었다. 

 

 궁금한 점

1. keystore가 뭘까?

2. intel 기반과 apple silicon 기반이 다르다는 건 알고 있었는데 뭐가 어떻게 다른건지 스스로 잘 모르는 것 같다. 알아보자. 

3. ISO는 무엇인가

 

오늘의 러닝 인증!

 

+ Recent posts