Ktlint란?
Kotlint에서 코딩 스타일을 자동으로 통일시켜 주는 도구
컴퓨터는 똑같이 인식해도, 사람마다 여러 코딩 스타일이 다를 수 있습니다. 대표적으로는 중괄호가 있습니다.
# 1번째 스타일
fun main()
{
println("Hello World!")
}
# 2번째 스타일
fun main() {
println("Hello World!")
}
1~2명이서 작업한다면 이런 스타일의 차이가 크게 상관없지만 여러 명이서 작업하면 큰 문제가 됩니다. 이건 여러 이유가 있는데요. 제가 느낀 이유 3가지는...
- 누가 작성했느냐에 따라 스타일이 너무 다르면 일관성이 떨어져 코드 읽기가 힘들어짐
- 같은 부분을 수정하면 Git에서 Conflict이 나서 이걸 해소하느라 불필요한 시간을 소모하게 됨
- 내가 작성한 코드라도 최대한 스타일을 맞추려고 해도 수동으로 하니 계속 놓치게 됨
이 같은 이유를 해결하기 위해 있는게 Lint입니다. Lint는 자동으로 코드 스타일을 맞춰 주는 프로그램입니다. 이걸 각자 설치해서 사용할 수도 있지만 Git과 연동해서 Commit 할 때는 무조건 Lint를 돌리게 설정할 수도 있고, 배포도 Lint에 맞지 않으면 막을 수도 있습니다. (이건 너무 극단적이긴 하지만...)
그리고 Pinterest라는 회사가 처음 개발하고, 지금은 오픈소스화한 Kotlin에서 가장 많이 쓰이는 Lint가 바로 Ktlint입니다.

Gradle에서 Ktlint 사용하기
Ktlint도 결국은 프로그램이기 때문에 우리가 원하는 대로 실행할 수 있도록 Gradle에 설정할 수 있습니다. 하지만... 이렇게 직접 하는 건 상당히 복잡하고 번거로운 작업입니다. 그래서 Gradle에서 제공하는 Plugin이라는 기능을 보통 사용합니다.
Gradle Plugin은 Gradle에서 실행할 수 있는 여러 Task나 설정을 라이브러리처럼 import해서 직접 작성하지 않고 사용할 수 있게 해 주는 기능입니다. 예를 들어 보통의 Spring 프로젝트로 build.gradle에 가서 Plugin 부분을 보면 아래 사진과 같이 여러 Plugin을 사용하고 있습니다.
plugins {
kotlin("jvm") version "1.8.22"
kotlin("plugin.spring") version "1.8.22"
kotlin("plugin.jpa") version "1.8.22"
id("org.springframework.boot") version "2.7.15"
id("io.spring.dependency-management") version "1.1.3"
id("com.adarshr.test-logger") version "4.0.0"
}
Spring Boot Plugin을 예시로 들자면 org.springframework.boot라는 Gradle Plugin을 사용함으로서 아래 사진과 같이 Spring Boot를 쓰는데 편리한 여러 Gradle Task들을 직접 작성하지 않고 사용할 수 있습니다.

실제로 Ktlint의 공식 문서에서도 Ktlint를 사용하기 위해 직접 Gradle과 연동하지 말고 Gradle Plugin을 사용할 것을 추천하고 있습니다.

그중에서도 저는 JLLeitschuh / ktlint-gradle라는 Plugin을 선택했습니다. 이유는 크게 2가지가 있습니다.
- 가장 유명하고 자주 쓰임
- 최근까지 (제가 적용한 시점에서는 2일 전) 유지보수 되고 있음
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
JLLeitschuh / ktlint-gradle 설치하기
설치하는 방법은 간단합니다. 우선 당연히 build.gradle의 plugins에 JLLeitschuh / ktlint-gradle를 추가해 줍니다.
plugins {
id("org.illeitschuh.gradle.ktlint") version "11.0.0"
}
그리고 subprojects들에 (단일 module이라면 그냥 project에) plugin을 적용합니다.
subprojects {
apply(plugin = "org.jlleitschuh.gradle.ktlin")
}
이렇게 하고 gradle을 새로고침 하면 설치 자체는 끝입니다. 추가적으로 원하는 옵션은 configure에서 지정할 수 있습니다.
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
// 여기에 공식 문서를 참고해서 원하는 옵션을 지정
}
Ktlint 옵션 우리 상황에 맞게 바꾸기
기본으로 Gradle Plugin이 지정해 준 옵션이 다 마음에 들면 다행이지만 저는 여러 가지 설정을 변경하고 싶었습니다.
- 오류가 나면 console에 메세지가 자세히 나왔으면 좋겠다 (debug 모드 설정)
- 실패해도 build는 잘 됐으면 좋겠다
- Ktlint 설정을 일부 바꾸고 싶다 (*로 import 안 되게 한다던가, 1줄의 길이 제한한다던가, trailing comma 없앤다던가...)
이 외에도 여러 설정을 바꾸고 싶을 수 있는데요. 사실 모든 건 공식 문서에 나와 있어 맨 밑에 있는 문서들을 참고하면 되지만, 위 3개는 제가 어떻게 했는지 간단히 알려 드리겠습니다.
🐜 오류가 났을 때 메세지 자세히 나오게 하기
요것은 간단히 Gradle의 configure에서 debug 옵션을 활성화시켜 주면 됩니다.
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
debug.set(true)
}
🐜 실패해도 build에는 영향 없게 하기
우선 비슷하게 configure에서 Plugin 단위에서 실패를 없게 해 줘야 합니다.
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
ignoreFailure.set(true)
}
하지만 이렇게 해도 build할 때 여러 ktlint 관련 task들이 도는 경우가 많아 그때는 console을 보면서 1개 1개 모두 비활성화시켜 줘야 합니다.
tasks.named("build").configure {
subprojects {
tasks.named("ktlintCheck").configure { enabled = false }
tasks.named("ktlintMainSourceSetCheck").configure { enabled = false }
tasks.named("ktlintTestSourceSetCheck").configure { enabled = false }
// 이 외에도 build 실패하게 하는 ktlint 관련 task들 모두 비활성화
}
}
🐜 Ktlint 설정 바꾸기
Ktlint의 설정을 바꾸는 방법은 크게 2가지가 있습니다.
- Gradle에서 직접 변경하기
- .editorconfig에서 지정하기
낮은 버전의 Ktlint를 사용해야 한다면 .editorconfig를 지원하지 않아서 어쩔 수 없지만, 그 외에는 .editorconfig를 사용하도록 권장하고 있습니다. .editorconfig을 사용하면 아래와 같이 간단하게 ktlint 기본 스타일에서 내가 원하는 방식으로 변경할 수 있습니다.
max_line_length = 10_000 # 1줄을 최대 1만 글자까지 (사실상 제한 없애기)
ktlint_standard_filename = disabled # (파일 이름에 제한 없애기)
ktlint_standard_trailing-comma = true # (trailing comma 허용하기)
disabled_rules=no-wildcard-imports # *를 사용한 import 허용하기
하지만 주의할 점은... 특정 버전 이상의 ktlint만 이걸 지원한다는 겁니다. Ktlint 버전은 Gradle의 configure를 사용해서 강제로 지정해 줄 수 있습니다.
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
version.set("0.43.2") // .editorconfig의 일부 옵션들을 사용하기 위해 KtLint 버전 강제
}
내가 쓰고자 하는 모든 버전은 Ktlint 공식 사이트에 가서 버전을 바꾼 뒤, 내가 사용하고 싶은 모든 옵션을 검색한 뒤 결과가 있는지 확인하면 됩니다.


이렇게 한 뒤에 Gradle Plugin과의 호환성 문제가 없는지 Ktlint를 돌려 보며 검증해야 하지만... 대부분의 경우 잘 동작합니다. 이 과정이 번거로우시다면 제가 찾은 버전을 쓰셔도 좋습니다!
- Ktlint: 0.43.2
- ktlint-gradle: 11.0.0
편의성 향상: Git Pre-Commit Hook 설치하기
🐜 하려는 것
ktlint를 적용하려는 이유가 보통 여러 명이 1개의 프로젝트에서 작업할 때의 일관성을 보장하고 git conflict를 피하려고 하는 걸 텐데, ktlint를 적용할 것을 각자의 자유에 맡기면 의미가 없습니다. 그래서 commit을 하기 전에 gradle을 통해서 ktlintCheck을 돌리고, 실패하면 commit을 하지 못 하게 막으려고 합니다.
🐜 Git Commit Hook?
Git Commit Hook이란 Git에서 Commit 하기 전/후 등 여러 생명주기에서 실행항 스크립트입니다. 그 중에서도 Pre-commit Hook을 사용하면 Commit을 진행하기 전에 스크립트를 실행하고, 특정 조건에 따라 Commit을 막을 수가 있습니다.
🐜 Pre-Commit Hook으로 Ktlint를 실행하기
#!/bin/sh
./gradlew ktlintCheck
- 1번째 줄은 이 스크립트는 sh를 통해서 실행되야 한다는 겁니다.
- 2번째 줄은 모든 파일이 .editorconfig에 명시된 대로 변경된 ktlint 형태를 따르는지 확인하고 맞으면 통과, 아니면 실패하는 명령어를 실행합니다.
🐜 직접 설치할 필요 없이 Gradle에 통합하기
사실 Local 환경에 Ktlint를 설치하면 Pre-Commit Hook를 설치할 수 있는 명령어를 실행할 수 있습니다.
ktlint installGitPreCommitHook
하지만 이 프로젝트를 사용하는 모든 사람에게 Local에 Ktlint를 설치하고, 해당 명령어를 실행하라고 하면 너무 번거롭습니다. 그래서 Gradle Task를 만들어서 자동으로 Pre Commit Hook을 설치할 수 있게 해 보겠습니다.
tasks.register("installKtlintGitPreCommitHook") {
val hooksDirectory = file(".git/hooks")
val hooksFile = hooksDirectory.resolve("pre-commit")
doLast {
if (!hooksDirectory.exists()) {
hooksDirectory.mkdirs()
}
hookFile.writeText(
"""
#!/bin/sh
./gradlew ktlintCheck
"""
)
hookFile.setExecutable(true))
}
}
- 현재 프로젝트의 .git 폴더를 찾고 (없으면 만들고)
- 거기에 Gradle Plugin을 통해서 설치된 KtlintCheck을 gradlew를 통해서 실행시켜 줍니다
- 이렇게 하면 해당 프로젝트의 .git 폴더만 영향이 가기 때문에 다른 ktlint가 없을 수도 있는 프로젝트에서는 문제없이 Commit이 됩니다.
이제 이 Gradle Task를 자동으로 실행할 수 있게 해야 합니다. 저는 그냥 build 할 때 설치하도록 했습니다. build는 프로젝트에 작업해서 commit 하기 전에 1번을 할 테니... 만약 하지 않고 push까지 하더라도 다음으로 알아볼 Github Actions에서 최종적으로 막을 수 있기 때문에 이 정도는 괜찮다고 생각했습니다.
tasks.named("build").configure {
dependsOn("installKtlintGitPreCommitHook")
}
편의성 향상: Github Actions에 통합해서 PR 만들 때 자동으로 확인하기
마지막으로 Github PR을 만들면 자동으로 Ktlint를 돌리도록 해 보겠습니다. Github Actions를 사용하기 때문 하고, Github Actions 관련해서는 이미 설정이 돼 있다고 가정하겠습니다.
Github Actions는 yaml 설정 파일에 추가만 하면 자동으로 파이프라인에 추가되니 .github에 아래와 같이 파일을 추가하면 끝납니다.
name: Pull Request
on:
pull_request:
branches: [ develop, master ]
jobs:
lint:
name: ktlint
runs-on: [ self-hosted ]
steps:
- uses: actions/checkout@v3
- name: Set up Java (JDK 17)
uses: actions/setup-java@v3
with:
distribution: corretto
java-version: 17
- name: Set up Gradle
uses: actions/gradle-build-action@main
- name: Run ktlint with Gradle
run: ./gradlew ktlintCheck
- 특정 branch (develop, master)에 PR을 만들면 실행됩니다.
- Jobs에 Java 환경 세팅하고, Gradle 세팅하고, 익숙한 ktlintCheck을 실행시키는 게 끝입니다!
참고
🐜 공식 문서
Features - Ktlint
Welcome to Ktlint Kotlin linter in spirit of feross/standard (JavaScript) and gofmt (Go). Features No configuration required ktlint aims to capture the Kotlin coding conventions and Android Kotlin Style Guide. In some aspects ktlint is a bit more strict*.
pinterest.github.io
🐜 공식 Github Repository
GitHub - pinterest/ktlint: An anti-bikeshedding Kotlin linter with built-in formatter
An anti-bikeshedding Kotlin linter with built-in formatter - pinterest/ktlint
github.com
🐜 가장 유명한 Ktlint Gradle Plugin Github Repository
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
'👨💻 프로그래밍 > 📦 Backend' 카테고리의 다른 글
IntelliJ 디버거 사용하기 (0) | 2025.03.22 |
---|---|
@FunctionalInterface란? (0) | 2025.01.30 |
(Spring 위주로) AOP 용어 정리 (0) | 2025.01.26 |
MDC로 풍부한 로그 쉽게 남기기 (0) | 2025.01.12 |
🥒 피클 (PKL): 새로운 설정 관리 언어 알아보기 (0) | 2024.11.02 |