훌륭한 개발자가 되기 위하여
[Android] Ktlint적용하기 본문
Ktlint란?
Kotlin 공식 Coding Convention을 기준으로 code를 분석해주고 올바르게 수정까지 도와주는 정적 분석 도구이다.
설정하기
먼저 프로젝트 및 모듈 단위의 build.gradle
에 종속성을 추가한다.
plugins {
id("org.jlleitschuh.gradle.ktlint") version "12.1.1"
}
project 단위의 build.gradle 의 plugin 밑에
subprojects {
apply plugin: "org.jlleitschuh.gradle.ktlint" // Version should be inherited from parent
// Optionally configure plugin
ktlint {
debug = true
}
}
코드를 작성하거나 app 수준의 gradle에서
plugins {
...
id "org.jlleitschuh.gradle.ktlint"
}
...
android {
...
ktlint {
debug = true
}
}
코드를 작성한다.
Ktlint는 별다른 설정 없이도 Default 규칙으로 실행될 수 있지만, .editorconfig
파일을 설정해 명시적으로 선언하는 것을 권장한다.
- 상위 디렉토리의 .editorconfig가 참조되는 경우를 막음 -> root = true 라는 선언이 된 .editorconfig 파일을 찾기 전까지는 모든 상위 디렉토리를 탐색한다.
- ktlint가 버전이 올라가면서 Default 값이 변경될 수 있음
- 다양한 IDE와 Editor 등의 도구에서 이 설정을 참조하기 때문
- Kotlin 공식 코딩 컨벤션에 명시되지 않아도 추가로 규칙 설정 가능
Global Patterns
*
: 경로(/
)를 제외한 파일 혹은 폴더에 적용**
: 일치하는 string이 있는 파일 혹은 폴더에 적용?
: 일치하는 string이 있는 파일 혹은 폴더에 적용[name]
: name과 일치하는 파일 혹은 폴더에 적용[!name]
: name과 일치하지 않는 파일 혹은 폴더에 적용{s1, s2}
: 일치하는 파일 혹은 폴더에 적용 (EditorConfig Core 0.11.0 이후 버전만 ){num1..num2}
: 양수 혹은 음수인 num1과 num2 사이의 정수에 적용
예시)
/example/**/*
: 'example'폴더 안의 폴더 혹은 파일에 적용**/*.kt
: 어떤 폴더안의 'kt'로 끝나는 파일에 적용!x.kt
: 'kt'을 제외한 파일에 적용
EditorConfig Properties
indent_style
: 들여 쓰기를 'tab', 'space'중 들여쓰기 스타일 설정indent_size
: indent_style = space일 경우, 몇 칸 할 것인지 설정tab_width
:indent_style = tab
일 경우 width 설정 (기본적으로indent_size
값을 따라가 거의 설정하지 않음)charset
: 'latin1', 'utf-8', 'utf-8-bom', 'utf-16be', 'utf-16le'로 설정하여 문자 집합 제어(주로 'utf-8'로 설정)trim_trailing_whitespace
: "true" or "false"로 줄 바꿈 문자 앞에 있는 공백 문자를 제거 여부max_line_length
: "off" or 양수로 설정하여 최대 줄 길이 설정insert_final_newline
: "true" or "false"로 줄바꿈으로 끝나도록 하는지 설정end_of_line
: 'lf', 'cr', 'crlf'중 하나로 줄바꿈 설정
- LF(Line Feed, \n): 커서를 다음 줄로 이동
- CR(Carriage Return, \r): 현재 커서를 줄 바꿈 없이 가장 좌측으로 이동
- CRLF: 윈도우에서 주로 사용하며, 리눅스/맥(10버전 이후)에서는 LF를 사용한다.
.editorconfig 파일 예시
[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
# Kotlin 파일에만 적용될 설정
[*.{kt,kts}]
max_line_length = 300
스타일 체크 사용법
기본 사용법
- 스타일 체크
./gradlew ktlintCheck
스타일 검사를 수행한다../gradlew build
를 실행했을 때 연결되는 전체 프로젝트 빌드 싸이클에 포함되어 정의한 코드 스타일을 지키지 않으면 빌드가 실패한다. - 스타일 변환
./gradlew ktlintFormat
스타일에 맞지 않는 코드를 정의한 코드 스타일에 적용하여 전체적으로 바꿔준다.
Commit 단계 자동 체크
./gradlew addKtlintCheckGitPreCommitHook
:ktlintCheck
을 pre-commit hook으로 등록./gradlew addKtlintFormatGitPreCommitHook
:ktlintFormat
을 pre-commit hook으로 등록
CI 단계 스타일 강제
CI(Continuous Integration, 지속적인 통합)
Github Actions 기반으로 CI가 구성되어 있다면 코드 스타일 명세를 아래와 같이 강제할 수 있다.
name: Android CI
on:
pull_request:
branches: [ "main", "dev" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- name: Check ktlint Check
run: ./gradlew ktlintCheck
빌드 java 버전 지정 후 build 과정에서 오류가 발생하지 않는 경우 ktlint check 진행
위 파일을 적용하여 pull-request를 요청하였지만 빌드하는데 4분 정도의 시간이 소요되었다. (프로젝트 초기 세팅 단계임에도...)
Github-Action 빌드 시간 단축 시키기
빌드 캐시
빌드 캐시는 캐시 키 값이 일치해야 사용할 수 있다.
빌드 캐시 키는 의존성이 바뀔 때마다 값이 달라진다.
빌드 캐시 Input
key - 캐시 항목의 명시적인 키
path - 캐시하고 복원할 파일, 디렉터리 및 와일드카드 패턴의 목록
restore-keys - 캐시 적중이 발생하지 않았을 때 오래된 캐시를 복원하기 위해 사용하는 접두사 일치 키의 순서가 있는 목록
key : 키 값이 완전히 일치해야 캐시가 적용됨
실행하는 운영체제와 gradle파일, gradle-wrapper.properties의 내용이 변경될 때마다 고유한 해시 값을 생성하여 캐시 키에 포함시킨다. 캐시 키값을 대조해서, 값이 일치하지 않을 경우 의존성을 다시 설치하고 새로운 캐시를 생성한다.
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
path : 명시된 경로의 파일을 캐싱함
path: |
~/.gradle/caches
~/.gradle/wrapper
restore-key: 키 값이 달라도 유사한 캐시가 적용됨
restore-key를 쓰는 이유는 의존성 변경이 일어났을 때 key값이 달라지고, 캐시가 적용되지 않을 경우를 대비하는 것이다.
아래와 같이 restore-key를 사용하면 같은 운영체제, runner.os-gradle또는 runner.os-로 시작하는 유사한 캐시를 사용하게 된다.
restore-keys: |
${{ runner.os }}-gradle-
빌드 캐싱 스텝 추가하기
name: Android CI
on:
pull_request:
branches: [ "main", "dev" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: gradle
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- name: Check ktlint Check
run: ./gradlew ktlintCheck
Github Action Secrets로 환경변수 관리하기
ReviewDocs 이용하기
Github Action 적용법
1단계
git hub의 Marketplace에서 사용할 액션 결정하기
(Run ktlint with reviewdog으로 사용 결정)
2단계
Run ktlint with reviewdog의 문서를 토대로
.github/workflows 폴더에 ktlint-reviewdog.yml 파일을 생성한 후
다음과 같이 작성
각각 기능의 설명은 주석으로 작성해두었음.
name: reviewdog // reviewdog라는 이름으로 정의
on: [pull_request] // Pull Request를 발생할 때 실행됩니다.
jobs: // 실행할 작업 (ktlint)
ktlint:
name: Check Code Quality // Check Code Quality 로 정의
runs-on: ubuntu-latest // ubuntu 환경에서 실행 (최신 버전)
steps: // 작업 단계
- name: Clone repo
uses: actions/checkout@master // 액션을 사용해 저장소를 클론
with:
fetch-depth: 1 // 최신 커밋만 가져옴.
- name: ktlint
uses: ScaCap/action-ktlint@master // 액션으로 ktlint 실행
with:
github_token: ${{ secrets.github_token }} //깃허브 비밀토큰으로 인증
reporter: github-pr-check // github-pr-check로 설정
fail_on_error: true // true를 넣어야지 오류가 떴을 때
// fail을 반환해줌
github-pr-check, github-pr-review 차이
- github-pr-check는 pr에 대한 스타일 위반 여부를 Checks에 요약 정보를 표시
- github-pr-review는 pr에 대해 스타일 위반 사항을 GitHub의 리뷰 코멘트로 남김.
3단계
.editorconfig를 통해 세부적인 체크 기준 설정
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
max_line_length = 140
trim_trailing_whitespace = true
[*.{kt,kts}]
indent_size = 4
ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL
ij_kotlin_name_count_to_use_star_import = 2147483647
ij_kotlin_name_count_to_use_star_import_for_members = 2147483647
ij_kotlin_packages_to_use_import_on_demand = unset
ktlint_code_style = ktlint_official
ktlint_standard_string-template-indent = disabled
ktlint_standard_multiline-expression-wrapping = disabled
ktlint_function_naming_ignore_when_annotated_with = Composable
ktlint_standard_max-line-length = disabled
ktlint_standard_no-wildcard-imports = disabled
ktlint_standard_package-name = disabled
[*.{yml,yaml}]
indent_size = 2
결과
경량화로 평균 20초 정도의 체크 시간 소요
참고
링크들 및 설치 링크
https://jja2han.tistory.com/408
https://msyu1207.tistory.com/entry/깔끔한-포맷팅을-위한-ktlint-적용하기-feat-kotlin
run-Ktlint-with-reviewdog
https://github.com/marketplace/actions/run-ktlint-with-reviewdog
'안드로이드' 카테고리의 다른 글
코루틴 제어 (0) | 2025.01.07 |
---|---|
스레드 기반 작업의 한계, Coroutine Dispatcher (0) | 2025.01.06 |
[Android | Kotlin] 안드로이드 기본 앱과 연동하기 (1) | 2024.01.03 |
[Android | Kotlin] 콘텐츠 프로바이더 이해하기 (0) | 2024.01.03 |
[Android | Kotlin] 잡 스케줄러 (1) | 2023.12.31 |