이코에코(Eco²)
이코에코(Eco²) 백엔드/인프라 코드 품질 분석기 도입
mango_fr
2025. 12. 20. 10:59

코드 품질을 객관적으로 측정하고 지속적으로 모니터링하기 위해 자동 정적 분석 도구들을 도입했습니다.
LLM이 생성하는 코드의 품질을 검수하기 위한 핵심 지표로 활용됩니다.
주요 지표인 단위 테스트 커버리지는 80%+를 준수하도록 가이드라인을 설정했습니다.
도구 선정 기준
| 기준 | 설명 |
|---|---|
| 비용 | 무료 또는 오픈소스 Public repo 무료 |
| Python 지원 | Python 3.11 호환 |
| CI 연동 | GitHub Actions 통합 가능 |
| 선언적 설정 | 코드베이스에서 설정 관리 |
도입 도구
| 도구 | 용도 | 비용 |
|---|---|---|
| Radon | Cyclomatic Complexity, Maintainability Index | 무료 (로컬 CLI) |
| SonarCloud | 종합 코드 품질, 보안 취약점 | Public repo 무료 |
Radon 설정 및 사용
설치
pip install radon
설정 (pyproject.toml)
[tool.radon]
exclude = "test_*,*_test.py,conftest.py,__pycache__,worktrees,.venv"
cc_min = "C" # Minimum grade to show (A=best, F=worst)
mi_min = "B" # Maintainability Index minimum grade
show_complexity = true
average = true
사용법
# Cyclomatic Complexity 측정
radon cc domains/ -a -s
# Maintainability Index 측정
radon mi domains/ -s
# Raw 메트릭 (LOC, LLOC 등)
radon raw domains/ -s
복잡도 등급
| 등급 | 복잡도 범위 | 의미 |
|---|---|---|
| A | 1-5 | 단순, 위험 낮음 |
| B | 6-10 | 약간 복잡 |
| C | 11-20 | 복잡, 리팩토링 권장 |
| D | 21-30 | 매우 복잡 |
| F | 31+ | 테스트 불가 수준 |
SonarCloud 연동
프로젝트 설정 (sonar-project.properties)
# Project identification
sonar.projectKey=eco2-team_backend
sonar.organization=eco2-team
sonar.projectName=backend
# Source settings
sonar.sources=domains
sonar.tests=domains
sonar.test.inclusions=**/tests/**,**/test_*.py,**/*_test.py
sonar.exclusions=\
**/tests/**,\
**/test_*.py,\
**/*_test.py,\
**/conftest.py,\
**/*_pb2.py,\
**/*_pb2_grpc.py,\
**/proto/**
# Python settings
sonar.python.version=3.11
sonar.python.coverage.reportPaths=coverage.xml
# Coverage exclusions
sonar.coverage.exclusions=\
**/tests/**,\
**/proto/**,\
**/*_pb2.py,\
**/*_pb2_grpc.py
GitHub Actions Workflow
# .github/workflows/ci-sonarcloud.yml
name: SonarCloud Analysis
on:
workflow_dispatch:
push:
branches: [develop, main]
paths:
- 'domains/**/*.py'
- 'sonar-project.properties'
jobs:
sonarcloud:
name: 🔍 SonarCloud Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install -r domains/character/requirements.txt
pip install pytest pytest-cov pytest-asyncio
- name: Run tests with coverage
run: |
pytest domains/character/tests/ \
--cov=domains/character \
--cov-report=xml:coverage.xml \
--ignore=domains/character/tests/integration/ \
--ignore=domains/character/tests/e2e/
continue-on-error: true
- uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
플랜 및 제한사항
SonarCloud는 유료 플랜 구독 시 PR/feature 브랜치 분석을 지원합니다.
| 플랜 | 브랜치 분석 | PR 분석 | 가격 |
|---|---|---|---|
| Free (Public) | main만 | ❌ | 무료 |
| Developer+ | 모든 브랜치 | ✅ | 유료 |
현재 적용: 무료 플랜 사용으로 main/develop 브랜치 머지 후에만 분석 실행.
# PR 분석은 유료 플랜 필요 - 현재 미사용
# main/develop 머지 후에만 분석 실행
on:
push:
branches: [develop, main]
# pull_request: 유료 플랜 필요
실측 결과
Radon Cyclomatic Complexity
실행: radon cc domains/ -a -s --total-average
결과:
- 총 블록: 1,004개
- 평균 복잡도: A (2.51)
- A등급: 997개 (99.3%)
- B등급: 7개 (0.7%)
- C등급 이상: 0개
개선 전후 비교
| 지표 | 개선 전 | 개선 후 |
|---|---|---|
| 총 블록 | 992개 | 1,004개 |
| 평균 복잡도 | A (2.53) | A (2.51) |
| C등급 함수 | 7개 | 0개 |
| D/F등급 | 0개 | 0개 |
테스트 커버리지
실행: pytest --cov=domains/character/services --cov-report=term-missing
결과:
- services/character.py: 91%
- services/evaluators/base.py: 100%
- services/evaluators/scan.py: 97%
- services/evaluators/registry.py: 83%
- 전체: 92%
결론
도입 효과
- 객관적 품질 지표: 복잡도, 커버리지 수치화
- 지속적 모니터링: CI에서 자동 분석
- 선언적 설정: 코드베이스에서 버전 관리
권장 사용 패턴
# 로컬 개발 시 - Radon으로 빠른 체크
radon cc domains/my_module/ -a -s
# PR 머지 전 - pytest 커버리지 확인
pytest --cov=domains/my_module --cov-report=term-missing
# 머지 후 - SonarCloud 대시보드 확인
https://sonarcloud.io/dashboard?id=eco2-team_backend
목표 지표
| 지표 | 목표 | 현재 |
|---|---|---|
| 평균 복잡도 | A | ✅ A (2.51) |
| C등급 함수 | 0개 | ✅ 0개 |
| 서비스 커버리지 | 80%+ | ✅ 92% |