[Briefing] Spotless로 코드 포맷 유지하기

Peter·2023년 12월 27일
post-thumbnail

🚀 코드 Formatter의 필요성

코드 Formatter의 필요성은 소프트웨어 개발의 여러 측면에서 중요합니다. 주요 이점은 다음과 같습니다.

  1. 일관성 유지
    Formatter는 팀 내의 모든 개발자가 동일한 코딩 스타일을 유지하도록 도와줍니다.
  2. 가독성 향상
    일관된 코드 포맷팅은 코드의 가독성을 크게 향상시킵니다. 이는 코드의 이해를 돕고, 디버깅 및 유지보수를 용이하게 만듭니다.
  3. 시간 절약
    자동화된 포맷팅으로 수동으로 코드 스타일을 맞추는 데 소요되는 시간을 줄여줍니다.
  4. 협업 효율성
    일관된 코드 스타일은 팀원들이 서로의 코드를 이해하고 협업하는 데 도움이 됩니다.

💡 Spotless란?

Spotless Github Repository

Spotless는 개발자들 사이에서 널리 사용되는 코드 포맷팅 도구입니다. 주로 Java, Kotlin, Groovy와 같은 프로그래밍 언어를 지원하며, Gradle 및 Maven 빌드 시스템과 통합되어 사용됩니다. Spotless는 코드의 일관성과 가독성을 높이기 위해 다양한 포맷팅 옵션과 규칙을 제공합니다.

이 도구의 주요 특징은 다음과 같습니다

  • 다양한 언어 지원
    Java, Kotlin, Groovy 등 여러 프로그래밍 언어에 대한 지원을 제공합니다.
  • 포맷팅 도구 통합
    Google Java Format, Eclipse Formatter, ktlint 등 다양한 인기 있는 포맷팅 도구와 통합됩니다.
  • 사용자 정의 가능
    프로젝트의 특정 요구사항에 맞게 포맷팅 규칙을 세밀하게 설정할 수 있습니다.
  • 자동화된 코드 정리
    불필요한 공백 제거, 들여쓰기 통일 등을 자동으로 처리합니다.
  • 프로젝트 통합 용이
    Gradle이나 Maven 프로젝트에 쉽게 통합되어, 빌드 프로세스의 일환으로 코드 포맷팅을 자동화할 수 있습니다.

♻️ SpringBoot 프로젝트에 적용

Briefing 프로젝트에서 Spotless 플러그인을 적용한 과정입니다. build.gradle을 수정합니다.

1. Spotless 플러그인 추가

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.2'
    id 'io.spring.dependency-management' version '1.1.2'
    id 'com.diffplug.spotless' version '6.23.3' // Spotless 플러그인
}

2. Spotless 포맷팅 설정 구성

spotless {
    java {
        // Google Java 포맷 적용
        /*
            googleJavaFormat() : 탭은 2개의 공백
            googleJavaFormat().aosp() : 탭은 4개의 공백
            [참고] https://github.com/google/google-java-format/issues/525
         */
        googleJavaFormat().aosp()
        // 아래 순서로 import문 정렬
        importOrder('java', 'javax', 'jakarta', 'org', 'com')
        // 사용하지 않는 import 제거
        removeUnusedImports()
        // 각 라인 끝에 있는 공백을 제거
        trimTrailingWhitespace()
        // 파일 끝에 새로운 라인 추가
        endWithNewline()
    }
}
  • googleJavaFormat()
    Google Java Format을 적용합니다. 이는 구글에서 제공하는 Java 코드 스타일 가이드를 기반으로 하는 포맷팅 규칙을 적용합니다.
  • importOrder('java', 'javax', 'jakarta', 'org', 'com')
    import 문의 정렬 순서를 지정합니다. 이 설정은 import 문을 'java', 'javax', 'jakarta', 'org', 'com' 순으로 정렬합니다.
  • removeUnusedImports()
    사용하지 않는 import 문을 제거합니다. 이는 코드를 깔끔하게 유지하는 데 도움이 됩니다.
  • trimTrailingWhitespace()
    각 줄 끝에 있는 공백을 제거합니다. 이는 파일의 불필요한 공백을 제거하여 깨끗한 코드 형식을 유지합니다.
  • endWithNewline()
    파일의 끝에 새로운 라인을 추가합니다. 이는 일부 코딩 표준 및 도구에서 필요로 하는 규칙입니다.

3. 컴파일 전에 코드 포맷팅 자동 적용

/*
    compileJava 태스크가 실행되기 전에 spotlessApply 태스크가 먼저 실행되도록 구성
    개발자가 별도로 코드 포맷팅을 신경 쓸 필요 없이, 코드가 항상 일관된 스타일을 유지하도록 설정
 */
tasks.named('compileJava') {
    dependsOn 'spotlessApply'
}
  • 순서) spotlessApply 완료 → compileJava 태스크 실행
  • 수동 실행 방법
    • ./gradlew spotlessCheck : 컨벤션을 지키고 있는지 검사
    • ./gradlew spotlessApply : 파일에 코드 컨밴션을 적용

4. build.gradle 전체 코드

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.2'
    id 'io.spring.dependency-management' version '1.1.2'
    id 'com.diffplug.spotless' version '6.23.3' // Spotless 플러그인
}

group = 'briefing.info'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '17'
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    // ...여러 의존성들
}

def querydslSrcDir = 'src/main/generated'

clean {
    delete file(querydslSrcDir)
}

tasks.withType(JavaCompile) {
    options.generatedSourceOutputDirectory = file(querydslSrcDir)
}

tasks.named('test') {
    useJUnitPlatform()
}

/*
    compileJava 태스크가 실행되기 전에 spotlessApply 태스크가 먼저 실행되도록 구성
    개발자가 별도로 코드 포맷팅을 신경 쓸 필요 없이, 코드가 항상 일관된 스타일을 유지하도록 설정
 */
tasks.named('compileJava') {
    dependsOn 'spotlessApply'
}

jar {
    enabled = false
}

spotless {
    java {
        // Google Java 포맷 적용
        /*
            googleJavaFormat() : 탭은 2개의 공백
            googleJavaFormat().aosp() : 탭은 4개의 공백
            [참고] https://github.com/google/google-java-format/issues/525
         */
        googleJavaFormat().aosp()
        // 아래 순서로 import문 정렬
        importOrder('java', 'javax', 'jakarta', 'org', 'com')
        // 사용하지 않는 import 제거
        removeUnusedImports()
        // 각 라인 끝에 있는 공백을 제거
        trimTrailingWhitespace()
        // 파일 끝에 새로운 라인 추가
        endWithNewline()
    }
}

📚 마무리

컴파일 전에 자동으로 코드 포맷팅을 수행하게끔 설정해두니 편리합니다. 회사에서 Typescript를 사용할 때는 아래 코드처럼 pre-commit 훅을 설정하여 커밋하기 전에 eslintprettier 실행시켰었는데 포맷팅을 조금 더 강제할 필요가 있어지면 Briefing에도 적용해봐야겠습니다!

"lint-staged": {
    "**/*.{ts,tsx}": [
      "eslint . --fix",
      "prettier --write ."
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
profile
https://dev-peter.online/

0개의 댓글