SonarQube 정적 분석
원천 · framework/evomind/web/workflow-project-evo-service기준 · 릴리스 v0.12.0커밋 · 2e32c6cc파일 · docs/operations/sonarqube.md기준선 · 2026-11-12
사내 SonarQube 서버로 이 저장소의 코드(백엔드 Java·프론트 TypeScript)를 CI 에서 분석하고, 백엔드는 JaCoCo 커버리지까지 올린다. 지금은 결과를 알리기만 하고 파이프라인을 막지 않는다. 서버 주소와 토큰은 이 문서·저장소·이슈에 적지 않는다.
1. 구성
섹션 제목: “1. 구성”| 프로젝트(서버) | 분석 방법 | 소스 |
|---|---|---|
evo-service-api |
Gradle 플러그인 org.sonarqube(backend/app/build.gradle.kts 의 sonar 블록) — 클래스패스를 알아 Java 분석이 정확하다 |
backend/app/src/main, 테스트 src/test, 커버리지 jacocoTestReport.xml |
evo-service-web |
스캐너 CLI(sonarsource/sonar-scanner-cli:12.3, frontend/sonar-project.properties) |
frontend/src(단위 테스트가 없어 커버리지는 올리지 않는다) |
- 두 프로젝트로 나눈 것은 Java 분석에 컴파일된 클래스와 의존성 클래스패스가 필요하기 때문이다(프론트는 빌드 없이 소스만 본다).
- 백엔드 테스트가 끝나면 JaCoCo 0.8.16 이
backend/app/build/reports/jacoco/test/jacocoTestReport.xml을 만든다(./gradlew build에 포함). CI 의backend_build가 이 보고서를 아티팩트로 남기고 분석 job 이 읽는다(테스트를 다시 돌리지 않는다).
2. CI
섹션 제목: “2. CI”| job | 조건 | 동작 |
|---|---|---|
sonarqube_backend |
develop push, SONAR_HOST_URL·SONAR_TOKEN 이 있을 때 |
./gradlew :app:sonar -x test |
sonarqube_frontend |
같음 | sonar-scanner |
- MR 에서는 분석하지 않는다.
SONAR_TOKEN은 protected 변수라 보호되지 않은 브랜치·MR 파이프라인에 전달되지 않고, Community Build 는 브랜치 분석·GitLab MR 연동이 없는 것으로 알려져 있다. 병합 뒤 develop 분석 결과를 서버에서 본다. MR 분석이 필요해지면 서버 에디션(Developer 이상)과 토큰 전달 방식을 다시 정해야 한다. - 예약 파이프라인에서는 돌리지 않는다(코드가 바뀌지 않으면 결과가 같다).
- job 은
allow_failure이고 개발 러너(docker-build태그,.101·.202)에서 돈다. 변수가 없으면 job 이 만들어지지 않고, 서버에 접속하지 못하면 job 만 실패하고 파이프라인은 계속된다. - 분석 job 은
GIT_DEPTH: "0"(전체 이력)으로 받는다. 얕은 클론이면Shallow clone detected, no blame information경고가 나고 소스 작성자 정보가 빠진다. - 품질 기준(Quality Gate)은 기다리지 않는다(
-Dsonar.qualitygate.wait=false). 서버 화면에서 통과 여부를 본다.
3. 변수와 토큰
섹션 제목: “3. 변수와 토큰”SONAR_HOST_URL(일반)·SONAR_TOKEN(masked + protected, 분석 실행 전용 글로벌 토큰)은 최상위 그룹framework·internal의 CI/CD 변수로 등록되어 하위 프로젝트가 상속한다(evo-infra 가 등록). 스캐너는 두 값을 환경 변수로 읽으므로 명령줄·로그에 값이 나오지 않는다.- 이 저장소의
develop·main은 보호 브랜치이고 릴리스 태그는 보호 태그가 아니다. 그래서 토큰은 develop 파이프라인에만 전달된다. - 토큰에는 만료일이 없다. 로그·아티팩트·이슈·MR 에 값을 찍지 않는다. 교체가 필요하면 evo-infra 에 요청한다.
4. 첫 분석과 문제 해결
섹션 제목: “4. 첫 분석과 문제 해결”-
프로젝트 자동 생성은 evo-infra 도 확인하지 못했다. 첫 분석에서 “프로젝트가 없다”는 오류가 나면 SonarQube 에서
evo-service-api·evo-service-web프로젝트를 만들고(키가 같아야 한다) 다시 돌린다. 안 만들어진 채 토큰 권한 부족이 원인이면 evo-infra 에 알린다. -
분석이 실패하면 job 로그의 마지막 오류 줄을 본다. 서버 접속 실패는 러너의 DNS·TLS 문제일 수 있다(개발 러너.101·.202 는 접속을 확인했다).
-
로컬에서 분석 설정을 보려면 서버가 필요하다(스캐너 엔진을 서버에서 내려받는다). 로컬 시험은
cd backend && ./gradlew :app:test(JaCoCo 보고서 확인)까지만 한다. -
첫 분석(2026-10-30) 결과: 프로젝트
evo-service-web·evo-service-api가 첫 분석으로 자동 생성됐고(토큰에 생성 권한 있음), TLS 는 추가 설정 없이 통과했다. 프론트 분석 12.6초, 백엔드sonar단계 약 55초. 경고: 얕은 클론(위GIT_DEPTH), JavaUnresolved imports/types(분석은 성공, 원인 미확인), 프론트 소스의 인코딩 경고 — 실제로 깨진 글자(U+FFFD)가 있어 로 고쳤다(경고를 그냥 넘기지 말고 파일을 열어 본다). -
서버 API 는 익명 접근을 막아 CI 밖에서 결과(커버리지 반영 등)는 서버 화면에서 로그인해 확인한다.
5. 결과를 보는 법과 다음 단계
섹션 제목: “5. 결과를 보는 법과 다음 단계”- 서버 화면의 두 프로젝트에서 이슈(버그·취약점·코드 냄새)·보안 핫스팟·커버리지·중복을 본다.
- 몇 번의 분석 결과를 본 뒤 품질 기준과 파이프라인을 막는 조건을 사용자가 정한다. 그 전에는 막지 않는다.
- 라이브러리·이미지 취약점은 SonarQube 가 아니라 Trivy(
docs/operations/vulnerability-scan.md)가 본다.
답변은 문서를 근거로 만들지만 틀릴 수 있습니다. 출처 문서를 함께 확인하세요.