본문 바로가기
백엔드 개발

#047. 코프링: ktlint 적용하기 & pre-commit 룰 만들기

by iamjoy 2023. 7. 9.

기본 설정들

설정을 하면 자동으로 check 하거나 formatting 할 수 있다. 기본으로 설정되는 규칙 중 몇가지를 보면 아래와 같다.
https://pinterest.github.io/ktlint/0.50.0/rules/standard/

Standard rules - Ktlint

Standard rules Annotation formatting Multiple annotations should be on a separate line than the annotated declaration; annotations with parameters should each be on separate lines; annotations should be followed by a space Rule-id: annotation (standard rul

pinterest.github.io

- Argument list wrapping (파라미터 목록 래핑 방법)
모든 파라미터는 같은 줄에 있거나 모든 인수는 별도의 줄에 있어야 합니다.

val x = f(
    a,
    b,
    c
)

- class 네이밍 규칙: Pascal Case

class Foo
class Foo1

- Enum 네이밍 규칙: Pascal 또는 underscore-separated

enum class Bar {
    FOO,
    Foo,
    FOO_BAR,
    FooBar
}

- Final newline: 각 파일 끝에 줄 바꿈이 일관되게 사용되도록 합니다.
- Import ordering : 수입품이 일관되게 주문되도록 보장
- No consecutive blank lines: 연달아 여러 빈 linebreak를 허용하지 않습니다.
- No consecutive blank lines: 빈 body {} 를 허용하지 않습니다.
- No line break after else: 예를 들어 혼동을 일으킬 수 있는 경우 else 키워드 뒤에 줄 바꿈을 허용하지 않습니다:

fun funA() {
    if (conditionA()) {
        doSomething()
    } else if (conditionB()) {
        doAnotherThing()
    }
}

- No semicolons: 세미콜론은 사용할 수 없습니다(같은 줄에 있는 여러 문을 구분하는 데 사용하지 않는 한).
- No trailing whitespaces
- No wildcard imports: import에 * 를 사용하지 않습니다.
이외에도 spacing, 띄어쓰기, linebreak 등 여러 규칙들이 있고 위 공식 사이트에서 검색해 확인해 볼 수 있다.
./gradlew ktlintCheck 로 린트 실행하기
ktlintCheck 로 린트 상태를 확인해보면 다음과 같이 문제가 되는 부분을 찾아준다

 

Custom하기: .editorconfig로 기본 설정 override 하기

그런데 이렇게 기본적인 ktlint 룰을 사용하면 기본 린트가 수정된다던지 하는 변화에 영향을 받을 수도 있고, 내부적으로 명시적인 린팅을 할 수 없어서 한계가 있다. 따라서 .editorconfig를 이용해 ktlint를 커스텀해서 사용할 수 있다.

root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
tab_width = 4
max_line_length = 150

[{*.js,*.ts,*.yaml,*.yml,*.md,*.json}]
indent_size = 2

[{*.kt,*.kts}]
ij_kotlin_allow_trailing_comma = true
ij_kotlin_allow_trailing_comma_on_call_site = true

설정이 정상적으로 적용되면, IDE의 kotlin 스타일 설정에 들어가면 아래와 같이 .editorconfig 설정으로 override 되었다는 안내가 뜬다.

자동화1: on-save 로 reformat 하도록 설정하기

IDE 레벨에서 파일 저장시마다 적용될 수 있도록 설정할 수 있다.

자동화2: pre-commit 설정하기

IDE 설정은 개인/컴퓨터 마다 다를 수 있기 때문에 커밋 전에 lint 를 적용하도록 룰을 설정하는 것이 좋다.
(1) build.gradle의 task 이용해 githook 설정하기
.git 이 있는 위치에서 hooks파일로 이동하면 현재 git을 작동할 때 설정된 훅들을 확인할 수 있다. 그 중 pre-commit 파일이 git commit을 하기 전에 실행되는 스크립트이다. 이 스크립트에 ktlint를 실행하도록 설정하면 커밋을 생성 전에 린트를 실행해준다. (스크립트 설정은 검색해서 확인할 수 있으므로 생략)

cd .git/hooks

일부 라이브러리는 이 빌드 시 preCommit이 추가될 수 있는 설정을 지원한다. 그러면 이 모듈을 클론 떠서 build.gradle을 실행할 때 일괄적으로 git hook이 적용되어 모두가 같은 스타일로 작업할 수 있다.
예) https://github.com/jlleitschuh/ktlint-gradle 의 preaddKtlintCheckGitPreCommitHook.

// build.gradle.kts

...
 tasks.check {
     dependsOn("addKtlintCheckGitPreCommitHook")
 }

(2) husky 이용하기
husky를 통해서 githook을 설정할 수도 있다. 나는 아래와 같이 pre-commit으로 ktlintCheck를 하도록 설정했다.

참고: Spotless 로 룰 추가하기

https://nesoy.github.io/articles/2020-04/Spotless

Reference

https://stackoverflow.com/questions/49912695/git-pre-and-post-commit-hooks-not-running
https://typicode.github.io/husky/getting-started.html
https://kotlinlang.org/docs/code-style-migration-guide.html