Java 개발자를 위한 Maven + SonarQube + Docker로 시작하는 코드 정적 분석
켄트 벡Kent Beck은 자신의 책 익스트림 프로그래밍Extreme Programming에서 5 가치[1] 를 이야기 했는데 그중 하나가 피드백Feedback이다.
한번에 완벽하게 해결하기를 바라는 것보다 점진적 개선에 만족하기 때문에 우리는 피드백을 이용해 목표에 점점 더 가까이 다가간다. 피드백은 여러 가지 형식으로 우리에게 들어온다. - 익스트림 프로그래밍 47 쪽
더 나은 코드를 만들기 위해서는 피드백이 필수이다. 어떻게 하면 효과적인 피드백을 받을 수 있을까?
필자는 코드 정적 분석 도구의 사용이 효과적인 피드백 중 하나라고 생각한다.
정적 분석 도구는 코드를 분석하여 여러 가지로 지적(?)을 한다. 개발자는 정적 분석 도구로부터의 피드백을 통해 자신의 코드를 뒤돌아 볼수 있는 계기를 가질 수 있으며 더 나아가 개선까지 이어질 수 있다.
정적 분석 도구의 종류는 프로그래밍 언어만큼이나 많다.[2] 이 글은 그중에서도 SonarQube를 소개한다.
SonarQube
예전에는 Sonar라고 했지만 지금은 SonarQube로 이름을 바꾸었다.[3]
SonarSouce에서 만든 SonarQube는 코드를 분석하여 중복, 테스트 커버리지, 코드 복잡도, 버그, 보안 취약성 등을 리포팅 해주며, IDE(Eclipse, Visual Studio, IntelliJ IDEA), 빌드 도구(Maven, Ant, Gradle, MSBuild), CIContinuous Integration 도구(Atlassian Bamboo, Jenkins, Hudson)와 통합하여 사용할 수 있다. 이에 더해 단일 프로그래밍 언어만 분석 가능한 것이 아니라 다양한 프로그래밍 언어로 만든 코드를 분석할 수 있다.[4]
자세한 SonarQube 리포팅 결과는 아래 체험 사이트에서 확인할 수 있다.
Docker로 SonarQube 서버 설치 하기
Docker 개념이 생소하다면 김형준님의 글(개발자가 처음 Docker 접할때 오는 멘붕 몇가지)을 읽어 보기를 권한다.
Docker가 설치되어 있지 않다면 아래 URL에서 다운로드해 설치한다.
SonarQube는 Docker 이미지를 제공한다. Docker 이미지를 다운로드하여 SonarQube 서버를 시작해 보자.
1 2 3 4
// SonarQube Docker 이미지 다운로드 $ docker pull sonarqube // SonarQube 서버 시작 $ docker run -d --name sonarqube -p 9000:9000 -p 9092:9092 sonarqube
정상적으로 SonarQube 서버가 시작되었다면 http://localhost:9000/에 접속해 보면 아래와 같은 화면이 나타난다.
Java Maven 프로젝트를 SonarQube 정적 분석하기
이 글에서는 Java 언어(1.8)로 만든 코드를 분석하며, 빌드 도구로는 Maven을 사용한다.
먼저 분석할 Java 코드를 준비해 보자.
필자의 GitHub에 올라가 있는 Spring Boot 프로젝트(Building an Application with Spring Boot) 체크아웃 받는다.(참고로 Spring Boot를 몰라도 된다. 이 글에서는 정적 분석 예제 코드로만 쓸 뿐이다)
이제 Maven으로 SonarQube로 정적 분석을 실행해 보자.
Maven이 설치되어 있지 않다면 아래 URL을 참고하여 설치한다.
Maven의 settings.xml 파일에 SonarQube 서버 설정을 추가한다.
참고로 settings.xml 파일 위치는 2개다. 둘 중 하나에 추가하면 된다.(해당 디렉토리에 settings.xml 파일이 없다면 새로 만들면 된다.)
- Maven 설치 디렉토리 : ${maven.home}/conf/settings.xml
- 사용자 홈 디렉토리 : ${user.home}/.m2/settings.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd"> <pluginGroups> <pluginGroup>org.sonarsource.scanner.maven</pluginGroup> </pluginGroups> <profiles> <profile> <id>sonar</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <!-- Optional URL to server. Default value is http://localhost:9000 --> <sonar.host.url> http://localhost:9000 </sonar.host.url> </properties> </profile> </profiles> </settings>
체크아웃 받은 프로젝트 디렉토리(pom.xml 이 존재하는 디렉토리)에서 Maven Goal을 실행한다.
1
mvn sonar:sonar
오류 없이 실행되었다면 SonarQube 서버(http://localhost:9000)에서 예제 프로젝트(gs-spring-boot)가 분석된 것을 확인할 수 있다.
IntelliJ와 SonarQube 서버 통합
SonarSouce는 SonarQube 서버와 IDE와 통합해서 사용할 수 있는 SonarLint를 IDEIntegrated Development Environment의 플러그인Plugin 형태로 제공한다.
SonarLint를 사용하면 IDE에서 정적 분석을 실행할 수 있고 코드 편집창에서 정적 분석 결과 확인할 수 있어 편하다.
IDE 중 하나인 IntelliJ에 SonarLint를 설치해 보고, SonarQube 서버와 통합해 보자.
SonarLint 설치
1 Preferences 창을 연다
2 SonarLint Plugin을 인스톨한다(Plugins | Browse repositories.. | SonarLint)
SonarLint와 SonarQube 서버 연결
1 SonarLint 창을 연다(View|Tools Windows|SonarLint)
2 SonarQube서버와 연결한다
SonarLint로 정적 분석 실행
컨텍스트 메뉴에서 Analyze|Analyze All File with SonarLint 선택하면 전체 파일을 분석한다.
분석 결과는 SonarLint 창에서 확인할 수 있다.
Maven 멀티 모듈로 프로젝트가 구성되어 있다면
Maven 멀티 모듈일 경우 테스트 커버리지가 측정되지 않는 경우가 있다. 이 경우에는 아래와 같이 설정해 주면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>ymyoo</groupId> <artifactId>article-module-root</artifactId> <version>0.0.1-SNAPSHOT</version> <modules> <module>...</module> <module>...</module> <module>...</module> </modules> <packaging>pom</packaging> <properties> <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin> <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis> <sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath> <sonar.language>java</sonar.language> </properties> <build> <plugins> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <configuration> <destFile>${sonar.jacoco.reportPath}</destFile> <append>true</append> </configuration> <executions> <execution> <id>agent</id> <goals> <goal>prepare-agent</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
주석
[1] 5 개 가치(Value)는 단순성(Simplicity), 의사소통(Communication), 피드백(Feedback), 존중(Respect), 용기(Courage)이다.
[2] https://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis
[3] 일반적으로 Sonar 라고 하면 음향탐지장비로 알려져 있다.(https://ko.wikipedia.org/wiki/소나)
[4] https://en.wikipedia.org/wiki/SonarQube