1.2Gradle
안드로이드 앱 개발의 빌드 자동화 도구, gradle
TL;DR
추억의 쪽지 시험
React Native 프로젝트는 React Native만 익혀선 제대로 완성할 수 없는데, 빌드나 배포 과정에서 안드로이드와 iOS 각각의 네이티브 모듈을 건드려야 할 때가 반드시 오기 때문이다.
안드로이드 빌드 과정에서 빼놓을 수 없는 도구가 Gradle이다.

Gradle이란?
Gradle is the open source build system of choice for Java, Android, and Kotlin developers. -공식 문서-
Gradle은 Android 앱 개발의 빌드 자동화 도구이다.
이전 포스팅인 CocoaPods에서도 알아보았지만, 리액트 네이티브 앱은 자바스크립트 코드 외에 각 OS에 필요한 네이티브 코드를 포함하고 있다. Android 쪽에선 Java/Kotlin 코드가 포함되는데, Gradle은 안드로이드 프로젝트에서 아래의 작업들을 수행한다:
- 각종 태스크(Tasks): Gradle의 기본 작업 단위를 Task라고 한다. 코드 컴파일, 테스트 시행 등이 해당된다.
 - 외부 의존성 추가(ex: Firebase, React Native 모듈)
 - 플러그인 추가(ex: 
Java플러그인) - 빌드 환경 설정(Debug/Release 구분, SDK 버전 지정 등)
 - 빌드: 결과물 애플리케이션을 생성한다.
 
즉, CocoaPods가 iOS 네이티브 라이브러리의 의존성 관리(Pod 설치)를 담당한다면 Gradle은 Android의 빌드 전체를 담당하고 그 안에 의존성 관리(Maven 패키지의 Dependency)도 포함한다.
Gradle 프로젝트의 구성
Gradle 프로젝트는 보통 아래와 같은 폴더 구성으로 되어 있다.
bashproject ├── gradle ├── gradlew ├── gradlew.bat ├── settings.gradle ├── subproject-a │ ├── build.gradle │ └── src/ └── subproject-b ├── build.gradle └── src/
1. gradle 폴더
gradle 폴더 안에는 wrapper라는 폴더가 있고, 이 안에는 gradle-wrapper.jar와 gradle-wrapper.properties라는 파일들이 있다.
Gradle Wrapper는 Gradle을 설치하지 않아도 프로젝트를 빌드할 수 있게 해주는 도구다. gradle-wrapper.jar는 Wrapper 실행에 필요한 자바 코드의 압축 파일(jar)이다. gradle-wrapper.properties는 사용할 Gradle 버전과 다운로드 경로를 정의한 파일이다.
이 파일들(Gradle Wrapper)을 통해 버전의 일관성이 보장되고, 새로 clone한 사람도 이후 소개할 Gradle Wrapper CLI인 ./gradlew build만으로 자동으로 필요한 Gradle 버전을 받아온다. 또, 빌드 서버에도 Gradle을 설치할 필요 없이 Wrapper만으로 빌드할 수 있다. 따라서 이들은 레포에 커밋해서 공유해야 할 파일들이다.
gradle 명령어로 하는 방법과 Gradle Wrapper를 통해 gradlew 명령어를 쓰는 방법, 2가지가 있다보니 헷갈릴 수 있다. 하지만 공식문서에서도 말하듯이 Gradle Wrapper를 쓰는 방법이 앞서 말한 이점들 때문에 표준이다.2. gradlew, gradlew.bat
gradlew는 Unix/Linux/Mac용 실행 스크립트, gradlew.bat은 Windows용 실행 스크립트다. 참고로 확장자 bat은 Windows의 Batch Script를 의미한다. 이 파일들은 조작하면 안된다.
React Native를 통해 개발하다보면 버그가 나서 ./gradlew clean이라는 명령어를 실행하래서 실행하게 될 경우가 아주 많다.
clean은 이전 빌드 산출물을 지우는 동작이다. 구체적으로는 build/ 폴더를 삭제해 안에 있는 컴파일된 클래스, 리소스, 캐시 등을 지운다. Android를 빌드할 때 의존성이 충돌하거나 Gradle 캐시가 꼬이는 경우(코드를 수정했는데 이전 산출물이 반영되는 경우)가 잦기 때문에 ./gradlew clean은 아주 많이 쓰는 명령어다. 물론 실행하려면 android 폴더에 있어야 한다.
clean 이외에도 많이 쓰는 것은 물론 빌드 명령어로, ./gradlew build, ./gradlew assembleDebug, ./gradlew bundleRelease 등을 상황에 따라 쓰게 된다. 이 명령어들이 어떤 태스크들을 어떻게 수행하는지는 글 후반에 다룬다.
3. settings.gradle
settings.gradle 파일은 모든 Gradle 프로젝트의 엔트리 포인트로, 다른 빌드 스크립트들(이후에 볼 build.gradle 파일들)보다 먼저 읽힌다. 이 파일은 프로젝트 전체의 빌드 구조를 정의하는데, 예를 들어 프로젝트 명이나 포함되는 서브 프로젝트들의 정보가 들어있다.
groovyrootProject.name = 'root-project' include 'sub-project-a' include 'sub-project-b'
리액트 네이티브에선 include :app으로 app 폴더를 서브 프로젝트로 포함한다.
4. build.gradle

리액트 네이티브 프로젝트 기준으로 android 폴더 아래엔 build.gradle이 있는데, android/app 폴더 아래에도 build.gradle이 있다. 이 파일들은 빌드 스크립트(Build Script)라고 부르며, 플러그인과 의존성 관련 정보들을 포함한다.
- 플러그인: Gradle의 코드 컴파일, 테스트 시행 등의 태스크와 관련된 Gradle의 기능을 확장하는 툴들
 - 의존성: 외부 라이브러리들로, 크게 아래의 두 가지로 나뉜다.
- Gradle and Build Script Dependencies: Gradle 자체나 빌드 스크립트 로직에 필요한 플러그인, 라이브러리 등
 - Project Dependencies: 프로젝트의 소스 코드를 컴파일하는데 필요한 라이브러리
 
 
글 작성 시점(25.9.20) Gradle 공식문서의 빌드 스크립트는 아래와 같이 작성하는게 표준이다:
groovyplugins { id 'application' } dependencies { testImplementation libs.junit.jupiter testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation libs.guava } application { mainClass = 'org.example.App' }
다만, React Native 프로젝트를 언제 만들었냐에 따라 코드가 위와는 다를 수도 있다. 예를 들어, 약간 예전 버전(7.6.2)은 아래와 같이 buildscript 안에 repositories, dependencies를 포함했다:
groovybuildscript { repositories { mavenCentral() } dependencies { classpath group: 'commons-codec', name: 'commons-codec', version: '1.2' } }
React Native에선 android 폴더에 있는 build.gradle은 전체 프로젝트 공통 설정에 대한 부분으로, 루트 빌드 스크립트라고도 부른다. 예를 들어 전체 규칙/모든 모듈에서 쓸 저장소(repositories)/플러그인 등에 대한 설정이다.
android/app 폴더의 build.gradle은 앱 모듈에 대한 구체적 설정으로, 앱 모듈 빌드 스크립트로도 부른다. 앱 모듈에 대한 설정이라는 말은, 실제 앱의 빌드 결과(디버그/릴리즈, APK/AAB 등)에 직접 영향을 주는 요소들에 대한 정보가 포함된다는 의미다. 앱의 applicationId, versionCode, 빌드 타입(debug, release 등), productFlavors, sdk 버전, keystore(서명) 설정, 앱 전용 의존성 등이 포함된다.
과거에는 루트 build.gradle에서 ext { ... } 블록으로 프로젝트 전역 상수를 선언하곤 했다. 즉, 루트에서 ext { minSdkVersion = 28 ...}식으로 선언하면, app 모듈에선 android { minSdkVersion rootProject.ext.minSdkVersion}등으로 가져다 썼다. 이 경우도 "공통 값은 루트에서, 실제 적용은 모듈에서"라는 책임 분리 원칙을 지킨 것으로 볼 수 있다.
Gradle을 통한 빌드 과정
Task는 Gradle 빌드 과정에서 처리해야할 작업들의 단위다.
- 코드 컴파일
 - 테스트 진행
 - 결과물 패키징(jar파일 또는 APK 파일 생성)
 
각 Task들은 독립적으로 실행되지만, 어떤 것들은 다른 Task가 먼저 수행되어야만 이어 실행될 수 있는것도 있다. Gradle은 가장 효율적으로 Task들을 수행할 수 있는 방법을 찾아 실행한다.
예를 들어, 빌드를 한다고 하자.
bash./gradlew build
Gradle은 build 태스크를 수행하기 위해 이 태스크가 의존하는 모든 태스크들을 수행할 것이다.
bash> Task :app:compileJava > Task :app:processResources NO-SOURCE > Task :app:classes > Task :app:run Hello World! BUILD SUCCESSFUL in 904ms 2 actionable tasks: 2 executed
위의 케이스(Task들을 보면 React Native는 아니고 일반 Java 애플리케이션으로 보인다)에선 우선 컴파일을 하는것부터 시작해 결국 run으로 이어져 "Hello World!"를 출력하였다. ./gradlew tasks 명령어를 통해서 프로젝트에서 어떤 태스크들이 수행가능한지 확인할 수 있다.
좀 더 실전적인 예시로, ./gradlew assembleDebug등의 명령어로 빌드를 지시하면 Gradle은 아래와 같이 동작한다.
- 초기화 단계: 
settings.gradle을 읽고 포함된 모듈(app, library등)을 인식한다. - 설정 단계: 각 모듈의 
build.gradle을 읽고 실행하며 태스크 그래프(Task Graph)를 구성한다. 즉,:app:assembleDebug라는 태스크를 실행하기 위해 어떤 태스크들이 선행되어야 하는지 계산한다. 이 시점에서ext값(SDK 버전 등)이 평가되고,android {...},dependencies {...}같은 설정이 적용된다. - 실행 단계: 요청된 태스크와 그에 필요한 의존 태스크만 실행한다. 빌드 명령어의 경우 소스 코드 컴파일, 리소스 처리, APK/AAB 생성 등이다.