개요
릴리스 빌드는 웹처럼 DevTools 콘솔을 띄울 수 없음. 대신 다음 루틴으로 본다:
1) 실기기 로그캡처(adb logcat / Xcode Console)
2) 크래시/ANR 리포트(Play Console)
3) 원격 에러 수집(Sentry/Crashlytics)
4) 필요시 OTA(Expo Updates)로 “진단용 JS”를 푸시해 현장에서 확인
목표: 크래시 전후의 스택/네트워크/환경변수 상태를 확보 → 원인 확정
Step 1. 기본 준비(안드로이드)
1) 기기 설정 → 휴대전화 정보 → 빌드 번호 7회 탭 → 개발자 옵션 활성화
2) 개발자 옵션 → USB 디버깅 ON (무선 디버깅을 써도 됨: Android 11+)
3) PC에 Android Platform Tools 설치(adb 포함)
4) 앱 패키지명 확인(예: com.stockexam.app)
Step 2. 실시간 로그캡처(adb logcat) – 가장 먼저, 가장 강력
# 0) 기기 연결 확인
adb devices
# 1) 앱 PID 얻기
adb shell pidof -s com.stockexam.app
# 2) JS/React Native/크래시 위주로 필터링(시간 포함)
adb logcat --pid=$(adb shell pidof -s com.stockexam.app) -v time ReactNative:V ReactNativeJS:V AndroidRuntime:E System.err:W *:S
# 3) 파일로 저장(재현 타임라인 분석용)
adb logcat --pid=$(adb shell pidof -s com.stockexam.app) -v time > app_release.log
# 4) (윈도우 CMD용 findstr 예시 – Bash가 아닌 경우)
adb logcat -v time | findstr /I "AndroidRuntime ReactNativeJS ReactNative System.err"
Step 3. 로그 패턴
- TypeError: Invalid URL / URL(...) 실패 → 환경변수/베이스URL 오기입(빈 값/placeholder/슬래시중복)
- 401/403 / AuthApiError / Invalid JWT → 키 잘못/권한 정책/만료
- UnknownHostException → 도메인 오타/DNS/오프라인
- SSLHandshakeException → SSL 인증서 문제
- CLEARTEXT not permitted → http 사용(네트워크 보안 설정 필요)
- Network request failed → 네트워크 차단/권한/프록시
핵심: 에러 메시지+발생 라인+직전 네트워크 요청을 같은 타임라인에서 묶어 해석
Step 4. Play Console에서 크래시/ANR 확인
경로: Google Play Console → 앱 → 품질 → Android Vitals → Crashes & ANRs
- 릴리스에서 JS 예외가 네이티브로 전파되면 cohttp://m.facebook.react.common.JavascriptException 등으로 보일 수 있음
- Pre-launch report도 참고(자동 테스트 중 크래시/권한/네트워크 이슈 힌트)
- 단, JS 소스맵 없으면 스택이 난독화되어 가독성 떨어짐 → Step 5로 보완
Step 5. 원격 에러 수집 도입(Sentry/Crashlytics) – JS 소스맵까지
1) 라이브러리 추가(sentry-expo 또는 @sentry/react-native, Crashlytics도 대안)
2) 앱 초기화 코드에 Sentry.init(...) 등 최소 설정
3) 빌드 파이프라인에서 JS 소스맵 업로드(리포트를 사람이 읽을 수 있는 스택으로)
4) 배포 후 크래시 재현 → 대시보드에서 스택/브레드크럼/디바이스 정보를 기반으로 추적
Tip) Hermes 엔진 사용 시 JS 소스맵 업로드가 특히 중요. 그래야 의미 있는 스택을 얻음
Step 6. OTA(Expo Updates)로 “진단용 JS” 푸시(재빌드 없이 빠른 확인)
개념: 같은 channel + 같은 runtimeVersion에서 JS만 교체 가능. 진단 전용 화면을 임시로 추가해 실제 주입된 ENV/네트워크를 눈으로 확인.
(예시 컴포넌트 – app/debug/env.tsx; 테스트 후 삭제)
- 현재 인라인된 EXPO_PUBLIC_* 값을 즉시 표시
- /auth/v1/health 등 가벼운 핑으로 통신상태 확인
use: /debug/env 라우트로 진입해 값/응답 코드 확인
Step 7. 환경변수 이슈를 막는 가드(React Native/Expo)
- 클라이언트에서 쓰는 값은 process.env.EXPO_PUBLIC_* 로 “직접” 참조
- 빌드 전 verify-env 스크립트로 필수 키/URL 형식 점검(누락 시 빌드 실패)
- 코드에서 createClient 전에 URL/KEY 유효성 검사(에러 메시지를 명확히)
- OTA로는 네이티브에 박힌 값은 못 바꿈 → JS에서 읽는 공개키만 OTA로 교정 가능
Step 8. 전체 디버깅 체크리스트(릴리스 기준)
[준비] 개발자옵션/ADB/패키지명 확인
[로그] adb logcat으로 PID 고정 + 태그 필터링 + 파일 저장
[재현] 버그 시나리오를 동일하게 실행(시간 표시를 기준으로 전후 로그 캡처)
[분석] 에러 패턴 → 원인 가설(ENV/네트워크/권한/코드)
[수집] Play Console / Sentry/Crashlytics 대시보드와 대조(스택/기기/OS)
[교정] 빠른 건 OTA 진단 패치, 구조 이슈면 재빌드
[재발방지] verify-env, 소스맵 업로드, 가드 코드, 테스트 케이스 추가
마무리
- 릴리스 빌드는 “보는 창”이 다를 뿐, 충분히 디버깅 가능하다.
- 우선 adb logcat으로 사실을 확보 → 대시보드/원격 수집으로 교차검증 → 필요시 OTA로 현장 진단 → 확정 뒤 재빌드.
- 커스텀 템플릿(로그 필터 스크립트/verify-env/진단 화면)만 갖추면 다음 번엔 10분 안에 원인 잡는다.