일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- gradle plugin만들기
- 스프링 scouter
- gradle custom plugin
- okhttp upload progress
- okhttp progress
- Springboot 테스트 속도
- 자바 가상스레드
- 테스트 속도
- @DirtiesContext 속도
- okhttp sink
- spring gatling
- 스프링 성능테스트
- @MockBean 속도
- junit 테스트 속도
- custom plugin
- gradle pl
- 테스트 속도개선
- spring 테스트 속도
- JDK21 가상스레드
- spring 테스트 성능
- 스프링 gatling
- file upload progress
- 자바Thread
- JAVA 가상스레드란
- gradle plugin이란
- 성능테스트 모니터링
- 스프링 모니터링
- gatling
- 자바 가상스레드란
- spring socuter
- Today
- Total
호딩클라우드
Gradle plugin 이란? Gradle Custom Plugin 만들기 본문
해당 게시글은 Tom Gregory 의 Introduction to writing Gradle plugins 아티클 예제를 기반으로 작성된 게시글 입니다.
Gradle 플러그인이란?
빌드를 위한 추가기능을 제공하며 아래와 같이 적용할 수 있습니다.
plugins {
id 'org.springframwork.boot' version '2.2.4.RELEASE'
}
플러그인 기능
- gradle task를 유저가 실행할 수 있도록 구성할 수 있습니다.
예를 들어 maven publish plugin 은./gradlew publisheToMavenLocal 명령을 통해 해당 Task를 실행시킬 수 있게 구성해줍니다.
또한 이러한 task들은 task graph를 통해 기본적으로 실행되도록 구성할 수도 있습니다.
Spring Boot plugin의 경우 bootJar task에 결합되어 실행가능한 파일을 만들도록 지원해 줍니다.

플러그인 특징으로는 적용과 동시에 바로 사용할 수 있습니다.
플러그인 Configuration
플러그인은 build.gradle 에서 구성할 수 있습니다.
플러그인을 사용하기 위해 간단한 파라미터만으로 구성될 수도 있고 복잡한 구성을 가질 수도 있습니다.
예를 들어 java Plugin은 태그를 이용해서 테스트를 포함하거나 제외할 수 있습니다.
test{
useJUnitPlatform{
includeTags 'fast'
excludeTags 'slow'
}
}
플러그인 클래스 설계

1. Plugin Class : 메인클래스로 플러그인이 적용되었을 때 무슨 일이 일어나는지 정의하는 최상위 플러그인 클래스입니다. Extension Class와 Task Class를 의존하고 있습니다.
2. Extension Class : 플러그인을 위한 Configuration을 작성해 두는 클래스입니다.
3. Task Class : 여러 유형으로 Task Class를 구성할 수 있지만 기본적으로 플러그인은 작업 클래스의 인스턴스를 생성하고 이를 이름으로 연결합니다.
플로그인 배포
일반 자바프로젝트처럼 공용 또는 개인 maven repository를 통해 배포할 수 있습니다.

플러그인 제작 프로젝트 생성하기
예제는 2개의 파일의 크기를 비교하는 플러그인을 제작합니다.
예제를 통해 groovy의 문법과 groovy 통합테스트를 부가적으로 학습할 수 있습니다.

gradle init를 통해 프로젝트를 생성합니다.
프로젝트 유형은 basic Type으로 설정하고 언어는 Groovy로 설정해 줍니다.
플러그인을 작성하는데 필요한 구성요소 추가(build.gradle)
// 세개의 플러그인이 필요합니다.
// 1. goorvy : groovy 스크립트를 사용하기 위한 플러그인
// 2.java-gradle-plugin : 플러그인 개발에 필요한 다양한 구성을 설정합니다
// 3.maven-publish : 메이븐 저장소(로컬,공용)에 게시하기위해 필요합니다.
plugins {
id 'groovy'
id 'java-gradle-plugin'
id 'maven-publish'
}
group = 'com.gradleplugin' //플러그인이 게시될 때 그룹을 식별하여 게시됩니다.
version = '0.0.1-SNAPSHOT'
//maven저장소를 사용합니다.
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.spockframework:spock-core:2.0-groovy-3.0' //groovy test framework
}
//다른 프로젝트에서 플러그인을 참조할 때 사용되는 ID와 구현 클래스를 설정합니다.
gradlePlugin {
plugins {
fileDiff {
id = 'com.gradleplugin.practice'
implementationClass = 'com.gradleplugin.plugins.BasicPlugin'
}
}
}
//junit platform기반에서 테스트를 진행합니다.
test {
useJUnitPlatform()
}
Extention Class 생성
프로젝트 Root에 src/main/com/gradleplugin/plugins/extention 패키지를 생성하고 클래스를 작성합니다.

intellij에서 모듈로 인식하게 되면 main아이콘 우측하단에 파란 박스가 붙습니다. (intelij ui에 따라 다를 수 있습니다.)
package com.gradleplugin.plugins.extention
import org.gradle.api.file.RegularFileProperty
abstract class BasicExtension{
abstract RegularFileProperty getFile1()
abstract RegularFileProperty getFile2()
}
- 참고
RegularFileProperty
RegularFileProperty는 RegularFile 타입의 값을 지연(Lazy) 제공할 수 있는 Provider입니다.
RegularFile
파일 시스템의 고정 위치에 있는 일반 파일을 나타냅니다. 일반 파일은 디렉터리도 아니고 장치와 같은 특별한 종류의 파일도 아닌 파일입니다.
task class 생성
package com.gradleplugin.plugins.task
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
abstract class BasicTask extends DefaultTask {
@InputFile //Gradle이 매핑된 파일의 변경 사항을 감시하고 변경된 경우에만 작업을 다시 실행하도록 설정합니다.
abstract RegularFileProperty getFile1()
@InputFile
abstract RegularFileProperty getFile2()
@OutputFile //결과 파일이 변경된 경우에만 작업을 다시 실행합니다.
abstract RegularFileProperty getResultFile()
BasicTask() {
resultFile.convention(project.layout.buildDirectory.file('diff-result.txt'))
}
@TaskAction //task가 실행될 때 실행되는 메서드임을 나타냅니다.
def diff() {
String diffResult
if (size(file1) == size(file2)) {
diffResult = "Files have the same size at ${file1.get().asFile.size()} bytes."
} else {
File largestFile = size(file1) > size(file2) ? file1.get().asFile : file2.get().asFile
diffResult = "${largestFile.toString()} was the largest file at ${largestFile.size()} bytes."
}
resultFile.get().asFile.write diffResult
println "File written to $resultFile"
println diffResult
}
private static long size(RegularFileProperty regularFileProperty) {
return regularFileProperty.get().asFile.size()
}
}
@InputFile : Gradle이 매핑된 파일의 변경 사항을 감시하고 변경된 경우에만 작업을 다시 실행하도록 설정합니다.
@OutputFile : 결과 파일이 변경된 경우에만 작업을 다시 실행합니다.
@TaskAction : task가 실행될 때 실행되는 메서드임을 나타냅니다.
def diff() : 파일사이즈를 비교하고 결과를 산출한 뒤 결과파일을 생성합니다. 완료 후 로깅을 위한 문구를 출력합니다.
Plugin 클래스 생성
package com.gradleplugin.plugins.task
import com.gradleplugin.plugins.extention.BasicExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
class BasicPlugin implements Plugin<Project> {
@Override
void apply(Project project) { // 플러그인이 build.gradle 파일 에 적용될 때 호출됩니다 .
// 플러그인이 적용되는 build.gradle 에서 구성 블록 에서 구성을 정의할 수 있음을 의미합니다
project.extensions.create('fileDiff', BasicExtension)
//구성된 fileDiff 속성을 통해 file을 설정하고 task로 등록합니다.
project.tasks.register('fileDiff', BasicTask) {
file1 = project.fileDiff.file1
file2 = project.fileDiff.file2
}
}
}
apply() : 플러그인이 build.gradle 파일에 적용될 때 호출됩니다.
project.extensions.create(String name, Class <T> type) : 플러그인이 적용되는 build.gradle 에서 플러그인 속성값을 정의할 수 있음을 의미합니다
project.tasks.register(String name, Class <T> type) : 구성된 fileDiff 속성을 통해 file을 설정하고 task로 등록합니다.
플러그인 통합테스트 작성
package com.gradleplugin.plugins
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome
import spock.lang.Specification;
import spock.lang.TempDir;
/**
플러그인을 참조하는 build.gradle 파일을 동적으로 생성합니다.
해당 빌드에 대해 특정 작업을 실행합니다.
작업이 성공적으로 실행되었는지 확인
*/
class FileDiffPluginIntegrationTest extends Specification{
@TempDir // 테스트를 위한 디렉토리를 생성하기 위해 사용됩니다.
File testProjectDir
File buildFile
//Junit의 setUp과 동일합니다.
def setup() {
buildFile = new File(testProjectDir, 'build.gradle')
buildFile << """
plugins {
id 'com.gradleplugin.practice'
}
"""
}
def "can diff 2 files of same length"() {
given:
//사이즈가 같은 두개의 파일을 생성합니다.
File testFile1 = new File(testProjectDir, 'testFile1.txt')
testFile1.createNewFile()
File testFile2 = new File(testProjectDir, 'testFile2.txt')
testFile2.createNewFile()
//gradle에서 플러그인 configruation을 정의하는 문구를 삽입합니다.
buildFile << """
fileDiff {
file1 = file('${testFile1.getName()}')
file2 = file('${testFile2.getName()}')
}
"""
when:
//GradleRunner를 이용해 task를 실행시킵니다. task이름은 fileDiff입니다.
def result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments('fileDiff')
.withPluginClasspath()
.build()
then:
//의도한 출력이 나오는지 확인하고 성공여부를 검증합니다.
result.output.contains("Files have the same size")
result.task(":fileDiff").outcome == TaskOutcome.SUCCESS
}
def "can diff 2 files of differing length"() {
given:
File testFile1 = new File(testProjectDir, 'testFile1.txt')
testFile1 << 'Short text'
File testFile2 = new File(testProjectDir, 'testFile2.txt')
testFile2 << 'Longer text'
buildFile << """
fileDiff {
file1 = file('${testFile1.getName()}')
file2 = file('${testFile2.getName()}')
}
"""
when:
def result = GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments('fileDiff')
.withPluginClasspath()
.build()
then:
result.output.contains('testFile2.txt was the largest file at ' + 'Longer text'.bytes.length + ' bytes')
result.task(":fileDiff").outcome == TaskOutcome.SUCCESS
}
}
- @TempDir : 테스트를 위한 디렉터리를 생성하기 위해 사용됩니다.
- def setup() : Junit의 setUp과 동일합니다.
- 테스트를 위한 build.gradle 파일을 생성하고 플러그인을 적용시킵니다
- def "can diff 2 files of same length"() : 두 개의 파일이 다른 경우를 테스트합니다.
- 사이즈가 같은 두개의 파일을 생성합니다.
- gradle에서 플러그인 configruation을 정의하는 문구를 삽입합니다.
- GradleRunner를 이용해 task를 실행시킵니다. task이름은 fileDiff입니다.
- 의도한 출력이 나오는지 확인하고 성공여부를 검증합니다.
터미널에서./gradlew test 또는 intelij를 통해 테스트를 실행해 줍니다.

mavenLocal에 배포하기
터미널에서./gradlew publishToMavenLocal 혹은 intelij를 통해 task를 실행해 줍니다.

빌드가 성공되고 나면 maven 저장소의 기본 로컬경로인 /Users/사용자이름/. m2/repository/com (맥북기준) 하위의 우리가 설정한 이름(gradleplugin)으로 폴더가 생깁니다.
gradleplugin/gradle-plugin/0.0.1-SNAPSHOT 경로로 더 들어가서 확인해 보면 jar파일이 빌드된 것을 확인할 수 있습니다.

pom파일을 열게 되면 사용법에 대한 힌트를 얻을 수 있습니다.

참고
https://gradlehero.com/introduction-to-gradle-plugins/
https://www.bucketplace.com/post/2022-06-10-gradle-plugin-%EA%B0%9C%EB%B0%9C-%EA%B8%B0%EB%A1%9D/
https://docs.gradle.org/current/userguide/custom_plugins.html
'SpringBoot > 꿀팁' 카테고리의 다른 글
[Spring] gatling 성능테스트 with scouter 모니터링 (0) | 2024.02.26 |
---|