우리는 프로젝트
를 진행하면서 적게는 수 십줄 많게는 수 백줄의 코드
를 작성합니다.
적절한 단위 테스트
와, 통합 테스트 작성
으로 많은 버그를 잡아내고 문제를 해결하기도 하지만 그것만으로 부족할 때가 있습니다.
보안 취약점
이나, 현재 작성된 코드로 인해 향후 일어날 수 있는 문제들을 전부 런타임
에 체크
하기는 한계
가 있기 때문입니다.
코드
에서 냄새
가 나고, 취약점
이 발생한 걸 잡는다고 하고 서론과 제목에서 수 많은 어그로
를 끈 이유가 당연히 있습니다.
이런걸 해결해 주는 도구
가 없다면 이런 글을 쓰지도 않았을테니까요.
개발자
가 작성한 코드 품질을 책임져주는 개발자의 좋은 친구를 오늘 게시글
에서 소개하고자 합니다!
바로 SonarQube
입니다!
SonarQube
는 20개 이상의 프로그래밍 언어에서 버그, 코드 스멜, 보안 취약점을 발견할 목적으로 정적 코드 분석을 수행합니다.
그렇다면 SonarQube
의 특징을 알아보겠습니다.
보안 취약점
의 보고서를 제공합니다.Maven
, Ant
, Gradle
과 같은 빌드 도구들과 CI 도구들과의 연동도 제공하고 있습니다.20
개 이상의 프로그래밍 언어
를 지원하고 있습니다.동적 분석과 정적 분석은 분명 둘 다 필요한 일입니다. 그렇다면 동적분석
과 정적분석
어떤 차이가 있을까요?
동적 분석(Dynamic Analysis)
테스트 코드
를 실행하여 현재 코드가 테스트
를 모두 통과하는지 확인할 수 있습니다.동적 분석
만으로는 코드의 모든 문제를 발견할 수 없다는 아쉬운 점이 있습니다.동적 분석 만으로는 효율이 떨어지는
코드나, 보안 취약점이 있는
코드 또는 언어의 특성에 맞지 않는 스타일로 작성된 코드를 잡아내기는 굉장히 어렵습니다.
정적 분석(Static Analysis)
소스 코드
의 실행 없이 정적
으로 프로그램의 문제를 찾는 과정을 의미합니다.정적 분석
은 런타임에 어떤 문제가 생길지는 알 수 없기 때문에 이 부분이 아쉬운 점입니다.결론은 두 가지 방법
을 전부 사용해서 아쉬운 부분을 메꾸는 것이 핵심입니다.
정적 분석 vs 동적 분석 관계에서 어떤 것이 더 좋은 방법인지 찾는 것이 아니라, 정적 분석 + 동적 분석으로 최소한의 코드 품질을 유지할 수 있는 것입니다.
정적 분석
은 Code-Smell
이라고 불리는 코드의 문제와 보안 취약점 등의 문제를 확인할 수 있는데요.
SonarQube
는 여러가지 문제를 잡아주고, 개선해야 할 방안을 제시합니다. 참 고마운 친구죠?
그렇다면 여기서 말하는 Code-Smell
은 무엇일까요?
SonarQube
가 꽤 많은 부분을 알아서 탐지하고 코드 품질
을 올리는데 도움을 준다는 것을 알 수 있습니다.
SonarQube
는 공식 사이트에서 다운 받아 직접 설치하는 방법과, Docker-Compose
를 이용하는 방법이 있습니다.
Docker-Compose
를 이용해 간단히 설치 후 실습할 수 있도록 후자를 선택하겠습니다.
version: "3"
services:
sonarqube:
image: sonarqube:9.9.1-community
hostname: sonarqube
container_name: sonarqube
depends_on:
- db
environment:
SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
SONAR_JDBC_USERNAME: sonar
SONAR_JDBC_PASSWORD: sonar
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_logs:/opt/sonarqube/logs
ports:
- "9000:9000"
db:
image: postgres:13
hostname: postgresql
container_name: postgresql
environment:
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar
POSTGRES_DB: sonar
volumes:
- postgresql:/var/lib/postgresql
- postgresql_data:/var/lib/postgresql/data
volumes:
sonarqube_data:
sonarqube_extensions:
sonarqube_logs:
postgresql:
postgresql_data:
SonarQube
와 PostgreSQL
을 docker-compose를 이용해 한 번에 실행하겠습니다.
docker compose -f sonar.yml up -d
위의 명령어를 실행하면, PostgreSQL
과 SonarQube
가 잘 띄워진 것을 확인할 수 있습니다.
SonarQube
는 처음 접근하면 아이디와 비밀번호가 모두 admin
입니다.
먼저 로그인을 해주겠습니다.
로그인 후 프로젝트
에서 사용하기 위해 토큰
을 만들어 주겠습니다.
Administration
탭으로 이동합니다.Security
> Users
탭으로 이동합니다.Tokens
탭을 클릭합니다.Token
의 이름과 유효기간을 설정하고 Generate
버튼을 눌러줍니다.Token
은 Copy
버튼을 눌러 잘 복사해 둡니다.저는 Java
+ Spring Boot
+ Gradle
조합으로 프로젝트를 진행하기 때문에, Spring Boot 3.0 기준으로 설명드리겠습니다.
build.gradle
에 두 가지 내용을 추가합니다.Gradle Project
를 전체 Reloading
해줍니다.Gradle
> Tasks
> verification
> sonar
를 실행합니다.sonar task
가 완료되면 SonarQube
에 접속해서 그 결과를 확인할 수 있습니다.샘플 프로젝트에서는 2건의 버그
와 3건의 보안 취약점
그리고 4건의 Code-Smell
이 감지되었습니다.
이 중 한 가지
정도만 살펴보겠습니다.
Bug
탭에서 검출된 문제로 그 이유는 아래와 같습니다.
Random
객체를 생성
하고 저장
해서 재사용
해야 하는데, 매번 생성하는 코드가 작성되어 있어서 문제로 검출된 것입니다.SonarQube
는 문제를 검출하고, 어떻게 개선
해야 하는지 친절히 알려주는게 장점입니다.
그렇다면 SonarQube
가 준 가이드대로 코드
를 수정해보겠습니다.
Random 객체
를 재사용하도록 코드를 변경했습니다.
다시 sonar task
를 실행해보겠습니다.
Bugs
탭에는 0건
이 표시되지만, 새로운 보안 취약점이 생겨서 Quality Gate
를 통과하지 못했습니다.
왜 이런 문제
가 생겼을까요?
Random
클래스는 난수처럼 보이는 의사 난수
를 생성하기 때문에, 규칙을 알면 어떤 값이 생성될 지 알 수 있기 때문에 보안
에 취약하다는 것입니다.
의사 난수에 대한 내용은 정리가 잘 된 블로그를 참고하시면 좋겠습니다.
진짜 임의의 난수
를 생성하는 SecureRandom 클래스
를 사용하면 이 문제를 해결할 수 있습니다. 코드를 변경해 보겠습니다.
코드를 수정하고 sonar task
를 다시 수행해보겠습니다.
모든 문제가 해결되어 Quality Gate
를 통과한 것을 볼 수 있습니다.
코드를 Push
하고, 정적 분석
이 이루어질때까지 코드의 문제점
을 알 수 없다면 매번 코드를 수정해 다시 올려야하기 때문에 생산성
이 떨어지게됩니다.
이런 문제를 해결하기 위해서 사용할 수 있는 것은 SonarLint
입니다!
대부분의 IDE
에서 SonarLint
를 제공하고 있고, IntelliJ
기준으로 설명드리겠습니다.
Marketplace
에서 SonarLint
플러그인을 설치합니다.설치를 했는데도 SonarLint Window
가 보이지 않는 경우 아래의 사진대로 따라하시면 됩니다.
View
> Tool Windows
> SonarLint
를 클릭하면 하단에 노출되는 것을 확인할 수 있습니다.SonarLint
를 설치 후 활성화 한뒤, 코드 작성
을 하면 코드를 Push 하기 전에 문제를 감지할 수 있습니다.이렇게 함으로써 Local 환경
에서 SonarLint Plugin
을 통해 일차적으로 코드의 문제를 해결하면, SonarQube Server
에서 더 적은 코드의 문제점이 검출되어 생산성
이 올라갈 것입니다.
내 코드에 뿌리는 페브리즈 같은 존재, SonarLint