SonarQube란?
SonarQube는 클린 코드를 구현하기 위한 정적 코드 분석 도구이다.
🤔 정적 코드 분석 vs 동적 코드 분석
정적 코드 분석은 코드가 실행되기 전 소스 코드 또는 바이너리 코드를 분석해 코드를 직접 실행하지 않고 코드의 구조, 문법, 스타일, 잠재적인 버그, 코드 복잡도, 보안 취약점 등을 분석한다. 정적 코드 분석은 코드 실행 없이도 오류를 조기에 발견할 수 있는 장점이 있으나, 코드의 실제 실행 환경에서 발생하는 런타임 오류나 메모리 누수와 같은 동적인 문제는 감지할 수 없다는 단점이 있다.
동적 코드 분석은 코드를 실제로 실행하는 동안 수행되는데, 프로그램을 실행하면서 그 동작을 모니터링하고, 런타임에서 발생할 수 있는 메모리 누수, 성능 문제, 예외 처리, 보안 문제 등을 분석한다.
SonarQube 설치
SonarQube에서 community 버전을 다운로드한 후 터미널을 통해 sonar 스크립트를 실행한다.
# SonarQube 서버 실행 파일이 있는 디렉토리로 이동
% cd Downloads/sonarqube-10.6.0.92116/bin/macosx-universal-64
# sonar.sh 스크립트 실행
% ./sonar.sh start
그 후 localhost:9000 로 접속해 아이디와 패스워드에 admin을 입력하여 로그인한다.
📐 로컬 레포지토리를 측정하고 싶은 경우
Create a local project를 선택해 프로젝트 정보를 입력한 후 아래 페이지에서 Locally를 선택한다.
토큰 이름을 설정하고 Generate 버튼을 눌러 생성된 토큰을 저장해 놓는다.
만약 토큰을 잊었으면 Administration > Security > User > Tokens에서 토큰을 새로 발급해 준다.
IntelliJ의 Settings > Tools > SonarLint에 + 버튼을 누른 후 이름과 소나큐브 URL(http://localhost:9000)을 입력한 후 다음 창에서 소나큐브 토큰을 넣어준다.
루트 build.gradle에 SonarQube 의존성을 추가해 준다.
Gradle에서 사용할 수 있는 소나큐브의 최신 버전은 Gradle 플러그인 포털에서 확인할 수 있다.
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id "org.sonarqube" version "5.0.0.4638" # 추가
}
allprojects {
...
}
subprojects {
apply plugin: 'java'
# 추가
apply plugin: 'org.sonarqube'
# (설정 1)
sonar {
properties {
property 'sonar.java.binaries', "${buildDir}/classes"
}
}
}
# 추가 (설정 2)
sonar {
properties {
property 'sonar.host.url', 'http://localhost:9000'
property 'sonar.token', System.getenv('SONAR_TOKEN')
property 'sonar.sources', 'src'
property 'sonar.language', 'java'
property 'sonar.sourceEncoding', 'UTF-8'
property 'sonar.test.inclusions', '**/*Test.java'
property 'sonar.exclusions', '**/Q*.java, **/config/**, **/common/**, **/importer/**, ' +
'**/*Application*.java, **/*Dto*.java, **/*Exception*.java, **/*ErrorCode*.java'
property 'sonar.java.coveragePlugin', 'jacoco'
property 'sonar.coverage.jacoco.xmlReportPaths', "${project.rootDir}/support/jacoco/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml"
}
}
🫧 설정 1
subprojects 블록 내부에 있는 sonar 설정은 각 서브 프로젝트에 공통적으로 적용되는 설정이다. 멀티 프로젝트에서 각 서브 프로젝트의 buildDir 경로가 다를 수 있어 subprojects 블록 내부에 선언하여 각 서브 프로젝트가 올바르게 경로를 참조하도록 설정한다.
- sonar.java.binaries 속성은 소나큐브가 코드 품질 및 커버리지 분석에 필요한 바이트코드 파일(.class 파일)을 찾기 위해 사용하는 경로를 지정한다.
🫧 설정 2
루트 프로젝트(subprojects 외부)에 있는 sonar 설정은 모든 서브 프로젝트와 루트 프로젝트 자체에 적용되는 전역 설정을 정의한다. 이 설정에는 소나큐브 서버의 URL, 인증 토큰, 스캔할 소스 경로와 규칙들이 포함된다. 자세한 정보는 SonarScanner for Gradle 문서에서 확인할 수 있다.
- sonar.token 속성에는 소나큐브에서 발급받은 토큰 값을 넣어야하기 때문에 터미널에 아래 명령어를 입력하여 토큰을 환경 변수에 저장한다.
# 환경 변수 설정
% export SONAR_TOKEN=토큰값
# 환경 변수 적용 여부 확인
% echo $SONAR_TOKEN
- sonar.coverage.jacoco.xmlReportPaths 속성은 JaCoCo의 XML 파일 경로를 명시한다. JaCoCo의 XML 보고서가 여러 개의 파일로 생성되는 경우(멀티 모듈인 경우), jacoco-aggregation을 통해 하나의 파일로 합쳐 경로를 지정하거나, 각 JaCoCo XML 파일의 경로를 설정할 수 있다.
subprojects {
apply plugin: 'org.sonarqube'
sonar {
properties {
property 'sonar.java.binaries', "${buildDir}/classes"
# jacoco-aggregation을 사용하지 않은 경우 설정 1에서 각 프로젝트의 buildDir마다 따로 적용
property 'sonar.coverage.jacoco.xmlReportPaths', "${buildDir}/reports/jacoco.xml"
}
}
}
소나큐브 태스크는 두 가지 방법으로 실행할 수 있다.
- 터미널 ./gradlew test sonar (권한이 없는 경우 chmod +x gradlew 입력)
- IntelliJ Gradle > verification > sonar(혹은 sonarqube)
📐 GitHub Actions를 통해 프로젝트를 측정하고 싶은 경우
'Back-end' 카테고리의 다른 글
[JPA] N+1 문제 해결 방법 (0) | 2024.08.27 |
---|---|
[Spring] 정적 코드 분석을 위해 SonarCloud 사용하기 (0) | 2024.08.21 |
[Spring Boot] 로컬 환경에서 Github Actions 테스트하기 (0) | 2024.08.16 |
[JUnit] 테스트 코드에 Test Fixture 사용하기: 테스트 데이터 재사용 (0) | 2024.08.05 |
[Gradle] build.gradle 플러그인 분리하기 (0) | 2024.07.25 |