개요
프로젝트를 시작하기 전 가장 중요한 점이 있는데 바로 일관적인 코드가 유지될 수 있도록 하는것이다. 이는 코드 관점에서는 아키텍처와 규칙이 될 수 있겠고 컨벤션 관점에서는 포맷팅이 있을 것 같다. 사람이 코드 포맷팅을 직접 지키면서 작업하기는 힘들기 때문에 일반적으로 플러그인 등의 기능을 이용하여 모든 코드에 일관성을 지키는데 이를 도와주는 것이 바로 Spotless이다. Spotless를 사용하면 현재의 코드가 정해진 규약을 충족하는지 체크할 수 있고 충족하지 않는다면 자동으로 코드를 변경해주는 기능 또한 제공한다.
또한 모든 코드는 테스트 코드가 필수적으로 들어가는데, 사람이 직접 엣지 케이스를 찾아내는건 쉽지 않은 일이다. 이때 코드 커버리지를 측정하는 방법을 도입할 수 있는데 이는 실제로 굉장히 많은 도움이 된다. 자바 진영에서는 이런 코드 커버리지 측정을 위해 Jacoco를 사용한다. 해당 플러그인은 현재 코드에 대한 테스트 커버리지를 측정하여 리포트로 제공해주기 때문에 개발자가 손쉽게 확인할 수 있다. 물론, 코드 커버리지에 의존하기보단 직접 엣지 케이스를 도출하는 능력을 기르는게 우선적으로 선행되어야할 것이다.
본 포스팅에서는 Spotless와 Jacoco에 대한 설정 방법에 대해 간단하게 다뤄보겠다.
Spotless
plugins {
id("com.diffplug.spotless") version "6.20.0"
}
먼저 build.gradle.kts 파일을 열고 spotless를 플러그인으로 추가한다.
spotless {
java {
trimTrailingWhitespace()
indentWithTabs()
indentWithSpaces(4)
endWithNewline()
googleJavaFormat("1.10.0").aosp().reflowLongStrings()
formatAnnotations()
removeUnusedImports()
importOrder(
"java",
"jakarta",
"lombok",
"org.springframework",
"",
"\\#",
"org.junit",
"\\#org.junit",
"com.teamhide",
"\\com.teamhide"
)
}
}
다음으로 위 코드를 추가해준다. 각 항목별로 어떠한 작업을 하는건지는 네이밍만 봐도 유추할 수 있을 것이다.
./gradlew spotlessCheck
이제 위 명령어를 통해 현재 코드가 정의한 컨벤션을 지키고 있는지 검사할 수 있다. 최초로 프로젝트를 생성하고 위 명령어를 실행하면,
Run './gradlew :spotlessApply' to fix these violations.
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
BUILD FAILED in 760ms
위처럼 실패하는모습을 볼 수 있고 그 위쪽으로 컨벤션에 어긋난 코드 목록을 보여준다.
./gradlew spotlessApply
이때 위 명령어를 실행하면 정의한 컨벤션을 적용할 수 있다.
Jacoco
plugins {
id("jacoco")
}
플러그인에 jacoco를 추가해준다.
tasks.jacocoTestReport {
reports {
html.required.set(true)
xml.required.set(false)
csv.required.set(false)
}
}
테스트 리포트 관련 설정을 진행한다. 나는 HTML파일로만 제공받고싶기 때문에 해당 부분만 true처리해줬다.
tasks.jacocoTestCoverageVerification {
violationRules {
rule {
enabled = true
element = "CLASS"
limit {
counter = "LINE"
value = "COVEREDRATIO"
minimum = "1.00".toBigDecimal()
}
}
}
}
다음으로 테스트 조건에 대한 룰을 명시해준다. 위에 보면 minimum에 100% 모든 부분이 테스트되어야한다고 명시해줬다. 그리고 element에 CLASS를 줌으로써 클래스 단위로 커버리지를 측정하도록 해줬고, counter에 LINE을 줌으로써 빈 줄을 제외한 실제 코드의 라인 수를 기준으로 코드 커버리지 지표를 측정하도록 해주었다.
이제 오른쪽 Gradle탭에서 Tasks - verification쪽을 보면 위에서 설정한 2개의 태스크가 있음을 확인할 수 있다. jacocoTestConverageVerification은 내가 원하는(위에서 설정한 minimum) 커버리지 기준을 충족하는지 검사한다. 그리고 jacocoTestReport는 커버리지에 대한 리포트를 만들어준다.
./gradlew test를 통해 테스트 코드를 실행해보면 build/reports/jacoco/index.html 파일이 생성되고 해당 파일을 통해 커버리지 리포트를 확인할 수 있게 된다.
ETC
lombok.config
config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true
lombok.setter.flagUsage = error
lombok.allArgsConstructor.flagUsage = error
루트 디렉토리에 lombok.config파일을 만들고 위와 같은 내용을 추가한다. 각 라인별로 설명하자면,
- 롬복이 생성한 코드를 상위 클래스에 전파하지 않도록 하는 옵션이다. 예를 들어 @Getter 어노테이션을 사용하여 클래스의 필드에 게터 메소드를 생성하려하면, 롬복은 해당 게터 메소드를 하위 클래슬 뿐만 아니라 상위 클래스에도 생성하려고 시도한다. 이 속성을 꺼줌으로써 클래스간 상속할 때 롬복 코드가 덮어쓰이지 않도록 한다.
- 롬복으로 인해 생성된 코드에 자동으로 @Generated를 붙여주도록 한다. 이렇게 함으로써 롬복에 의해 생성되었음을 알리고, Jacoco가 테스트 커버리지를 측정할 때 롬복에 의해 생성된 메소드는 테스트 대상에서 제외시키게 된다.
- 무분별한 setter를 막기 위해 설정한다.
- 무분별한 전체 인자 생성자를 막기 위해 설정한다.
logback-spring.xml
일반적으로 Slf4j 구현체로 logback을 많이 사용할텐데, 관련해서 로그 설정을 해주는것이 좋다. src/main/resources 하위에 logback-spring.xml 파일을 생성하고 내용을 채워넣는다.
<configuration>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %green(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
<appender name="logstash" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<timeZone>UTC</timeZone>
</encoder>
</appender>
<springProfile name="default | test">
<root>
<appender-ref ref="stdout" />
</root>
</springProfile>
<springProfile name="prod">
<appender-ref ref="logstash" />
</springProfile>
</configuration>
default 또는 test 프로필로 설정했을 때 stdout으로 정의한 형태로 로그를 출력하고 prod인 경우 logstash로 설정한 로그로 출력하는 설정이다.
'Coding > Java Spring' 카테고리의 다른 글
Reactive Streams 개념 정리 (0) | 2023.08.23 |
---|---|
스프링 테스트 코드를 위한 어노테이션 (0) | 2023.08.22 |
DDD 이벤트 스토밍 - 크림 클론 프로젝트 (0) | 2023.08.18 |
Webflux Function Endpoints 정리 (0) | 2023.08.17 |
Spring Camp 2023 - 실무에서 적용하는 테스트 코드 작성 방법과 노하우 (0) | 2023.08.05 |