React Native 앱 개발에서 Debug(디버그)와 Release(릴리즈) 빌드는 단순히 "개발용"과 "배포용"이라는 차이를 넘어, 앱의 구동 방식과 성능 자체가 완전히 다르다.
이 둘의 기술적인 차이점과 작동 원리를 상세하게 살펴보자.
Debug Build (개발 모드)
개발자가 코드를 작성하고 수정하는 과정에서 사용하는 모드이다. 편의성에 모든 초점이 맞춰져 있다.
- Metro Bundler와의 연결되어 있으며 Debug로 빌드된 앱은 빈 껍데기에 가까움
- 앱이 실행되면 내부적으로
localhost:8081 (Metro Bundler 서버)에 접속해서 JavaScript 번들(코드)을 실시간으로 다운로드 받아서 실행함.
- 이 때문에 개발 중에 코드를 고치고 저장(Save)만 하면, 앱이 다시 다운로드 받아서 화면을 즉시 갱신(Fast Refresh)할 수 있는 것이다.
주요 특징
__DEV__ 변수가 true로 설정됨
- Minification (코드 압축) 없음 : 에러가 났을 때 몇 번째 줄인지 알아야 하므로, 코드가 압축되지 않고 사람이 읽을 수 있는 상태로 유지된다.
- RedBox / LogBox : 에러가 발생하면 앱이 꺼지는 대신, 화면에 빨간색 에러 로그 창을 띄워줌
- 성능 저하 : 개발 편의를 위한 온갖 로깅, 유효성 검사(PropType Check), 디버깅 툴 연결 기능이 켜져 있어서 앱이 무겁고 느리다. 특히 애니메이션이나 제스처가 버벅거릴 수 있다.
Release Build (배포 모드)
실제 사용자에게 배포되거나, 스토어에 업로드할 때 사용하는 모드이다. "성능"과 "안정성"에 모든 초점이 맞춰져 있다.
- 오프라인 번들링 (Offline Bundling)이며 Metro 서버가 필요 없다.
- 빌드 시점에 JS 코드를 하나의 파일(
index.android.bundle / main.jsbundle)로 합쳐서 앱 내부에 심어버린다.
- 사용자는 인터넷 연결 없이도 이 심어진 파일을 통해 앱을 실행한다.
주요 특징
__DEV__ 변수가 false로 설정됨
- 코드를 압축(공백 제거)하고 난독화(변수명을 a, b로 변경)한다. 때문에 용량이 획기적으로 줄어들고 실행 속도가 빨라진다.
if (__DEV__) { ... } 안에 있는 개발용 코드를 아예 삭제해 버린다.
- React Native 프레임워크 내부의 최적화 기능이 활성화된다.
- Hermes 엔진을 쓴다면, JS 코드를 미리 기계어에 가까운 바이트코드(Bytecode)로 변환해 둔다. (앱 켜지는 속도가 2배 이상 빨라짐)
- 컴퓨터와 usb 연결이 끊겨있어도, 컴퓨터를 종료해도 폰에서 영구적으로 사용 가능
- Debug 빌드는 "스트리밍"이다. 앱 껍데기만 폰에있고, 알맹이는 컴퓨터의 Metro Bundler에서 실시간으로 불러오기에 이 연결다리 (USB) 가 없으면 앱은 작동하지 않는다.
- Release 빌드는 "다운로드"이다. 빌드하는 순간 컴퓨터에 있던 모든 JS코드와 이미지들을 압축해서 앱 설치 파일(APK / IPA)안에 꽉 채워넣는다. 때문에 폰에 설치된 후에는 컴퓨터가 필요 없다. 이미 모든 파일이 폰 안에 있기 때문이다.
Debug vs Release 상세 비교
| 특징 | Debug Build (개발용) | Release Build (배포용) |
|---|
| JS 코드 위치 | Metro 서버 (localhost)에서 실시간 전송 | 앱 바이너리 내부에 내장됨 (Embed) |
| 실행 속도 | 느림 (로깅, 디버깅 오버헤드 큼) | 매우 빠름 (최적화됨) |
| 파일 용량 | 큼 (디버깅 심볼 포함) | 작음 (압축 및 난독화) |
| 에러 발생 시 | RedBox (빨간 화면) 뜸 | 앱이 즉시 종료됨 (Crash) |
| 개발자 메뉴 | 흔들거나 단축키로 진입 가능 | 비활성화됨 (접근 불가) |
| 로그 (console) | 터미널/브라우저에 출력됨 | 출력되지 않음 (일부 무시됨) |
| Hermes | JS 소스로 실행 (일반적으로) | 바이트코드로 미리 컴파일됨 |
유의사항
1) 애니메이션이 너무 버벅거린다
- 원인 : Debug 모드에서 테스트했기 때문일 확률이 90%이다.
- 해결 : Release 빌드로 폰에 설치해서 테스트해보자. Debug 모드는 JS 스레드가 로깅하느라 바빠서 애니메이션 프레임을 놓친다. Release에서는 부드러워질 수 있다.
2) 시뮬레이터에선 잘 되는데 폰에선 안 된다?
- Debug 빌드는 Metro 서버(컴퓨터)랑 같은 네트워크에 있어야 한다. 폰이랑 컴퓨터가 다른 와이파이를 쓰고 있으면 앱이 켜지자마자 꺼지거나 흰 화면만 나온다.
3) Release 빌드에서만 앱이 죽는다
- 원인 1 (Proguard/R8) : 안드로이드의 경우 코드 난독화 도구(R8)가 너무 공격적으로 코드를 줄이다가, 필수 라이브러리 코드까지 삭제해서 발생하는 경우가 많습니다. (
proguard-rules.pro 설정 필요)
- 원인 2 (이미지/폰트) : Debug 때는 Metro가 파일을 잘 찾아줬는데, Release 때는 경로 설정 실수로 에셋을 못 찾아서 죽을 수 있다.
실행 명령어 차이
1) iOS
- Debug:
npx react-native run-ios (기본값)
- Release:
npx react-native run-ios --mode Release (Xcode 설정에 따라 다름)
2) Android
- Debug:
npx react-native run-android
- Release:
npx react-native run-android --mode=release
개발할 때는 Debug가 주는 편리함(Fast Refresh)을 누리되, 성능 테스트나 배포 전 최종 확인은 반드시 Release 빌드로 해야 한다. Debug 모드의 성능은 진짜 성능이 아니기 때문이다.