코드 품질을 향상시키기 위해선 컨벤션, 단위테스트, 정적 분석 등 여러 가지를 고려해야 한다.

이번 글에서는 팀에서 코딩 스타일을 공통으로 관리하기 위해 고민했던 내용, 적용한 사례, 그리고 느낀 점까지 기록해보려 한다.


배경

프로젝트를 시작할 땐 BE 개발자가 3명이었다. 3명의 코딩스타일을 맞추기 위해 깊게 고민할 필요는 없었고 단순히 intelliJ 플러그인 중 하나인 ktlint를 각자의 IDEA에 설치해서 최소한으로 컨벤션을 맞추고 프로젝트를 진행했다.

 

그 후 동료들이 늘어났지만 변한 건 없었다. 각자의 담당영역이 나뉘어 있었고 코드리뷰를 할 때 코딩스타일 컨벤션까지는 세세하게 보지 않았다. 

 

그러다 최근 서비스에 대규모 리뉴얼 작업을 진행하게 되면서 여러 사람들이 엮인 로직을 작업하게 되었는데 내가 작업할 코드가 빨간 줄 투성이거나 혹은 작업한 코드의 코딩스타일이 바뀌어져 있는 경우가 많았다.

 

원인이 무엇일까 고민했고 내린 결론은 다음과 같았다.

 

첫 번째로 '코딩스타일 컨벤션 체크'를 안 하는 사람도 있었다.

하지 않더라도 (분명 ide에선 빨간 줄로 보일 텐데...) 코드가 동작하는데 문제는 없기 때문에 신경 쓰지 않는 건가 싶었다.

 

두 번째는 명확하진 않지만 ide 설정에서 변경했거나 ktlint 버전 차이 때문에 standard rule이 변경되어서 코딩 스타일이 차이가 있는 게 아닐까 싶었다.

 

그렇기 때문에 코딩스타일을 공통관리하고 컨벤션 체크에 강제성을 부여할 필요성을 느꼈다.


Ktlint

ktlint이 뭔지부터 다시 한번 집어봤다. 

ktlint는 kotlin 코드 스타일을 검사하고 적용하기 위한 정적 분석 도구로서 ktlint는 코드의 일관성과 가독성을 높이기 위해 kotlin 코딩 컨벤션을 적용하고 코드에서 발견된 문제점을 지적하고 수정하는 도움을 줍니다.

ktlint는 Gradle, Maven, Ant 및 Command Line Interface(CLI)와 같은 다양한 빌드 시스템과 통합할 수 있으며, IntelliJ IDEA, Android Studio, Visual Studio Code 등 다양한 통합 개발 환경에서도 지원됩니다.

Kotlin 프로젝트에서 ktlint 사용하면 코드의 일관성과 가독성을 향상시키고, 코드 리뷰 과정에서 발견되는 문제를 줄일 있다.

 

위에서 언급한 것과 같이 ktlint는 빌드 환경에서 사용할 수 있도록 libarary 형태가 있고 에디터에서 쉽게 사용할 수 있도록 만든 플러그인 형태가 있었다. 

 

Gradle을 이용해서 build pipeline에 적용한다면 공통의 코딩스타일 컨벤션을 가지고 코드 체크할 있고, 강제성을 추가 있어서 코드의 품질을 유지하는데 효과적일 이라고 생각이 들었다.


도입기

1.  특정 브랜치 (Develop , Master)에 build 할 때 CI에서 ktlint 컨벤션 체크  

방식: develop or master 브랜치에 push 후 build 될 때 컨벤션을 체크해서 실패 처리

결론: 실패된 작업을 수정하기 위해서 작업 브랜치부터 다시 진행을 해야 하는 불편함이 있고 혹시나 다른 사람들이 작업한 소스의 영향도 받을 수 있기 때문에 포기했다.

 

 

2.  작업 브랜치 Push 시점에 체크

방식: git hook pre-push를 이용해서 브랜치 push 시점에 체크, 컨벤션 오류일 경우 push 실패처리

결론: 코딩 스타일 컨벤션을 맞추기 위한 불필요한 commit 로그가 많아질 것으로 보임, 좀 더 빠른 시점에 체크하는 게 나을 것 같다고 판단함.

 

 

3.  Commit 시점에 체크

방식: git hook pre-commit을 이용해서 coomit 시점에 체크, 컨벤션 오류일 경우 commit 실패처리

결론: 결국 가장 작은 단위인 commit 할 때부터 컨벤션 체크를 하는 게 맞다고 생각, 이 방식으로 작업 진행


작업 

1. IntelliJ Plugin: https://plugins.jetbrains.com/plugin/15057-ktlint-unofficial-  (version "0.10.0")

  • 작성한 코드의 코딩 스타일 컨벤션을 실시간으로 확인해서 알려주는 기능.
  • Preferences > Plugins > Ktlint 설치

 

2. gradle 플러그인 https://github.com/JLLeitschuh/ktlint-gradle (version "11.3.1") + git hook pre-commit 세팅 

  • gradle 플러그인: 전체/부분 로직에 대한 코딩스타일 정적검사를 진행할 수 있음
  • pre-commit 스크립트: commit 이전에 진행되는 작업이 적힌 스크립트. - 해당 스크립트에 코딩스타일 컨벤션 검사 로직을 추가

 

  • gradle 플러그인 설치 & build
plugins {
		id("org.jlleitschuh.gradle.ktlint") version "11.3.1”
}



apply(plugin = "org.jlleitschuh.gradle.ktlint")

 

  • pre-commit 작성방법 
    • 1. ./gradlew addKtlintCheckGitPreCommitHook - 기본적으로 컨벤션 체크해 주는 pre-commit 스크립트를 만들어준다.
    • 2. .git/hooks/pre-commit 스크립트를 직접 생성하기. (feat. 킹갓제너럴 ChatGPT )
           컨벤션 불일치하는 라인을 표시하는 작업을 추가함.
#!/bin/sh
######## KTLINT-GRADLE HOOK START ########

CHANGED_FILES="$(git --no-pager diff --name-status --no-color --cached | awk '$1 != "D" && $NF ~ /\.kts?$/ { print $NF }')"

if [ -z "$CHANGED_FILES" ]; then
    echo "No Kotlin staged files."
    exit 0
fi;

echo "Running ktlint over these files:"
echo "$CHANGED_FILES"

diff=.git/unstaged-ktlint-git-hook.diff
git diff --color=never > $diff
if [ -s $diff ]; then
  git apply -R $diff
fi

echo "KTLINT CHECK START"
ktlint_output=$(./gradlew ktlintCheck -PinternalKtlintGitFilter="$CHANGED_FILES")
if [ $? -ne 0 ]; then
  echo "KTLINT CHECK FAIL"
  echo "check these files:"
  while read -r line; do
    if [[ "$line" =~ ^.*\.kt:[0-9]+:[0-9]+.*$ ]]; then
      echo "$line"
    fi
  done <<< "$ktlint_output"
  exit 1
fi


  echo "KTLINT CHECK SUCCESS"


if [ -s $diff ]; then
  git apply --ignore-whitespace $diff
fi
rm $diff
unset diff

  echo "KTLINT CHECK FINISH"
exit 0
#exit $gradleCommandExitCode
######## KTLINT-GRADLE HOOK END ########

 

3. .editorconfig 파일 설정

    • ktlint 기본 컨벤션 외에 프로젝트에 적용되는 예외 규칙들 작성 리스트 
    • 자세한 내용은 EditorConfig 참조. 
    • .editorconfig 파일이 없는 경우 기본룰 Ktlint 버전에 따라서 Standard rules 기본적으로 따르지만 버전이 변경이 되면 Standard rules 변경이 있기 때문에 root 디렉터리에 .editorconfig파일을 설정하는 것을 권장.


결과

commit 요청 클래스가 코딩스타일 컨벤션에 일치하는 경우: 정상적으로 커밋 성공

commit 요청 클래스가 코딩스타일 컨벤션에 일치하지 않는 경우: console에 에러 표시 & 불일치 라인과 이유 표시


추가적으로 고민해 볼 내용

표시되는 코딩 스타일 컨벤션 오류에 대한 고민 

코드 수정이 아니라 컨벤션 수정을 고려해야 할 수도 있음.

max-line-length가 70으로 설정되어 있어서 작성된 코드들을 줄 바꿈 해야 한다고 알려준다.

하지만 제안에 맞게 코드를 바꾸게 된다면 프로젝트 내 다른 코드들도 전부 변경해줘야 하기 때문에 max-line-length을 늘리는 것을 고려해 볼 수 있다.

 

ktlint 버전 차이에 의한 rule 차이

ktlint 버전은 계속 변하면서 kotlin standard rule도 바뀐다.

한 예로 ktlint 0.42.1 버전에선 rule에 걸리지 않았던 내용이 0.47.1 버전에서는 rule에 잡힘.

그렇기 때문에 꾸준한 버전 관리를 통해서 코딩스타일 컨벤션을 꾸준히 Update 해주는 것이 필요하다고 느꼈다.


마무리

간단할 줄 알았던 코딩 스타일 컨벤션 세팅을 작업하고 나니 생각보다 고려할게 많았고, 작업량에 비해서 시간도 많이 소요되었다. (대부분이 고민, 삽질 등..)

또한, 코딩스타일 규칙을 강제했더니 error를 해결하기 위해 코드 리펙토링을 진행할 수 밖에 없는 환경도 생겼다. (물론 제약이 생겨서 답답한면도 많았다.) 

하지만 명확한 정책을 세우고, 나뿐만 아니라 팀원들이 좀 더 나은 품질의 코드를 볼 수 있겠다는 생각에 뿌듯...

지속적으로 팀원들간에 협의를 통해서 개선해 나갈 예정이다.

 

함께 관리해야 하는 코드는 공통으로 관리할 수 있는 규칙과 그 규칙을 지킬 수 있는 환경을 만들어 주는 게 중요하다는 점을 배운 시간이지 않나 싶다.

+ Recent posts