ballqs 님의 블로그
[Spring] 소나클라우드(SonaCloud)란? 본문
소나클라우드(SonaCloud)란?
소나클라우드(SonaCloud)는 SonarQube와 관련된 클라우드 기반의 코드 품질 관리 플랫폼입니다. 소나클라우드를 사용하여 코드 품질을 분석하고, 버그 및 코드 스멜을 식별할 수 있습니다.
SonaCloud 가입 및 로그인
위 링크에 들어가서 로그인을 하면 된다.
github로 로그인하면 승인할건지 여러가지 모션이 뜸으로 상황에 따라 맞게 설정하면 된다.
Github 프로젝트 엮는 작업
github repository private는 유료버전이니 사용이 불가하다.
sonar cloud에서는 무료버전으로 사용하면 public으로 열린 repository만 적용 가능하다.
적용하고자 하는 Repository를 선택하면 아래와 같이 Set Up 버튼이 보이게 된다.
Set Up 버튼을 누르면 아래와 같이 나온다.
기준 옵션:
1.Previous version:
설명: 이 옵션을 선택하면, 이전 버전 이후 변경된 모든 코드가 새로운 코드로 간주됩니다. 정기적인 버전을 따르는 프로젝트에 추천됩니다.
2.Number of days:
설명: 이 옵션을 선택하면, 최근 x일 이내에 변경된 코드가 새로운 코드로 간주됩니다. 지속적인 배포를 따르는 프로젝트에 추천됩니다.
버전? 이라는 개념이 내가 알고 있는 그 버전인지 알지 못해 우선은 Previous version를 선택해 진행했다.
Create Project 버튼을 누르면 아래와 같이 나온다.
SonarCloud Token 확인!!
설명을 보면 적용할 Repository의 Settings > Secrets > Actions 로 가서 Secret 키로 등록하라고 한다.
Spring boot 적용
build.gradle 수정
1. 플러그인 적용
plugins {
...
id "org.sonarqube" version "5.0.0.4638"
}
기능: SonarQube 플러그인을 Gradle 프로젝트에 적용합니다. SonarQube는 코드 품질 분석 도구로, SonarCloud와 통합하여 클라우드에서 코드 분석 결과를 확인할 수 있습니다.
2. SonarQube 설정
subprojects {
apply plugin: 'org.sonarqube'
sonar {
properties {
property 'sonar.java.binaries', "${buildDir}/classes"
property 'sonar.coverage.jacoco.xmlReportPaths', "${buildDir}/reports/jacoco.xml"
}
}
}
기능: 하위 프로젝트에 대해 SonarQube 플러그인을 적용하고, SonarQube의 다양한 속성을 설정합니다.
- sonar.java.binaries: Java 바이너리 파일의 경로를 지정합니다. 이 경로는 코드 분석 시 클래스 파일을 찾는 데 사용됩니다.
- sonar.coverage.jacoco.xmlReportPaths: JaCoCo의 XML 보고서 경로를 지정합니다. 코드 커버리지 분석을 위해 JaCoCo의 결과를 SonarQube에 전달합니다.
3. 코드 제외 패턴 정의
def jacocoExcludePatterns = [
// 측정 안하고 싶은 패턴
"**/Q*.java",
"**/*Application*",
...
]
기능: JaCoCo 코드 커버리지 측정에서 제외할 파일 패턴을 정의합니다. 예를 들어, DTO, Exception 클래스 및 테스트 관련 파일을 제외하여 분석의 정확성을 높입니다.
4. SonarCloud 프로퍼티 설정
sonar {
properties {
property "sonar.projectKey", "ballqs_spring-task"
property "sonar.organization", "ballqs"
property "sonar.host.url", "https://sonarcloud.io"
property 'sonar.sources', 'src'
property 'sonar.language', 'java'
property 'sonar.sourceEncoding', 'UTF-8'
property "sonar.profile", "Sonar way"
property 'sonar.test.inclusions', '**/*Test.java'
property 'sonar.exclusions', jacocoExcludePatterns.join(',')
property 'sonar.java.coveragePlugin', 'jacoco'
}
}
기능: SonarCloud 분석을 위한 다양한 속성을 설정합니다.
- sonar.projectKey: SonarCloud에서 프로젝트를 식별하는 고유 키입니다.
- sonar.organization: SonarCloud에서 속한 조직의 이름입니다.
- sonar.host.url: SonarCloud 서버의 URL입니다.
- sonar.sources: 코드 소스 파일이 위치한 경로입니다.
- sonar.language: 분석할 코드의 프로그래밍 언어입니다.
- sonar.sourceEncoding: 소스 코드 파일의 인코딩 방식입니다.
- sonar.profile: 코드 품질 검사에 사용할 프로파일입니다.
- sonar.test.inclusions: 테스트 파일로 간주할 파일 패턴입니다.
- sonar.exclusions: 분석에서 제외할 파일 패턴입니다. 앞서 정의한 jacocoExcludePatterns를 사용합니다.
- sonar.java.coveragePlugin: JaCoCo를 코드 커버리지 플러그인으로 설정합니다.
5. 결론
SonarCloud와의 통합을 통해 프로젝트의 코드 품질을 자동으로 분석하고, 커버리지 보고서를 생성하여 코드 품질 개선에 기여합니다. 각 설정은 SonarCloud에서의 코드 분석을 최적화하고, 팀의 개발 프로세스에 통합하여 지속적인 코드 품질 관리를 가능하게 합니다.
6. 전체 코드
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.4'
id 'io.spring.dependency-management' version '1.1.6'
id "org.sonarqube" version "5.0.0.4638"
}
group = 'org.sparta'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
subprojects {
apply plugin: 'org.sonarqube'
sonar {
properties {
property 'sonar.java.binaries', "${buildDir}/classes"
// jacoco-aggregation을 사용하지 않은 경우 각 프로젝트의 buildDir마다 따로 적용
property 'sonar.coverage.jacoco.xmlReportPaths', "${buildDir}/reports/jacoco.xml"
}
}
}
def jacocoExcludePatterns = [
// 측정 안하고 싶은 패턴
"**/Q*.java",
"**/*Application*",
"**/*Config*",
"**/*Aop*",
"**/*Exception*",
"**/*Request*",
"**/*Response*",
"**/*Dto*",
"**/*Interceptor*",
"**/*Filter*",
"**/*Resolver*",
"**/*Entity*",
"**/test/**",
"**/resources/**"
]
sonar {
properties {
property "sonar.projectKey", "ballqs_spring-task"
property "sonar.organization", "ballqs"
property "sonar.host.url", "https://sonarcloud.io"
property 'sonar.sources', 'src'
property 'sonar.language', 'java'
property 'sonar.sourceEncoding', 'UTF-8'
property "sonar.profile", "Sonar way"
property 'sonar.test.inclusions', '**/*Test.java'
property 'sonar.exclusions', jacocoExcludePatterns.join(',')
property 'sonar.java.coveragePlugin', 'jacoco'
}
}
dependencies {
runtimeOnly 'com.h2database:h2'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
// spring security
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'
// jwt
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.12.5'
implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.12.5'
implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.12.5'
// bcrypt
implementation 'at.favre.lib:bcrypt:0.10.2'
// QueryDSL
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
//Slack API
implementation("com.slack.api:bolt:1.43.1")
implementation("com.slack.api:bolt-servlet:1.43.1")
implementation("com.slack.api:bolt-jetty:1.43.1")
implementation("org.slf4j:slf4j-simple:1.7.36")
implementation 'org.json:json:20190722'
// redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
//redisson
implementation 'org.redisson:redisson-spring-boot-starter:3.27.0'
}
tasks.named('test') {
useJUnitPlatform()
}
github action 수정
1. 워크플로우 이름 및 트리거 설정
name: SonarCloud
on:
push:
branches: [ "dev" ]
pull_request:
branches: [ "dev" ]
push: dev 브랜치에 푸시할 때 이 워크플로우가 실행됩니다.
pull_request: dev 브랜치에 대한 풀 리퀘스트가 생성되거나 업데이트될 때 실행됩니다.
2. jobs 정의
jobs:
build_and_analyze:
name: Build and SonarCloud Analysis
runs-on: ubuntu-latest
job 이름: build_and_analyze라는 이름으로 정의되며, Build and SonarCloud Analysis라는 표시 이름을 가집니다.
런타임 환경: ubuntu-latest 환경에서 실행됩니다.
3. 서비스 설정
services:
redis:
image: redis:6.2
ports:
- 6379:6379
options: >-
--health-cmd="redis-cli ping"
--health-interval=10s
--health-timeout=5s
--health-retries=5
Redis 서비스: Redis 데이터베이스를 Docker 컨테이너로 실행합니다.
- 이미지: redis:6.2 버전을 사용합니다.
- 포트: 6379 포트를 열어 Redis에 접근할 수 있도록 합니다.
- 헬스 체크 옵션: Redis가 정상적으로 작동하는지 확인하기 위한 헬스 체크를 설정합니다.
4. 단계 정의
steps:
- name: Checkout branch
uses: actions/checkout@v4
체크아웃 단계: 현재 브랜치를 체크아웃하여 코드가 작업 디렉토리에 복사됩니다.
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
JDK 설정: Java Development Kit (JDK) 17을 설치합니다. temurin 배포판을 사용합니다.
- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: ${{ runner.os }}-gradle
Gradle 캐시: Gradle 패키지를 캐싱하여 빌드 시간을 단축합니다.
- 경로: Gradle 캐시와 래퍼를 캐시합니다.
- 키: OS와 Gradle 파일의 해시를 기반으로 키를 생성합니다.
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
권한 부여: gradlew 스크립트에 실행 권한을 부여합니다.
- name: Cache SonarCloud packages
uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
SonarCloud 캐시: SonarCloud 관련 패키지를 캐시하여 분석 시간을 줄입니다.
- name: SonarCloud Scan
env:
SPRING_PROFILES_ACTIVE: test
REDIS_HOST: ${{ secrets.REDIS_HOST }}
REDIS_PORT: ${{ secrets.REDIS_PORT }}
SLACKBOT_TOKEN: ${{ secrets.SLACKBOT_TOKEN }}
JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }}
GITHUB_TOKEN: ${{ secrets.TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: ./gradlew build test sonar --info --stacktrace
SonarCloud 분석: Gradle을 사용하여 빌드하고 테스트한 후 SonarCloud 분석을 수행합니다.
- 환경 변수: 여러 환경 변수를 설정하여 테스트 및 분석에 필요한 정보를 제공합니다. 이 변수들은 GitHub Secrets에서 가져옵니다.
- SPRING_PROFILES_ACTIVE: Spring 프로파일을 test로 설정합니다.
- REDIS_HOST, REDIS_PORT, SLACKBOT_TOKEN, JWT_SECRET_KEY, GITHUB_TOKEN, SONAR_TOKEN: 각종 비밀 정보를 설정합니다.
- 실행 명령: Gradle을 사용하여 빌드, 테스트 및 SonarCloud 분석을 실행합니다. --info와 --stacktrace 옵션을 통해 더 자세한 로그를 출력합니다.
5. 결론
코드를 푸시하거나 풀 리퀘스트를 생성할 때마다 자동으로 빌드하고 SonarCloud를 통해 코드 품질을 분석합니다. Redis 서비스를 포함하여, Gradle 캐시를 활용하여 효율적인 빌드를 지원합니다. 이를 통해 개발 팀은 코드 품질을 지속적으로 유지하고 개선할 수 있습니다.
6. 전체 코드
name: SonarCloud
on:
push:
branches: [ "dev" ]
pull_request:
branches: [ "dev" ]
jobs:
build_and_analyze:
name: Build and SonarCloud Analysis
runs-on: ubuntu-latest
services:
redis:
image: redis:6.2
ports:
- 6379:6379
options: >-
--health-cmd="redis-cli ping"
--health-interval=10s
--health-timeout=5s
--health-retries=5
steps:
- name: Checkout branch
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: ${{ runner.os }}-gradle
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
- name: Cache SonarCloud packages
uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: SonarCloud Scan
env:
SPRING_PROFILES_ACTIVE: test
REDIS_HOST: ${{ secrets.REDIS_HOST }}
REDIS_PORT: ${{ secrets.REDIS_PORT }}
SLACKBOT_TOKEN: ${{ secrets.SLACKBOT_TOKEN }}
JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }}
GITHUB_TOKEN: ${{ secrets.TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: ./gradlew build test sonar --info --stacktrace
'코딩 공부 > Spring' 카테고리의 다른 글
[Spring] RedisTemplate vs Redisson (0) | 2024.11.22 |
---|---|
[Spring] Spring Batch란? feat.DB 분리 작업 (0) | 2024.11.10 |
[Spring] Redis Cluster localhost에 구현하여 적용 (0) | 2024.10.15 |
[Spring] Redis 동시성 문제 Redisson으로 해결! (0) | 2024.10.08 |
[Spring] Redis pub/sub란? (0) | 2024.10.07 |