내가 짠 코드에서 썩은내가 난다고?

DevSeoRex·2024년 2월 2일
22
post-thumbnail

우리는 프로젝트를 진행하면서 적게는 수 십줄 많게는 수 백줄의 코드를 작성합니다.
적절한 단위 테스트와, 통합 테스트 작성으로 많은 버그를 잡아내고 문제를 해결하기도 하지만 그것만으로 부족할 때가 있습니다.

보안 취약점이나, 현재 작성된 코드로 인해 향후 일어날 수 있는 문제들을 전부 런타임체크하기는 한계가 있기 때문입니다.

😎 그러면 어떻게 취약점을 잡을것인가?

코드에서 냄새가 나고, 취약점이 발생한 걸 잡는다고 하고 서론과 제목에서 수 많은 어그로를 끈 이유가 당연히 있습니다.
이런걸 해결해 주는 도구가 없다면 이런 글을 쓰지도 않았을테니까요.

개발자가 작성한 코드 품질을 책임져주는 개발자의 좋은 친구를 오늘 게시글에서 소개하고자 합니다!

바로 SonarQube 입니다!
SonarQube는 20개 이상의 프로그래밍 언어에서 버그, 코드 스멜, 보안 취약점을 발견할 목적으로 정적 코드 분석을 수행합니다.

그렇다면 SonarQube의 특징을 알아보겠습니다.

  • 중복 코드, 코딩 표준, 유닛 테스트, 코드 커버리지, 코드 복잡도, 주석, 버그 및 보안 취약점의 보고서를 제공합니다.
  • Maven, Ant, Gradle과 같은 빌드 도구들과 CI 도구들과의 연동도 제공하고 있습니다.
  • Java, C#, C, C++, Kotlin, JavaScript 등 약 20개 이상의 프로그래밍 언어를 지원하고 있습니다.

🙃 동적 분석 vs 정적 분석

동적 분석과 정적 분석은 분명 둘 다 필요한 일입니다. 그렇다면 동적분석정적분석 어떤 차이가 있을까요?

동적 분석(Dynamic Analysis)

  • 테스트 코드를 실행하여 현재 코드가 테스트를 모두 통과하는지 확인할 수 있습니다.
  • 동적 분석만으로는 코드의 모든 문제를 발견할 수 없다는 아쉬운 점이 있습니다.

동적 분석 만으로는 효율이 떨어지는 코드나, 보안 취약점이 있는 코드 또는 언어의 특성에 맞지 않는 스타일로 작성된 코드를 잡아내기는 굉장히 어렵습니다.

정적 분석(Static Analysis)

  • 소스 코드의 실행 없이 정적으로 프로그램의 문제를 찾는 과정을 의미합니다.
  • 정적 분석은 런타임에 어떤 문제가 생길지는 알 수 없기 때문에 이 부분이 아쉬운 점입니다.

결론은 두 가지 방법을 전부 사용해서 아쉬운 부분을 메꾸는 것이 핵심입니다.
정적 분석 vs 동적 분석 관계에서 어떤 것이 더 좋은 방법인지 찾는 것이 아니라, 정적 분석 + 동적 분석으로 최소한의 코드 품질을 유지할 수 있는 것입니다.

😡 정적 분석을 왜 사용해야 할까?

정적 분석Code-Smell 이라고 불리는 코드의 문제와 보안 취약점 등의 문제를 확인할 수 있는데요.
SonarQube는 여러가지 문제를 잡아주고, 개선해야 할 방안을 제시합니다. 참 고마운 친구죠?

그렇다면 여기서 말하는 Code-Smell은 무엇일까요?

  • 잠재적으로 버그가 발생할 수 있는 코드
  • 안티 패턴
  • 코드 스타일(컨벤션) 위반 여부
  • 성능 문제
  • 오타
  • 사용되지 않는 코드(unused import)
  • 잠재적인 보안 취약점

SonarQube가 꽤 많은 부분을 알아서 탐지하고 코드 품질을 올리는데 도움을 준다는 것을 알 수 있습니다.

🫡 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:

SonarQubePostgreSQL을 docker-compose를 이용해 한 번에 실행하겠습니다.

docker compose -f sonar.yml up -d

위의 명령어를 실행하면, PostgreSQLSonarQube가 잘 띄워진 것을 확인할 수 있습니다.

SonarQube는 처음 접근하면 아이디와 비밀번호가 모두 admin 입니다.
먼저 로그인을 해주겠습니다.

로그인 후 프로젝트에서 사용하기 위해 토큰을 만들어 주겠습니다.

  • Administration 탭으로 이동합니다.
  • Security > Users 탭으로 이동합니다.
  • Tokens 탭을 클릭합니다.
  • Token의 이름과 유효기간을 설정하고 Generate 버튼을 눌러줍니다.
  • 생성된 TokenCopy 버튼을 눌러 잘 복사해 둡니다.

😍 SonarQube + Spring Boot 통합하기

저는 Java + Spring Boot + Gradle 조합으로 프로젝트를 진행하기 때문에, Spring Boot 3.0 기준으로 설명드리겠습니다.

  • 기존에 작성된 build.gradle에 두 가지 내용을 추가합니다.
  • Gradle Project 를 전체 Reloading 해줍니다.
  • IntelliJ에서 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를 통과한 것을 볼 수 있습니다.

🤬 SonarLint 활용으로 미리 확인하기!

코드를 Push하고, 정적 분석이 이루어질때까지 코드의 문제점을 알 수 없다면 매번 코드를 수정해 다시 올려야하기 때문에 생산성이 떨어지게됩니다.

이런 문제를 해결하기 위해서 사용할 수 있는 것은 SonarLint 입니다!

대부분의 IDE에서 SonarLint를 제공하고 있고, IntelliJ 기준으로 설명드리겠습니다.

  • Marketplace에서 SonarLint 플러그인을 설치합니다.

설치를 했는데도 SonarLint Window가 보이지 않는 경우 아래의 사진대로 따라하시면 됩니다.

  • View > Tool Windows > SonarLint를 클릭하면 하단에 노출되는 것을 확인할 수 있습니다.
  • SonarLint를 설치 후 활성화 한뒤, 코드 작성을 하면 코드를 Push 하기 전에 문제를 감지할 수 있습니다.

이렇게 함으로써 Local 환경에서 SonarLint Plugin을 통해 일차적으로 코드의 문제를 해결하면, SonarQube Server에서 더 적은 코드의 문제점이 검출되어 생산성이 올라갈 것입니다.

😌 참고한 레퍼런스

2개의 댓글

comment-user-thumbnail
2024년 2월 6일

내 코드에 뿌리는 페브리즈 같은 존재, SonarLint

1개의 답글