Gradle 동작순서

Arakene·2024년 6월 23일

순서

  1. 초기화(Initialization) : 빌드 대상 프로젝트를 결정하고 각각에 대한 Project 객체를 생성. settings.gradle 파일에서 프로젝트 구성 (멀티프로젝트, 싱글프로젝트 구분)
  2. 구성(Configuration) : 빌드 대상이 되는 모든 프로젝트의 빌드 스크립트를 실행. (프로젝트 객체 구성) configured Task 실행
  3. 실행(Execution) : 구성 단계에서 생성하고 설정된 프로젝트의 태스크 중에 실행 대상 결정. gradle 명령행에서 지정한 태스크 이름 인자와 현재 디렉토리를 기반으로 태스크를 결정하여 선택된 Task들을 실행

Init

빌드할 프로젝트를 선택 및 각 프로젝트 오브젝트 생성하며 해당 과정에서는 settings.gradle에서 세팅을 가져옴

repository

impletation을 통해 우리가 사용하려는 소스들을 명시하면 해당 친구들은 repository로 설정한 곳에서 가져오게된다.
주로 사용하는 곳은

repositories {
    mavenCentral() // maven central repository
    google() // google maven repository
}

이렇게 두가지가 있다. 이런 shorten notation의 경우 RepositoryHandler API을 이용한다.

dependencies 해결을 위해서 다양한 repo를 추가할 수 있다.
특정 레포에서만 기능을 지원하는경우 설정한다.

repositories {
    mavenCentral()
    maven {
        url = uri("https://repo.spring.io/release")
    }
    maven {
        url = uri("https://repository.jboss.org/maven2")
    }
}

위와 같은 경우 runtime 시 레포를 검색하는 순서는 맨 위부터 진행하게 된다. 따라서 원치않는 친구들이 받아질 수 있는데 이는 아래에서 해결방안을 소개한다.

만약 프로젝트 내부에 라이브러리를 가지고 있는 경우

repositories {
    flatDir {
        dirs("lib")
    }
    flatDir {
        dirs("lib1", "lib2")
    }
}

와 같이 flat (fileSystem) directory 를 repository로써 사용할 수 있다.

NOTE
As Gradle prefers to use modules whose descriptor has been created from real meta-data rather than being generated, flat directory repositories cannot be used to override artifacts with real meta-data from other repositories declared in the build.
For example, if Gradle finds only jmxri-1.2.1.jar in a flat directory repository, but jmxri-1.2.1.pom in another repository that supports meta-data, it will use the second repository to provide the module.
For the use case of overriding remote artifacts with local ones consider using an Ivy or Maven repository instead whose URL points to a local directory.

Reposotiry Content Filtering

위에서 잠깐 말한 특정 레포에서 특정 라이브러리르 받고, 특정 레포에서는 특정 라이브러리를 제외하는 등에 대한 기능이다.

Usecase

  • 성능
    • 특정 레포에서는 절대 해당 dependency가 없다는걸 아는 경우 해당 레포 검색을 건너뜀으로 성능 향상
  • 보안
    • 프라이빗 프로젝트에서 dependencies의 유출을 막기 위해서
  • 연관성
    • 몇몇 레포들이 손상된 메타데이터나 아티팩트를 가지고 있는 경우

사용방법

repositories {
    maven {
        url = uri("https://repo.mycompany.com/maven2")
        content {
            // this repository *only* contains artifacts with group "my.company"
            includeGroup("my.company")
        }
    }
    mavenCentral {
        content {
            // this repository contains everything BUT artifacts with group starting with "my.company"
            excludeGroupByRegex("my\\.company.*")
        }
    }
}

기본적으로 repo는 모두 포함하고 제외시키는 것은 없다.
다만 위처럼 설정을 하면

  • include만 설정하면, 설정한 것만 가져오고 나머지는 모두 제외한다.
  • exclude만 설정하면, 설정한 것만 제외하고 나머지는 모두 가져온다.
  • include, exclude 둘다 설정하면, include 설정한 것과 exclude 설정한 것을 제외한 나머지를 모두 가져온다.

추가로 그룹, 모듈, 버전을 직접 명시하거나 regular expressions을 사용해서 필터링할 수 있다. 특정 범위내에 있는 것으로 필터링할 수 있지만 그래도 특정 버전을 명시할 때는 bradle에서 제공하는 포맷을 사용해야한다. 게다가 resolution context에 의한 필터링 옵션도 있다. RepositoryConentDescriptor을 사용하면된다.

repository-level에서 제외시킨 라이브러리가 다른 레포에서 없다는 보장이 없다.
따라서 모든 레포에 대해서 설정을 해줘야하는데 이를 간단하게 할 수 있도록 Gradle에서 API를 제공해준다.
exclusiveContent를 사용하면
1. 레포 선언 순서와 상관없이 다른 레포에서는 이제 exclusive된 라이브러리를 검색하지 않음
2. exclusive된 라이브러리를 어디서 가져올지 extension을 통해 선언해야한다.

repositories {
    // This repository will _not_ be searched for artifacts in my.company
    // despite being declared first
    mavenCentral()
    exclusiveContent {
        forRepository {
            maven {
                url = uri("https://repo.mycompany.com/maven2")
            }
        }
        filter {
            // this repository *only* contains artifacts with group "my.company"
            includeGroup("my.company")
        }
    }
}

위의 예시에서는 mavenCentral에서는 my.company로 그룹된 아티팩트는 검색하지 않을 것이고 해당 아티팩트는 forRepository에 작성된 url에서 가져오게된다.
(혹시 제가 잘못 이해한거면 알려주세요)

Maven repository filter

Maven repository에 한해서 빌드 모드에 따라서 다른 url을 가져올 수 있다.

repositories {
    maven {
        url = uri("https://repo.mycompany.com/releases")
        mavenContent {
            releasesOnly()
        }
    }
    maven {
        url = uri("https://repo.mycompany.com/snapshots")
        mavenContent {
            snapshotsOnly()
        }
    }
}

나중에 추가로 공부해볼만한 것

profile
안녕하세요 삽질하는걸 좋아하는 4년차 안드로이드 개발자입니다.

0개의 댓글