글 작성자: beaniejoy

이번 게시글에서는 ktlint를 사용해보고 적용했던 내용들을 간단하게 정리해보고자 합니다.

  • 📌 간단한 Overview
  • 📌 spring boot, kotlin 프로젝트에서 ktlint 설정
  • 📌 멀티모듈 환경에서 ktlint 설정
  • 📌 git commit시 ktlint check 설정

위의 내용을 가지고 ktlint를 어떻게 적용했는지 한 번 알아보겠습니다.

 

1. 간단한 Overview

KtLint is a linter tool for checking and enforcing code style conventions for Kotlin programming language.
(https://medium.com/@naeem0313/configuring-and-running-ktlin-on-android-studio-752413e7f6c2)

ktlint는 개발자들이 코틀린 코드에 대한 컨벤션을 지키도록 체크하고 강제할 수 있도록 도와주는 툴입니다.
코드 컨벤션은 왜 필요할까요. 이 부분에 대해서 개인적으로 크게 생각을 하지 않았었는데 최근들어서 필요성을 느끼고 있습니다.

여러 개발자들이 하나의 프로젝트에 개발한 내용을 가지고 커밋하고 머지하는 과정에서 코드가 지저분해지는 것은 당연합니다. 처음 프로젝트를 구성하고 개발을 시작할 때에는 팀 내에 나름 코드 작성 규칙도 정해보고 잘 지켜지는 것처럼 보일 수 있습니다.

하지만 시간이 지날 수록 코드에 먼지(?)가 쌓이기 시작합니다. 간편하게 코드 보라고 한 줄에 코드를 압축해놓아 가로 스크롤 해야 뒷 부분을 볼 수 있는 것들도 있고, 과거의 추억을 회상하고자 몇 년째 안쓰는 코드들 그대로 남겨놓아서 IntelliJ로 보면 곳곳에 회색처리된 부분들도 많이 보이기 시작합니다. 이외에도 먼지가 쌓인 코드들이 많아지게 되는데요.

얼핏 생각해보면 이런 것들 뭐 별거 아니라고 생각이 들 수도 있습니다. 그런데 프로젝트가 정말 복잡해지고 오류 찾아내려고 역으로 코드를 추적하거나 로직 파악하는데 있어서 이러한 먼지들이 상당히 거슬립니다. 여러 개발자들이 각자의 스타일을 가지고 개발을 하게 되면 코드만 가지고 분석할 때에도 꽤나 시간을 잡아먹게 됩니다.

이러한 것들을 방지해주고 일관성있게 프로젝트를 관리할 수 있게 해주는 것이 바로 Linter인데요. Linter 뜻을 찾아보니 보푸라기 제거제라고 나오더라고요. 코드에 붙어있는 지저분한 먼지나 보푸라기들을 제거해준다고 해서 Linter라고 부르는 것 같습니다.

여러 언어들을 지원해주는 Linter들이 존재하는데요. 그 중 kotlin 언어의 linter, ktlint에 대해서 어떻게 설정하는지 알아보도록 하겠습니다.

 

2. spring boot, kotlin 프로젝트에서 ktlint 설정

ktlint는 기본적으로 pinterest의 오픈소스 프로젝트를 가장 많이 사용합니다. 

 

GitHub - pinterest/ktlint: An anti-bikeshedding Kotlin linter with built-in formatter

An anti-bikeshedding Kotlin linter with built-in formatter - GitHub - pinterest/ktlint: An anti-bikeshedding Kotlin linter with built-in formatter

github.com

github readme 페이지에서 여러 장점들을 소개하고 있는데요. 그 중에 개인적으로 큰 장점으로 다가왔던 두 부분에 대해서 말씀드리자면, 첫 번째로, 코틀린 공식 document의 code convention을 기반으로 한다는 점이 있습니다. ktlint는 공식 문서의 code convention보다 좀 더 타이트한 컨벤션 rule을 가지고 있는 것 같은데요. 이 부분이 저에게는 큰 장점으로 다가왔습니다.

두 번째로 .editorconfig 파일을 지원한다는 것입니다. ktlint에 내장되어 있는 built in rule들이 존재하는데요. 개인 프로젝트를 하거나 팀 내에서 코드 컨벤션을 정할 때 원치 않은 rule들이 있거나 설정된 숫자값들이 분명 있습니다. 그 때 해당 프로젝트 루트 경로에 .editorconfig 파일을 만들고 거기에 커스텀하게 rule들을 설정할 수 있습니다. ktlint는 이러한 것도 같이 적용할 수 있도록 지원해주고 있어서 이부분도 큰 장점으로 다가왔습니다.

 

2-1. gradle plugin 설정

저는 kotlin DSL이 적용된 build.gradle.kts 파일에 ktlint를 적용해보았습니다.
(groovy DSL에 대한 ktlint 설정 내용도 아주 친절하게 나와있으니 구글링 조금만 해보시면 바로 나올 거예요)

gradle plugin으로 적용한 것은 JLLeitschuh/ktlint-gradle 플러그인 입니다. 

 

GitHub - JLLeitschuh/ktlint-gradle: A ktlint gradle plugin

A ktlint gradle plugin. Contribute to JLLeitschuh/ktlint-gradle development by creating an account on GitHub.

github.com

pinterest/ktlint를 gradle 기반 프로젝트에서 간편하게 사용할 수 있도록 감싼(wrapping) gradle plugin입니다.

// build.gradle.kts
plugin {
	id("org.jlleitschuh.gradle.ktlint").version("12.1.0")
}

설정도 정말 간편합니다. Spring Boot 프로젝트 루트 경로에 있는 build.gradle.kts 파일에서 jlleitschuh plugin 하나만 추가하면 기본적인 ktlint 기능을 사용해볼 수 있습니다.

위의 plugin 하나만 추가하면 gradle build task에 ktlint check가 포함됩니다. 그래서 프로젝트 build시 ktlint check 과정도 진행됩니다.

$ ./gradlew ktlintCheck

plugin ktlint 기능만 사용하고 싶다면 ktlintCheck 입력하면 됩니다.

ktlintCheck 수행 결과 콘솔 내용(오류 내용)

만약 ktlint rule에 어긋난 코드 내용이 있다면 위의 캡쳐화면처럼 오류내용이 나옵니다. 오류 내용만 보더라도 대강 어떤 rule 내용을 위반했는지 나오긴 하지만 더 자세히 확인해보려면  ${project_root_dir}/build/reports/ktlint/.. 해당 경로로 가면 됩니다.

standard:no-empty-first-line-in-method-block rule을 위반했다고 나오네요. SpringBootKtlintDemoApplication.kt 파일에서 발생한 것이니 가서 수정하도록 하겠습니다.

확인해보니 10번째 라인에 main method block 맨 첫 번째 줄이 비어있어서 발생한 위반내용이었습니다. 해당 라인을 제거하고 다시 ktlintCheck를 실행해보겠습니다.

ktlintCheck 다시 한 번 실행해보니 성공적으로 작업을 수행했다고 나옵니다. 이러면 프로젝트 내 모든 kotlin 코드들이 ktlint 규칙에 맞는 것이라 할 수 있습니다.

 

2-2. ktlint report 형식 바꾸기

그런데 위 과정에서 하나 걸리는 것이 있습니다. ktlint 수행 결과로 나온 오류 내용 report 파일이 txt 파일로 되어있는데, 막상 보면 규칙 위반 내용이 눈에 띄질 않습니다. 어떤 파일에 몇 번째 라인에서 어떠한 rule을 위반했는지 읽기가 어렵습니다. 이럴 때는 ktlint의 report 파일 형식을 바꾸면 되는데요. txt 파일로 되어있는 것을 JSON 파일로 바꾸면 만족 할만한 내용들을 받아볼 수 있습니다.

ktlint {
    reporters {
        reporter(ReporterType.JSON)
    }
}

ktlint은 kotlin DSL에서 KtlintExtension을 설정할 수 있도록 람다형식으로 제공하고 있는 function입니다. KtlintExtension에 대한 설정 옵션 내용들은 JLLeitschuh/ktlint-gradle github readme 페이지에서 확인해볼 수 있습니다. 이 중에 저는 ReporterExtension의 ReporterType을 JSON 타입으로 설정했습니다. 이렇게 설정하고 다시 ktlint check 작업을 수행해보겠습니다.

[
    {
        "file": ".../spring-boot-ktlint-demo/src/main/kotlin/io/beaniejoy/ktlintdemo/SpringBootKtlintDemoApplication.kt",
        "errors": [
            {
                "line": 10,
                "column": 1,
                "message": "First line in a method block should not be empty",
                "rule": "standard:no-empty-first-line-in-method-block"
            }
        ]
    }
]

txt 파일로 받아봤을 때보다 훨씬 더 좋네요. 몇 번째 라인에서 어떤 rule을 위반했고 그 내용까지 한 번에 확인할 수 있어서 오류 내용이 눈에 확 띄는 것 같습니다.

이것 말고도 추가 editor config 파일 설정, 특정 경로 ktlint 수행하지 않도록 하는 filter 설정 등, ktlint 관련 커스텀하게 설정할 수 있는 여러 옵션들이 있으니 github repo 문서 내용 보시고 적용해보시면 좋을 것 같습니다.

 

3. Multi module 프로젝트에서 ktlint 설정

위의 내용은 monolithic project에서 간단하게 ktlint를 적용해본 것입니다. 보통 spring boot project를 구성하게 되면 multi module로 진행하는 경우가 많은데요. multi module 환경에서는 ktlint를 어떻게 적용할 수 있는지 알아보겠습니다.

멀티모듈 프로젝트에 ktlint를 적용하기 위해 테스트 프로젝트로 3개의 모듈이 설정된 프로젝트를 만들어보았습니다.

그리고 모듈간에 의존성 설정을 해두었는데요. 다음과 같습니다.

// app/build.gradle.kts
dependencies {
    implementation(project(":domain"))
    implementation(project(":persistence"))

	//...
}

// persistence/build.gradle.kts
dependencies {
    implementation(project(":domain"))
    
	//...
}

// domain/build.gradle.kts
dependencies {
	//...
}

app 모듈은 api controller 기능을 모아둔 곳으로 endpoint 역할을 담당하게 됩니다. domain 모듈은 비즈니스 로직을 담고 있고, persistence는 database 관련 영속화작업을 수행하고 관련 datasource를 설정하는 모듈입니다. 간단하게 요정도로 프로젝트 구성을 해보았고 본격적으로 ktlint를 설정해봅시다.

 

3-1. 프로젝트 루트 경로의 build.gradle.kts 설정

루트 경로의 build.gradle.kts부터 살펴보겠습니다.

plugins {
    //... 기본 springboot + kotlin gradle plugin 설정

    id("org.jlleitschuh.gradle.ktlint").version("12.1.0")
}

allprojects {
    group = "io.beaniejoy"

    repositories {
        mavenCentral()
    }

    apply {
        plugin("org.jlleitschuh.gradle.ktlint")
    }

    ktlint {
        reporters {
            reporter(ReporterType.JSON)
        }
    }
}

subprojects {
	//...
}

모놀로틱 구조의 프로젝트에서 ktlint 설정과 조금 다른 점은 allprojects에 리포트파일 형식 설정을 적용했다는 것입니다.

만약 subprojects에 적용하게 되면 app, domain, persistence 모듈 안에 있는 내용만 ktlint 리포트 파일 형식이 json으로 바뀌게 됩니다. 루트 경로에도 build.gradle.kts, settings.gradle.kts, 추가로 buildSrc를 적용해볼 수 있는데 여기서 존재할 수 있는 코틀린 코드에 대해 수행한 ktlint 리포트 결과 형식은 txt파일(default)로 나오게 됩니다.
(subprojects에 ReporerType.JSON 적용하고 ./gradlew :ktlintCheck 실행해보면 바로 알 수 있습니다.)

즉, 루트 경로에 대해서도 ktlint 리포트 파일 형식을 json으로 똑같이 적용하고 싶다면 allprojects에 적용해야합니다.

위와 같이 설정하고 다음 명령어를 실행해보면 결과파일들이 json형태로 잘 나오는 것을 확인할 수 있습니다.

$ ./gradlew clean ktlintCheck

 

3-2. ktlint report 파일 한 곳에서 관리하기

위에서 각 모듈의 build/reports/ktlint 디렉토리 안에서 ktlint 오류에 대한 결과파일을 볼 수 있는데요. 한 가지 불편한 점은 각 모듈마다 결과파일이 산재해 있다보니 각 모듈의 build 디렉토리 안을 확인해야 해서 확인하기가 꽤나 버겁고 정신이 없는 것 같습니다. 

루트 프로젝트와 각 서브 모듈에 대한 ktlint 결과 파일들을 하나의 디렉토리로 모을 수 있다면 보기에도 편할 것 같습니다.

allprojects {
	//...

    apply {
        plugin("org.jlleitschuh.gradle.ktlint")
    }

    ktlint {
        reporters {
            reporter(ReporterType.JSON)
        }
    }

    // ktlint report directory location setting
    tasks.withType<GenerateReportsTask> {
        reportsOutputDirectory.set(
            rootProject.layout.buildDirectory.dir("reports/ktlint/${project.name}")
        )
    }
}

jlleitschuh plugin github readme에 보면 reports output file에 대한 디렉토리를 custom하게 설정할 수 있도록 가이드한 내용이 있습니다. 여기서 저는 프로젝트 루트 경로에 build/reports/ktlint 디렉토리 안에서 모듈 이름 별로 관리하고 싶어서 위와 같이 설정했습니다. rootProject,,buildDirectory에 reports/ktlint/${project.name} 으로 설정하면 각 모듈 이름 별로 결과파일을 확인할 수 있습니다.

이렇게 하니 하나의 디렉토리에서 모든 모듈에 대한 rule 위반 내용을 확인할 수 있어서 확실히 좋아진 것 같습니다.

 

3-3. 모든 rule 위반 내용을 한 번에 확인할 수는 없는 것인가요?

app, domain, persistence 모듈에 있는 코틀린 코드에 임의로 rule에 맞지 않는 내용을 넣고 ktlint 작업을 수행해보겠습니다.

분명 모든 서브 모듈에 위반한 내용이 있는데 실제 ktlint 결과 파일 보면 domain에 있는 json 파일은 비어있고 persistence에 대한 위반 내용만 나와 있습니다.

$ ./gradlew clean ktlintCheck --info | grep "Task :"

콘솔에 해당 프로젝트에 대해서 위의 gradle task를 실행해서 로그를 확인해보면 어느정도 이유를 알 수 있는데요.

gradle ktlint check task 성공한 경우
gradle ktlint check task 실패한 경우 (중간에 작업이 끊기고 예외를 반환한다)

gradle ktlintCheck 작업을 수행했을 때 실패한 경우와 성공한 경우의 로그를 살펴보면 차이점을 바로 알 수 있습니다.
성공했을 때는 모든 모듈과 루트 프로젝트에 대해서 ktlintCheck를 모두 잘 수행된 것을 확인할 수 있습니다. 하지만 실패한 경우 실패한 task 기점으로 더이상 작업이 진행되지 않는 것을 알 수 있습니다.

그래서 gradle ktlintCheck를 여러 번 수행을 하며 rule 오류 내용을 고쳐나가야 하는 경우가 많이 발생합니다. 예를 들어, ktlintCheck를 처음 수행하고 domain, persistence에서 rule 위반 내용이 나왔는데, 해당 위반 내용을 모두 고치고나서 다시 ktlintCheck를 수행하면 이전에 안나왔던 app 모듈에서 rule 위반 내용이 나올 수 있습니다. 이부분 참고하시면 좋을 것 같습니다.

+ 위의 ktlint check 오류 캡쳐화면에 보면 :ktlintKotlinScriptCheck에서 FAILED가 나왔는데 거기서 task가 끝나는 것이 아니라 그 이후에도 2개의 task가 더 수행된 것을 볼 수 있습니다. 이 부분은 저도 정확하게 확인해보지는 못했지만 gradle task는 parallel execution 기능이 있는데요. 여러 모듈의 gradle task를 병행해서 수행하는 기능으로 보입니다. 추측이지만 ktlint plugin에 대한 task도 parallel execution으로 수행되어서 여러 task에서 FAILED된 것이 아닐까 생각합니다.
gradle document를 확인했는데 default로 parallel mode를 사용하고 있지 않다고 봐서 왜 병행해서 수행되는지 알지는 못했네요,, ㅜ 이부분에 대해서 아시는 분 계시면 댓글 부탁드리겠습니다~

 

3-4. 멀티모듈 build 수행할 때 ktlint task 설정

멀티모듈 Spring Boot를 개발하고 build 작업을 수행할 때 시작점이 되는 서브 모듈이 있을 것입니다. 예를 들어 위의 예시 프로젝트를 가지고 말씀드리자면 app 모듈이 될 것 같습니다. app 모듈은 애플리케이션의 endpoint를 담당하고 있고 실제 프로젝트를 실행할 수 있는 bootstrap class(AppApplication.kt)를 가지고 있기 때문입니다.

$ ./gradlew clean :app:build -x test

애플리케이션을 서버에 배포할 때 프로젝트 build 과정을 거쳐야 하는데요. 위의 gradle 명령을 수행하여 app 모듈을 build하게 되면 implement 하고 있는 domain, persistence 모듈도 같이 빌드를 진행하게 됩니다.

여기서 위에 2-1. gradle plugin 설정 섹션에서 ktlint gradle plugin 설정하기만 하면 gradle build 작업 수행시 ktlint check 과정을 진행하게 된다고 했습니다. 멀티모듈에도 그대로 적용되는데 위 설정 그대로 적용하면 app 모듈만 ktlintCheck가 진행되는 것을 볼 수 있습니다.

build 수행시 app 모듈에 대해서만 ktlint 작업 수행

build 할 때 모든 모듈과 루트 프로젝트까지 ktlint를 수행하게 하고 싶다면 afterEvaluate 설정을 app/build.gradle.kts에 추가해야 합니다.

// app/build.gradle.kts

import org.jlleitschuh.gradle.ktlint.tasks.KtLintCheckTask

afterEvaluate {
    project.tasks.apply {
        // check all root & sub-modules ktLint
        this.withType<KtLintCheckTask> {
            dependsOn(
                listOf(
                    ":ktlintCheck",
                    ":domain:ktlintCheck",
                    ":persistence:ktlintCheck"
                )
            )
        }
    }
}

dependencies {
    implementation(project(":domain"))
    implementation(project(":persistence"))

	//...
}

KtLintCheckTask에 의존성을 부여하는 방식입니다. app 모듈의 ktlintCheck task를 수행할 때 dependsOn에 등록한 task들을 먼저 수행하겠다는 의미로 생각하면 편할 것 같습니다. 위와 같이 설정하고 다시 :app:build 작업을 실행해보겠습니다.

루트 프로젝트(:ktlintCheck)까지 포함해서 모든 모듈에서 ktlintCheck 작업이 수행된 것을 확인할 수 있습니다.

+ 참고로 app 모듈의 KtLintCheckTask에 다른 모듈의 ktlintCheck 작업을 dependsOn 걸어버리면 ./gradlew ktlintCheck를 따로 수행했을 때 domain, persistence의 ktlintCheck가 실행되고 app의 ktlintCheck도 실행될텐데 app 모듈에 dependsOn 걸려있으면 domain, persistence의 ktlintCheck가 불필요하게 두 번 수행하는 것은 아닌가 하는 의문이 들 수 있습니다.

결론은 그렇지 않습니다. 직접 테스트해봤을 때는 의도한 대로 모든 모듈들의 ktlintCheck는 한 번씩 실행되는 것을 확인했는데요. 이부분에 대해서 명확한 이유를 잘은 모르겠네요,, 찾아보다가 답이 나오면 여기에 추가해놓도록 하겠습니다.

$ ./gradlew ktlintCheck
$ ./gradlew :app:ktlintCheck
app 모듈에 dependsOn을 설정했을 때는 두 개의 gradle 명령은 똑같이 동작하게 됩니다. 이 점 참고하세요.

 

3-5. ktlint의 특정 rule을 비활성화 하고 싶을 때 .editorconfig 활용하기

코틀린 코드로 개발하다가 ktlint에서 기본적으로 적용되어 있는 rule이 마음에 안드는 경우가 있을 수 있습니다. 혹은 팀 내에서 코드 컨벤션을 정했는데 ktlint의 rule과 충돌하는 경우가 발생하게 됩니다. 이런 경우에는 특정 rule을 비활성화해야될텐데요. 이 때 .editorconfig 파일을 사용하면 됩니다.

[
    {
        "file": ".../OrderReaderAdapter.kt",
        "errors": [
            {
                "line": 12,
                "column": 49,
                "message": "Missing trailing comma before \")\"",
                "rule": "standard:trailing-comma-on-declaration-site"
            }
        ]
    }
]

ktlintCheck를 수행하고 받은 오류 report 내용입니다. trailing-comma-on-declaration-site rule을 위반했다고 나오는데요. ktlint의 rule에 대한 내용을 보고싶으면 pinterest github 페이지에 있는 document를 참고하면 됩니다.

 

Code styles - Ktlint

Code styles Starting from version 1.0, ktlint_official is the default code style. If you want to revert to another code style, then set the .editorconfig property ktlint_code_style. [*.{kt,kts}] ktlint_code_style = intellij_idea # or android_studio or ktli

pinterest.github.io

trailing-comma-on-declaration-site를 찾아보면 선언부에 괄호안의 인자 끝부분에 comma를 넣으라는 것 같습니다.

@Component
class OrderReaderAdapter(
    private val orderRepository: OrderRepository, // 마지막 인자 끝부분에 comma(,)를 넣어야 합니다
) : OrderReaderPort {
    override fun getOrder(orderId: Long): Order {
        return orderRepository.findByIdOrNull(orderId)
            ?: throw RuntimeException("order not found")
    }
}

엇 그런데 저는 콤마 넣기가 싫어서 해당 rule을 비활성화하고 싶습니다. 이 때 루트 디렉토리에 .editorconfig 파일을 만들고 다음과 같이 내용을 기입합니다.

root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120

[*.{kt,kts}]
indent_size = 4
tab_width = 4

# ktlint_[standard/experimental]_[rule_name]=disabled
ktlint_standard_trailing-comma-on-declaration-site=disabled

root = true를 맨 위에 넣어줌으로써 해당 프로젝트 안에 .editorconfig 파일을 인식하는 경계지점을 설정해줍니다.
(프로젝트 root 경로에 root = true로 된 .editorconfig가 있으면 프로젝트 root 경로를 끝으로 상위 폴더에 가서 .editorconfig를 찾지 않겠다는 것입니다.)

위에서 다른 부분은 제치고 [*.{kt,kts}] 기준으로 kt, kts 파일에 적용할 editing 형식을 지정하게 되는데요. disabled하고 싶은 ktlint 규칙 설정도 그 아래에 넣어주면 됩니다. 위 내용처럼 disabled 처리하고 ktlintCheck 작업을 수행하면 해당 rule 위반 내용이 안나오게 됩니다.

특정 ktlint rule disabled 처리하는 것과 관련해서 pinterest document에서 친절하게 가이드해주고 있는데요. 링크 참고하셔서 사용해보시면 좋을 것 같습니다. https://pinterest.github.io/ktlint/0.49.0/rules/configuration-ktlint/#disabled-rules

 

KtLint configuration - Ktlint

KtLint configuration Ktlint uses a limited set of .editorconfig properties for additional configuration. A sensible default value is provided for each property when not explicitly defined. Properties can be overridden, provided they are specified under [*.

pinterest.github.io

.editorconfig는 참고로 코틀린 파일외의 여러 파일들에 대한 스타일을 설정할 수 있어서 어떤 환경에서 작업을 하든 해당 프로젝트를 받기만해도 형식을 맞출 수 있어서 잘 활용하면 좋을 것 같습니다.

 

4. git commit 시 ktlint 연동하기

개발작업을 다하고 git commit을 하게 되는데요. 이 때에도 ktlint check 작업을 연동해서 commit 하기 전에 형식 관련해서 rule 위반 사항이 있는지 자동으로 체크할 수 있도록 설정할 수 있습니다.

$ ./gradlew addKtlintCheckGitPreCommitHook

ktlint gradle plugin이 적용되어 있는 상태로 프로젝트 루트 경로에서 위의 명령어만 입력하면 설정 끝입니다.

git commit을 시도하면 gradle ktlint 작업을 진행하게 됩니다. ktlintCheck를 통과했을 때 commit이 제대로 되고 만약 rule 위반사항이 있다면 commit이 되지 않고 에러를 반환하게 됩니다. 프로젝트에 gradle ktlint plugin을 적용했다면 이러한 설정을 적용해서 git commit시 놓쳤던 ktlint 규칙 위반내용들을 알아서 걸러낼 수 있도록 하면 좋을 것 같네요.

 

위의 모든 내용에 대해서 적용해보았던 테스트 프로젝트 github repository 링크를 첨부해놓겠습니다. 참고하세요~

 

Spring Boot + kotlin 프로젝트 환경에서 ktlint 적용하는데 있어서 조금이나마 도움이 되었으면 좋겠습니다.
혹시나 틀린내용이 있거나 제가 알지 못했던 내용을 알고 계시다면 언제든 댓글 주세요. 감사합니다~!