정적 코드 분석
정적 코드 분석은 소스 코드에서 수행되는 일련의 자동 검사로 구성됩니다.
정적 분석 도구는 코드를 검사하여 메모리 누수 또는 버퍼 오버플로우 등 알려진 오류 및 취약점을 파악합니다.
또한 정적 분석을 활용하면 코딩 표준 적용이 가능합니다.
정적 분석은 소스 코드에서 실행되기 때문에 프로그램을 실행할 필요가 없으므로 CI/CD 파이프라인의 첫 단계에서 수행하거나 변경 사항 커밋 전 IDE에서 직접 수행하는 경우가 많습니다.
하지만 정적 분석은 프로그래밍 된 규칙 위반이 발생한 사례만을 식별하며, 소스를 읽는 것만으로는 모든 결함을 발견할 수는 없습니다.
그렇기 때문에 테스트 코드와 같은 동적 분석이 가능한 방법과 같이 사용하는 것이 좋습니다.
SonarQube란?
SonarQube는 정적 코드 분석 도구 중에 하나로 버그, 코드 스멜, 보안 취약점을 발견해주는 것을 목적으로 사용되는 오픈소스 플랫폼입니다.
SonarQube는 SonarSource가 개발하였으며 중복코드, 코드 표준, 보안, 테스트 커버리지, 중복에 대한 보고서를 제공합니다.
SonarQube의 서비스를 제공하는 클라우드 환경의 SonarCloud도 존재합니다.
SonarCloud 같은 경우 레포지터리만 연동하면 바로 사용할 수 있기 때문에 간편하게 사용할 수 있습니다.
SonarCloud를 이용한 코드 정적 분석
SonarCloud에 레포지터리를 연동하여 코드 정적 분석 기능을 사용해봅시다.
다음과 같은 순서로 진행합니다.
- https://sonarcloud.io 로 이동한 후 원하는 깃 호스팅 서비스로 로그인합니다.
- 계정 로그인을 완료하면 다음과 같은 화면이 나오는데 Import an organization from Github를 눌러 원하는 레포지터리를 선택합니다.

- SonarQube로 정적 코드 분석을 할 Organization을 선택합니다.

- 그 다음에 원하는 레포지터리를 지정하고 요청을 보냅니다.

- 비밀번호를 입력합니다.
- sonar cloud organization key를 확인하고(수정 가능) 다음으로 이동합니다.

- 원하는 플랜을 선택합니다.

- analyze new project로 정적 분석을 시작할 프로젝트를 지정합니다.


- set up을 누르면 다음과 같이 해당 레포지터리에 소나 클라우드를 연동시킵니다.

Github actions를 이용한 코드 정적 분석 기능 자동화
sonar cloud는 따로 설정하지 않아도 PR에 코드 정적 분석 보고서를 제공하지만 저의 경우 jacoco와의 연동을 위해 github actions 환경에서 돌려서 jacoco 결과를 받을 수 있도록 구성했습니다. (더 좋은 방법이 있다면 알려주세요)
- 생성된 sonar cloud 화면에서 좌측 하단에 설정 → Analysis Method로 이동합니다.
여기서 github actions를 통해 github actions이 돌아갈때 정적 분석을 하기 위해 Github actions → Follow the tutorial을 선택합니다.

- 이동하면 다음과 같이 깃허브 시크릿 등록을 하라는 창을 볼 수 있습니다. 2번에 SONAR_TOKEN에 대한 값이 나오며 이를 복사합니다.

- Settings > Secrets에 걸린 하이퍼링크를 선택하면 다음과 같이 github secret 등록 페이지가 나옵니다.
New repository secret으로 새로운 시크릿을 등록합시다.

- 다음과 같이 이름은 SONAR_TOKEN으로 하고 값은 2번에서 복사한 토큰으로 설정해주세요

- gradle 기준으로 build.gradle에 sonarqube plugin을 추가합니다.
plugins { ... id 'org.sonarqube' version "3.4.0.2513" ... }
- sonarqube 작업에 대한 설정을 다음과 같이 넣어줍니다.
sonarqube { properties { property "sonar.projectKey", "Rchicken_booktudy" property "sonar.organization", "rchicken" property "sonar.host.url", "https://sonarcloud.io" // jacoco를 이용한 코드 커버리지 체크시 추가 property "sonar.coverage.jacoco.xmlReportPaths", "${buildDir}/reports/jacoco/test/jacocoTestReport.xml" } }
- github actions 파일을 다음과 같이 설정합니다. (캐시 관련 설정은 빌드 캐시를 통해 빌드를 빠르게 하기 위해서이지 필수적 요소는 아닙니다.)
name: develop branch ci on: pull_request: branches: - "develop" jobs: build: runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up JDK 17 uses: actions/setup-java@v3 with: distribution: temurin java-version: 17 - name: Cache Gradle packages uses: actions/cache@v3 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: ${{ runner.os }}-gradle - name: Cache SonarCloud packages uses: actions/cache@v3 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Execute Gradle build and analyze run: ./gradlew build sonarqube env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- 이제 돌려보면 다음과 같이 github action이 돌아갈때마다 코드 정적 분석이 되는 것을 볼 수 있습니다.

⚠️ 겪었던 문제
Q. commit을 했는 데 계속해서 No Coverage information 가 나오는 현상

A. 해당 문제의 경우 올린 커밋에 코드 변경 사항이 없을 경우 (production code) 해당 메시지가 나오며 정상적으로 연동되었다면 코드 변경사항이 발생한다면 해당 변경된 코드가 몇 % 커버리지 되었는지 나오게 됩니다.
연동 여부의 확인은 gradle의 경우
./gradlew build sonarqube --info
와 같이 디버깅하여 정보를 확인할 수 있습니다.이런식으로 파일이 존재하는지 확인해야 합니다.

만약 파일이 존재하지 않는다면 테스트 결과가 담긴 xml 파일이 생성되었는지 빌드 순서를 확인해봐야 합니다.
jacoco의 경우
jacocoTestReport
작업이 정상적으로 실행된 후 sonarqube가 작동하는지 확인해야 합니다.