Back to list

#03. 모듈 & 빌드 파일

목차10

Build 파일의 공통 골격

  • plugins { ... }: 해당 모듈에서 적용할 플러그인들
  • android { ... }: 안드로이드와 관련된 옵션들을 정의
  • dependencies { ... }: 모듈 및 의존성 정의

plugins

  • root 레벨의 build.gradle.kts에서는 apply false 옵션을 붙여, 프로젝트에서 사용할 플러그인들을 선언
    • Ex) alias(libs.plugins.android.application) apply false
  • 각 모듈에서는 실제로 사용할 플러그인들을 선언
plugins {
    alias(libs.plugins.android.library)
    alias(libs.plugins.kotlin.android)
    ...
}

android

android {
    namespace = "com.example.presentation"
    compileSdk = 36

    defaultConfig {
        applicationId = "com.example.myapplication"
        minSdk = 26
        targetSdk = 36
        versionCode = 1
        versionName = "ver 1.0.0"
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }

    buildFeatures {
        compose = true
        buildConfig = true
    }
}

Namespace vs ApplicationId

  • namespace: 패키지 명 (코드 import 경로). 모듈별로 다름
  • applicationId: 기기/Playstore에서 앱을 구분하기 위한 ID

Sdks

  • defaultConfig 블록 내에서는 프로젝트의 최소/타겟 SDK 버전을 지정할 수 있다.

    • minSdk: 앱이 돌아가는 최소 버전
    • targetSdk: 이 앱이 최적화된 버전 (검증된 버전)
      • Google에서는 이 버전을 매년 강제로 올리고 있으므로, 배포 전에 확인 필요
  • compileSdk: 어떤 Sdk로 컴파일할지를 정의

    • 컴파일 시, 어떤 API를 쓸 수 있는지 (대표적으로 “권한 허용”은 Sdk 버전마다 선언 방식이 다르다)
    • targetSdk와 맞추는 것이 권장됨 (Lint가 안드로이드 신규 정책과 관련된 경고를 띄우기 위함)
    • defaultConfig가 아닌, android 블록 내부에서 선언해야 함

VersionCode vs VersionName

둘 모두 버전과 관련되지만, 누구에게 보여지느냐와 용도가 다름

  • VersionCode: 정수값, 플레이스토어의 판단 기준.

    • play console에서 새로운 버전을 트랙에 배포할 때, 이 값이 이전보다 높은 값이어야 함
    • PackageInfoCompat.getLongVersionCode(packageInfo) 등을 사용하여 버전 코드를 가져올 수 있음
  • VersionName: 문자열 값, 사용자에게 보여지는 “마케팅 표기” 버전.

    • 설정 > 앱 정보에서 보여지는 버전으로, “ver 1.0.0”과 같은 표기가 가능

buildTypes

prod/dev flavor를 나눌 때, 이 블록에서 설정을 변경할 수 있다. 현재 예시 구문에서는 release 버전에서 어떤 설정을 적용할 것인지가 정의되어있다.

  • isMinifyEnabled = true: 코드 크기 축소 및 난독화, 최적화 적용 여부.
    • true일 경우, R8은 다음과 같은 일을 함:
      • 코드 축소: 안쓰는 클래스/함수/필드 제거 (물리적 크기 감소)
      • 난독화: 클래스/함수 등의 이름을 짧고 직관적이지 않게 변경
      • 최적화: Dead code 제거, Inlining 등 바이트코드 단위 최적화
    • 이 값은 최상위 모듈(= app 모듈)에서만 한번 켜고, 나머지 라이브러리 모듈에서는 false로 둠
  • progaurdFiles을 통해 R8이 어떻게 동작할지 정의된 파일을 연결
    • 예전에는 R8이 아니라 progaurd였기에 위와 같은 이름이 붙은듯

CompileOptions

이름 그대로 컴파일 옵션. sourceCompatibility, targetCompatibility는 같은 Java 버전으로 맞춰준다.

buildFeatures & BuildConfig 클래스

컴파일 기능과 관련된 항목을 buildFeatures { ... } 블록에서 정의.

  • buildConfig = true: BuildConfig 클래스의 생성을 지시

    • local.properties에서 관리하는 secret을 주입하는 패턴에서 사용
    • 이 값의 기본값은 false이므로, 명시적 선언이 필요하다.
  • compose = true: Compose 컴파일러를 활성화 시킴

    • preview 등의 기능을 활성화하기 위함

dependencies

이전 글에서 언급된 ‘설정 버킷’을 이용하여 다른 모듈과의 관계, 라이브러리 의존성을 관리한다.

‘클린 아키텍처’니 ‘멀티 레이어 구조’니 하더라도, 결국은 어딘가에서 “실제 의존성 방향”을 지정해줘야 한다. 우선, 아래와 같은 전형적인 클린 아키텍처 구조를 살펴보자.

스크린샷 2026-06-04 094758

Presentation / Data 레이어는 Domain 레이어에만 의존하며, 앱의 조립 지점(Composition Root) 역할을 맡은 app 모듈은 모든 레이어들을 알고 있다. 이를 dependencies 블록에서는 아래와 같이 선언한다:


// data 혹은 presentation 모듈의 build.gradle.kts
dependencies {
    implementation(project(":domain")) // 이 모듈은 "domain" 모듈을 알고 있음
    ...
}

// app 모듈의 build.gradle.kts
dependencies {
    implementation(project(":presentation"))
    implementation(project(":domain"))
    implementation(project(":data"))
    ...
}

domain 모듈은 그 누구에게도 의존하지 않는 순수 kotlin 라이브러리이므로, 다른 모듈과 달리 project로 참조하는 모듈이 하나도 없다.

Comments

링크가 복사되었습니다