SonarQube를 이용한 지속적인 품질 관리


소프트웨어 개발은 크게 기능과 비기능 요건을 충족하도록 구현하는 대전제가 있는데, 왜냐하면 이 두가지 모두를 충족하지 못하면 어떤 형태로든 문제가 발생되기 때문입니다. 기능은 충족했지만, 성능, 보안, 확장성, 변화가능성 등의 수많은 비기능 요건을 충족하지 못해서 결국 재작업이라는 추가 비용이 발생되는 경우도 많이 있습니다.

비기능 요건이 기능 요건에 비해서 다루기 어려운 이유는 기능 요건에 대해서는 고객과 충분히 협의나 협상이 가능하여 범위 조정할 수도 있지만, 비기능 요건에 대해서는 기본적인 베이스라인이 충족해야만 해당 기능 요건을 실행할 수 있는 토대를 마련할 수 있기 때문에 고객과의 협의나 협상 대상의 폭이 그리 크지 않다는 점도 큰 작용을 합니다. 실행하지 않은 소프트웨어에 대해 비용을 지불하고 구매하려는 고객은 없을 것이기 때문입니다.

기능 요건들은 개발을 통해 고객에게 충분히 가시적으로 보여주는 영역이 있는 반면에, 비기능 요건에 대해서는 가시적으로 보여줄 수 있는 범위가 제한적이고 이 역시 별도의 비용이 발생될 수 밖에 없습니다. 특히, 소프트웨어 구축 비용 산정에 있어서 이러한 비기능 요건들에 대해서는 대부분이 비중있게 고려하지 않고 있는 상태라 비기능 요건을 충족시키려고 프로젝트 기간 동안 충분한 시간과 비용을 투여하기란 여간해서 쉽지가 않습니다.

SonarQube는 이와 같은 상황에서 프로젝트에 적용한다면 적은 시간과 비용으로 비기능 요건에 대한 가시화를 충분히 충족시킬 수 있는 도구임에 틀림없습니다. 물론, 그러한 가시화를 통해서 비기능 요건들을 충족시키려는 노력은 별도로 수반되어야 할 것입니다.

사용방법

SonarQube는 www.sonarqube.org에 서 다운로드 받을 수 있으며, 실행을 위해서는 tomcat과 같은 웹 애플리케이션 서버와 MySQL이나 오라클 같은 데이터베이스가 우선 필요합니다. 물론, SonarQube내에서 자그마한 웹서버를 통해 독자적인 실행도 가능하지만, 다양한 시스템들을 같이 한꺼번에 관리할 수도 있고 장기적으로 사용하려면 별도의 독자적인 서버를 마련해서 실행하는게 좋습니다.

SonarQube는 크게 SonarQube와 SonarQube Runner로 나뉘어져 있으며, SonarQube는 웹 애플리케이션 서버 내에서 실행하는 war로 구성되어 있습니다. SonarQube는 대상 소스를 분석한 결과를 보여주는 웹화면들로 구성되어 있으며, SonarQube Runner는 대상 소스를 분석하는 명령어가 있습니다. 형상관리 도구로부터 소스를 가지고 와서 소스를 분석 후, SonarQube를 통해 결과를 DB에 저장하고 이를 SonarQube를 통해 보는 방식입니다.

SonarQube 디렉토리 구조
[그림 1] SonarQube 디렉토리 구조

그림 1은 SonarQube의 디렉토리 구조이며, WAS의 구조와 거의 유사합니다. 즉, war 디렉토리 하위에 있는 war 파일을 tomcat과 같은 별도의 서버에 복사해서 실행이 가능합니다. 다만, DB 설정과 같은 내용들은 SonarQube 디렉토리 하위에 conf/sonar.properties를 통해서 설정해야 하며, SONARQUBE_HOME을 환경변수로 설정해야 합니다. (참고 : SonarQube 설치)

SonarQube Runner에는 실행 명령어(bin/sonar-runner)가 위치하고 있으며, 이를 통해서 웹서버와는 독립적으로 소스 분석이 가능합니다.

CI(Continuous Integration) 도구와의 연결

SonarQube는 Jenkins와 같은 CI(Continuous Integration) 도구를 통해서 연결이 가능합니다. 이를 위해서는 Jenkins Sonar Plugin을 설치하고, 해당 CI 작업 절차 중에 Post-build Actions에 Sonar 내용을 설정해주면 됩니다.

Jenkins Sonar Plugin을 설치하면 Configuration에 Sonar와 연결하는 내용을 입력하는 부분이 그림 2와 같이 나타납니다.

[그림 2] Jenkins와 SonarQube 연결 설정
[그림 2] Jenkins와 SonarQube 연결 설정

[그림 3] Jenkins의 작업에서 SonarQube 플러그인 내용 설정
[그림 3] Jenkins의 작업에서 SonarQube 플러그인 내용 설정

물론, Maven 프로젝트를 통해서 Jenkins는 실행해야 하며, pom.xml에도 이를 연결하는 설정이 별도로 필요합니다. CI를 통해서 SonarQube를 연결할 때에는 해당 작업을 실제 배포 작업과는 별도로 만들고, SonarQube 작업이 다 끝난 뒤에 배포 작업을 수행하도록 연결하는게 좋습니다. 분석하려는 대상 소스의 양이 많을수록 시간이 걸리며, SonarQube를 통해서 품질 문제를 모두 통과했다면 실제 배포는 단순한 빌드/컴파일만 수행하고 작업을 끝내는 것이 좋습니다. (빌드 작업에 대한 내용 참조 : http://homo-ware.tistory.com/206)

Jenkins와 SonarQube를 연결할 때에는 단위테스트 실행이 양쪽 모두 수행할 수 있기 때문에 Jenkins에서는 –DskipTests 옵션을 통해 빌드만 수행하고 SonarQube에서 단위테스트를 수행하도록 조절하는 것도 시간을 절약하는 방법이기도 합니다.

[그림 4] Maven의 pom.xml에 sonar 플러그인 설정
[그림 4] Maven의 pom.xml에 sonar 플러그인 설정

SonarQube 사용하기

SonarQube는 품질에 관련된 수많은 플러그인들이 존재하며, 분석시 이러한 플러그인들을 언제든지 추가하여 새로운 지표를 측정해볼 수 있습니다. 플러그인은 Update Center에서 온라인을 통해 설치할 수도 있지만, 인터넷 연결이 불가한 경우에는 SONARQUBE_HOME/extensions/plugins 디렉토리에 해당 jar만 올리면 됩니다.

최근에 SonarQube가 많이 사용되면서 언어로는 Android를 비롯해서 Scala까지 플러그인 개발이 진행되고 있으며, Fortify나 Google Analytics와 같은 플러그인들도 공개버전으로 제공되고 있습니다. 즉, SonarQube 하나만으로 다양한 품질을 측정할 수 있는 종합 선물 세트와 같은 느낌을 받습니다.

[그림 5] SonarQube 플러그인 라이브러리들
[그림 5] SonarQube 플러그인 라이브러리들

SonarQube를 통해 분석할 수 있는 언어는 Java를 포함해서 20여가지가 됩니다. 하지만, SonarQube의 단점은 하나의 작업에 하나의 언어만을 분석할 수 있기 때문에 Java와 JavaScript, Web, XML과 같이 섞여 있는 소스 코드를 한꺼번에 분석할 수는 없습니다. 즉, 동일 소스를 대상으로 해당 언어 만큼 작업을 실행해야 하는 단점이 있습니다. SonarQube의 플러그인이 가장 많은 것은 물론 Java이며 플러그인 별로 실행이 가능한 SonarQube 버전을 살펴봐야 합니다. 플러그인은 상용도 있으며, 사용자가 만든 것도 얼마든지 확장 가능합니다.

모든 것을 한눈에 보여주는 Dashboard 기능

SonarQube의 가장 뛰어난 기능이라면 단연 Dashboard를 들 수 있습니다. 사용자가 Dashboard 내용 편집이 가능하고, 플러그인에서 제공되는 화면에 대한 설정이 얼마든지 가능합니다. 특히, 여러가지 지표들을 종합하여 하나의 측정치를 보여주는 플러그인들도 있습니다. Technical Debt와 같은 플러그인의 경우에는 실제로 빚을 액수(달러)로 표현해주고 있습니다. 그림 6에서는 약 20만 라인의 소스가 60만 달러의 빚을 지고 있는 것으로 산출되고 있습니다. (빚은 상대적인 수치로 보는 것이 좋습니다. 실제로 60만 달러라는 금액은 정말 빚이 얼마되지 않은 좋은 수치에 포함됩니다.)

knowhow_img2-6
[그림 6] SonarQube의 Dashboard

Dashboard를 통해서 상세한 내용을 볼 수 있으며, 관련 소스를 더욱 자세하게 분석이 가능합니다. SonarQube가 Dashboard를 통해서 보여주는 내용은 소위 품질의 7가지 축(seven axes of quality)이라고 하는 ‘잠재적인 버그’, ‘코딩 규칙’, ‘테스트’, ‘중복’, ‘주석’, ‘아키텍처 및 설계’, ‘복잡도’에 관련된 내용입니다.

‘코딩 규칙’은 설정 부분에서 언어에 따라서 지정할 수가 있으며, Java의 경우에는 FindBugs와 같은 좀더 강력한 규칙을 적용해볼 수도 있습니다.

[그림 7] 특정 소스에 대한 다양한 분석 결과들
[그림 7] 특정 소스에 대한 다양한 분석 결과들

‘테스트’는 분석 대상 소스에 단위테스트가 있어야 하며, 커버리지를 통해 분석할 수 있습니다. ‘주석’이나 ‘중복’은 ‘주석’의 비율이 높으면 높을수록 좋고, ‘중복’은 비율이 적으면 적을수록 좋습니다. 이와 같이 서로 대조적으로 비교할 수 있는 지표들을 보여줌으로써 소스코드에 대한 품질을 다양한 각도에서 분석해볼 수 있습니다.

여러 프로젝트 간의 비교

[그림 8] SonarQube의 Treemap을 통한 각 프로젝트 간 비교
[그림 8] SonarQube의 Treemap을 통한 각 프로젝트 간 비교

Treemap에서 Size를 다양하게 변경함으로써 사각형의 크기가 이에 따라서 바뀌고, Color를 통해서 기준값을 변경함으로써 어떤 프로젝트가 얼마만큼의 크기로 어느 정도의 안정성을 가지는지를 비교해볼 수 있습니다. 예를 들어, Size에 LoC를 선택하고, Color를 Rules Compliance를 선택하면(그림 8) 사각형이 클수록 소스량이 많고, 색깔이 붉을수록 코딩 규칙을 위배하는 내용이 많은 부분을 볼 수 있습니다.

SonarQube 플러그인 중에는 소스코드의 영향도 파악을 위해 Doxygen 플러그인을 통해서 해당 소스를 호출하고 있는 다른 소스를 분석할 수 있는데, 이를 설치하기 위해서는 graphviz라는 라이브러리를 서버에서 이미지를 생성하도록 필요합니다. 다만, Doxygen은 정적 분석에 의존하기 때문에 인터페이스와 구현클래스와의 연결까지 분석해주지는 않습니다.

사실 영향도 분석은 모든 소프트웨어에서 가장 분석하기 어려운 부분이기도 합니다. 특히 시스템을 넘어서 재사용하는 모듈들에 대해서는 단순히 정적 소스 코드 분석만으로 모든 영향도 분석에 한계가 있습니다. 상용으로 영향도 분석 도구를 구매했다고 하더라도 각 시스템의 아키텍처나 내부 설계 구조에 따라서 영향도 분석 내용을 커스터마이징해야 하는 경우도 분명 발생합니다. 또한, 정적 소스 코드 분석의 한계가 있기 때문에 영향도 분석에서 아주 세세한 부분까지 파악하기는 힘들 수 있습니다.

[그림 9] Doxygen 플러그인을 통해 분석한 소스 call graph
[그림 9] Doxygen 플러그인을 통해 분석한 소스 call graph

온라인 코드 리뷰 협업

코드 리뷰를 수행하면 분명 코드의 품질은 높아지게 됩니다. 아무리 잘 짜여진 코드라고 하더라도 타인의 관점에서 해당 코드를 들여다보면 문제점이 발견되고는 하는데, SonarQube에서는 이를 온라인으로 수행할 수 있게끔 해줍니다.

[그림 10] SonarQube의 코드 리뷰 기능
[그림 10] SonarQube의 코드 리뷰 기능

특정 소스에서 문제가 발생된 지점은 코멘트를 적거나 해당 부분을 특정인에게 할당이 가능합니다. 혹은 문제가 없더라도 해당 소스 영역에서 의견을 개진할 수 있으며, 이 부분 역시 리뷰 절차를 수행할 수 있습니다.

이러한 코드 리뷰들은 이슈 절차에 따라서 모두 집계되고 실질적으로 코드 상의 이슈를 중점적으로 관리할 수 있도록 합니다. 물론, 이러한 이슈들은 Jira와 같은 도구와 연결할 수 있는 플러그인을 같이 사용하여 더욱 효과적으로 관리할 수도 있습니다.

Eclipse SonarQube 플러그인

IDE 도구인 Eclipse 역시 SonarQube 플러그인을 제공하고 있으며, 해당 프로젝트 선택시 관련 SonarQube 화면이 나타납니다.

[그림 11] Eclipse의 SonarQube 플러그인을 통한 연결
[그림 11] Eclipse의 SonarQube 플러그인을 통한 연결

독립적인 SonarQube 실행

SonarQube를 CI와 연결하지 않고, 소스 코드가 로컬이나 형상관리 도구에 위치하고 있다면, SonarQube Runner를 통해서 실행하면 되는데, 이 경우에는 소스나 컴파일된 바이너리의 위치를 지정하는게 필요합니다. 이러한 설정을 –Dproject.settings 를 통해서 지정할 수 있습니다.

[그림 12] 독립적인 실행을 위한 설정 및 실행 스크립트
[그림 12] 독립적인 실행을 위한 설정 및 실행 스크립트

개발에 부담이 아닌 도움을 주는 품질 가시화

비기능 요건인 소프트웨어 품질은 많은 부분에 있어서 개발에 대한 부담으로 작용하는게 사실입니다. 소스 코드의 분량이 늘어나면 늘어날수록 품질은 그만큼 더 안좋아지게 마련이며, 이를 위해서는 늘어나는 소스 코드 만큼 품질 활동이 뒷받침되어야 변경 이전의 상태 수준으로 맞출 수 있습니다. (소프트웨어의 회귀 성질이며, 이를 극복하는 방법 중에 하나가 회귀시험입니다) 늘어나는 소스 코드 만큼 품질 활동을 SonarQube가 대신해주고, 그에 대한 개선 활동을 지속적으로 수행한다면 늘 일정 수준의 소프트웨어가 유지될 것입니다.

지속적인 통합(CI, Continuous Integration)에는 꾸준한 속도로 소스 코드가 증가됨을 의미하며, 그에 맞게 품질 역시 지속적으로 개선되어야 함을 의미합니다. 이러한 지속적인 품질관리는 오픈소스인 SonarQube를 통해 일정 부분 달성할 수 있을 것입니다.


답글 남기기

이메일 주소는 공개되지 않습니다.