APK 빌드 환경

APK 빌드 환경

- Windows React Native APK 경로 제한 해결법 -

1. 요약

Windows에서 Expo CNG 기반 React Native 앱의 Android APK 빌드가 아래와 같이 실패할 수 있습니다.

ninja: error: Stat(...): Filename longer than 260 characters

이 문제는 앱 코드 문제가 아니라 Windows 경로 길이 제한과 CMake/Ninja의 네이티브 빌드 산출물 경로 구조 때문에 발생합니다.

권장 해결 방법은 다음 세 가지입니다.

  1. 프로젝트 루트에 Junction을 만들어 빌드 실행 경로를 짧게 만든다.

  2. CMake의 buildStagingDirectory를 짧은 절대 경로로 옮긴다.

  3. 기존 .cxx 캐시를 삭제한 뒤 전체 재구성을 수행한다.

Junction 생성 → buildStagingDirectory 지정 → android/app/.cxx 삭제 → 재빌드

subst 가상 드라이브는 경로를 줄일 수는 있지만, Metro·realpath·Gradle 캐시 경로가 섞이며 다른 문제를 만들 수 있어 사용하지 않습니다.

2. 원인

Windows의 일반적인 Win32 경로 길이 제한은 MAX_PATH, 즉 260자입니다. Windows의 Long Path 설정을 활성화해도, 실제로 그 기능을 사용할 수 있도록 준비되지 않은 도구는 여전히 긴 경로에서 실패할 수 있습니다.

React Native의 New Architecture 또는 자동 연결된 네이티브 모듈은 CMake와 Ninja를 통해 C++ 코드를 빌드합니다. 이때 오브젝트 파일 경로가 매우 길어질 수 있습니다.

<빌드 스테이징 경로>/<빌드 타입>/<해시>/<ABI>/
<target>_autolinked_build/CMakeFiles/<target>.dir/
<원본 소스 경로를 포함한 경로>

특히 node_modules 아래의 긴 C++ 소스 경로가 오브젝트 파일 경로에 다시 포함됩니다. 프로젝트 경로가 깊고 react-native-screens, safe-area-context 같은 네이티브 패키지가 추가되면 260자를 쉽게 초과합니다.

다음은 스테이징 위치에 따른 가장 긴 오브젝트 파일 경로의 예시입니다.

빌드 경로

가장 긴 오브젝트 경로

결과

정규 프로젝트 경로 + 기본 .cxx

331자

실패

Junction 경로 + 기본 .cxx

290자

실패

Junction 경로 + 짧은 스테이징 경로

248자

성공

프로젝트 루트만 짧게 만드는 것으로는 부족하고, CMake 중간 산출물 위치까지 짧게 만들어야 합니다.

3. 적용 방법

3.1 Junction 생성

프로젝트가 긴 경로에 있다면, 모노레포 루트를 짧은 경로에 Junction으로 연결합니다.

cmd /c mklink /J C:\v "C:\Users\<사용자>\<긴 경로>\<프로젝트 루트>"

이후 네이티브 빌드는 Junction 경로에서 실행합니다.

C:\v\<프로젝트 경로>

Junction은 같은 볼륨의 실제 디렉터리 엔트리로 동작합니다. subst처럼 가상 드라이브 루트가 별도로 생기는 방식보다 파일 시스템 경로 해석이 일관적입니다.

3.2 CMake 스테이징 경로 단축

android/app/build.gradle의 android {} 블록에 아래 설정을 추가합니다.

externalNativeBuild {
    cmake {
        buildStagingDirectory = file("C:/cxx-build")
    }
}

buildStagingDirectory는 CMake 외부 네이티브 빌드 산출물과 Ninja 관련 파일이 생성되는 위치를 지정합니다. 기본 .cxx 경로 대신 짧은 루트 경로를 사용해 오브젝트 파일 전체 길이를 줄입니다.

3.3 기존 CMake 캐시 삭제

경로 설정을 바꾼 뒤에는 기존 캐시를 반드시 삭제합니다.

rm -rf android/app/.cxx

Windows PowerShell에서는 아래와 같이 실행할 수 있습니다.

Remove-Item -Recurse -Force android\app\.cxx

CMake 캐시에는 최초 구성 당시의 정규 경로가 저장될 수 있습니다. 캐시를 삭제하지 않으면 Junction과 짧은 스테이징 경로를 적용했어도 이전 긴 경로가 계속 사용될 수 있습니다.

3.4 빌드 실행

네이티브 빌드는 Junction 경로에서 실행합니다.

.\gradlew.bat assembleRelease --max-workers=2

릴리즈 빌드 전에는 Metro와 여러 웹 개발 서버를 종료하는 것을 권장합니다. 메모리 경합으로 Gradle Worker Daemon 오류가 발생할 수 있기 때문입니다.

4. 운영 원칙과 주의사항

subst 대신 Junction을 사용한다

subst는 경로를 짧은 드라이브 문자로 매핑할 수 있지만, 가상 드라이브 경로와 실제 C: 경로가 함께 사용되면 아래 문제가 발생할 수 있습니다.

  • Codegen에서 서로 다른 루트 경로 오류 발생

  • Metro에서 워크스페이스 패키지 또는 alias 해석 실패

  • Gradle 전역 캐시에 저장된 정규 경로와 충돌

  • 재부팅 후 매핑이 사라져 매번 다시 설정 필요

따라서 경로 단축 목적에는 Junction을 사용합니다.

Metro는 정규 경로에서 실행한다

네이티브 Gradle 빌드는 Junction 경로에서 실행하지만, Metro는 정규 프로젝트 경로에서 실행합니다.

작업

실행 경로

네이티브 C++ 빌드 (gradlew, expo run:android)

Junction 경로

Metro 번들러 (expo start)

정규 C: 경로

일부 Expo/React Native 프로젝트는 TypeScript paths, Babel 또는 Metro 설정 기반 alias와 워크스페이스 패키지 해석에 의존합니다. Metro를 Junction 경로에서 실행하면 프로젝트 루트와 파일의 realpath가 어긋나 alias 또는 워크스페이스 패키지 해석 문제가 발생할 수 있습니다.

Expo CNG 생성물임을 인지한다

android/ 폴더는 Expo CNG가 생성하는 결과물입니다. expo prebuild --clean을 실행하면 android/app/build.gradle에 직접 넣은 buildStagingDirectory 설정이 사라질 수 있습니다.

이 설정은 Windows 로컬 빌드의 중간 산출물 경로만 바꾸며, APK 결과물에는 영향을 주지 않습니다. 따라서 Windows에서 네이티브 빌드를 담당하는 사람이 수동으로 적용하는 방식으로 운영할 수 있습니다.

장기적으로 자동화가 필요하면, Windows 사용자만 선택적으로 값을 제공할 수 있도록 Gradle Property 기반 opt-in 방식을 검토합니다. 절대 경로를 Config Plugin으로 모든 OS와 EAS 빌드에 강제 주입하면 안 됩니다.

5. 개발 환경 및 배포 구분

Java 및 Android Studio

Android Studio에서 android/ 프로젝트를 열 때 Gradle Sync가 실패하면, 해당 프로젝트의 Gradle Wrapper·Android Gradle Plugin·Kotlin 플러그인 조합과 JDK 버전 호환성을 확인합니다.

프로젝트에서 검증된 JDK 버전을 Gradle JDK로 사용합니다. 예를 들어 Java 21을 사용하는 환경이라면 다음과 같이 설정할 수 있습니다.

$env:JAVA_HOME = "C:\Program Files\Microsoft\jdk-21"
$env:ANDROID_HOME = "C:\Users\<사용자>\AppData\Local\Android\Sdk"

Android Studio의 android/ 폴더는 영구 소스가 아니라 CNG 생성물입니다. Android Studio는 네이티브 로그와 Gradle 상태를 확인하는 용도로 사용하고, 지속되어야 하는 설정은 app.json 또는 Config Plugin에 둡니다.

디버그 APK와 릴리즈 APK

구분

Debug

Release

JS 번들

Metro에서 실시간 로드

APK 내부에 포함

실행 조건

개발 PC의 Metro 접근 필요

독립 실행 가능

사용 목적

로컬 개발·디버깅

동료·테스터 전달

빌드 시간

상대적으로 짧음

모든 ABI 포함으로 길어질 수 있음

APK 산출물은 일반적으로 아래 경로에서 확인할 수 있습니다.

android/app/build/outputs/apk/debug/app-debug.apk
android/app/build/outputs/apk/release/app-release.apk

하이브리드 앱은 대다수 화면을 WebView로 서버에서 불러오는 경우가 많습니다.

  • 웹 화면 변경: 웹 배포 후 앱을 완전히 종료하고 다시 실행

  • RN 셸 변경: 탭바, 딥링크, 브릿지, 네이티브 SDK 등은 APK 재빌드 및 재설치 필요

Justin

Site footer