AI가 생성한 코드의 품질을 어떻게 보장할 것인가? 단일한 테스트나 리뷰만으로는 불충분합니다. 정적 분석(Static Analysis), 동적 테스트(Dynamic Test), Mutation Testing의 3단계(Layer)를 결합함으로써 다각적인 품질 보장이 가능해집니다.
본 기사에서는 AI 에이전트의 파이프라인에 통합한 2단계 품질 게이트의 설계와 구현을 소개합니다.
Tier 1은 빠르게 실행할 수 있으며, Tier 2는 시간이 걸리지만 깊은 품질 보장을 제공합니다.
pytest-cov를 사용하여 테스트 커버리지(Test Coverage)가 80% 이상임을 확인합니다.
pytest --cov=src/nexuscore --cov-report=term-missing --cov-fail-under=80
커버리지가 기준을 밑돌 경우, 미커버된 라인이 리포트되며 CoderAgent가 추가 테스트 생성에 참고할 수 있습니다.
코드 품질 점수(Code Quality Score)가 8.0 이상임을 확인합니다.
pylint src/nexuscore --fail-under=8.0
타입 힌트(Type Hint)의 일관성을 검증합니다.
mypy src/nexuscore --strict
OWASP Top 10 등의 일반적인 보안 취약점을 탐지합니다.
bandit -r src/nexuscore -ll
모든 도구를 일괄 실행하여 결과를 집계합니다.
def run_tier1(source_dir: str) -> Tier1Result:
results = {}
results["coverage"] = run_coverage_check(source_dir)
...
Tier 1의 커버리지는 '테스트가 코드를 실행했는지'만 보여줄 뿐, '테스트가 올바르게 검증하고 있는지'는 알 수 없습니다.
# 커버리지 100%지만, 실질적으로 아무것도 테스트하지 않은 예시
def test_process():
result = process(data) # 실행함 (커버리지에 기여)
...
Mutation Testing은 코드에 의도적인 버그를 심고, 테스트가 그것을 탐지할 수 있는지로 품질을 측정합니다.
def run_tier2(source_dir: str, tests_dir: str) -> Tier2Result:
mutation_result = run_mutation_testing(
source_dir=source_dir,
...
GuardianAgent는 품질 게이트의 결과를 리뷰 판단에 통합합니다.
class ReviewDecision:
APPROVE = "approve" # 품질 게이트 통과 + 리뷰 OK
REJECT = "reject" # 품질 게이트 불통과 or 리뷰 NG
...
품질 게이트 결과
━━━━━━━━━━━━━━━━━━━━
Tier 1 (정적 분석):
...
모든 파일에 대한 리뷰가 아닌, 변경 차이(Diff)만 리뷰하는 고속 모드도 있습니다.
def review_diff(self, diff_text: str) -> ReviewResult:
# 차이의 요약 생성
summary = self.summarize_diff(diff_text)
...
차이 리뷰를 통해 대규모 프로젝트에서도 리뷰 시간을 단축할 수 있습니다.
처음부터 모든 도구를 도입하면, 기존 코드 수정이 대량으로 발생합니다. 단계적인 도입이 권장됩니다.
Week 1: 커버리지 체크만 (60% 시작 → 주 5% 인상)
Week 2: Pylint 추가 (6.0 시작 → 주 0.5 인상)
Week 3: MyPy 추가 (경고 레벨 → 에러 레벨)
...
GuardianAgent는 테스트 코드 내의 '무의미한 어설션(Assertion)'을 탐지합니다.
# 탐지 패턴
assert True # 항상 True
assert result is not None # None 체크만으로 값 검증이 없음
...
이들은 커버리지에는 기여하지만, 품질 보장에는 기여하지 않습니다.
테스트 코드 내에 포함될 가능성이 있는 위험한 명령어 문자열을 탐지합니다. 셸 호출이나 SQL문 직접 임베딩 등을 정적으로 스캔하여 리뷰 대상으로 플래그 지정합니다.
Tier 2 실행 시간: Mutation Testing은 수십 분이 걸리기 때문에 모든 커밋에 대해 실행하는 것은 비현실적입니다. PR(Pull Request) 시 또는 병합 전(merge前)에만 실행하는 것이 현실적입니다.
기준값 튜닝: 커버리지 80%나 Pylint 8.0과 같은 임계값은 프로젝트의 성숙도에 따라 조정이 필요합니다.
AI 생성 코드 특유의 문제: AI는 품질 게이트의 기준을 '학습'하여, 형식적으로는 통과하지만 실질적으로 품질이 낮은 코드를 생성할 수 있습니다.
품질 게이트(Quality Gate)는 다층적일수록 강력하지만, 동시에 운영 비용도 증가합니다. Tier 1(정적 분석)을 빠르고 첫 번째 방어선으로, Tier 2(Mutation Testing)를 깊은 품질 보증의 두 번째 방어선으로 하는 2단계 구성이 비용과 품질 사이에서 좋은 균형을 이룹니다.
품질 보증은 '한 번 도입하고 끝'이 아니라, 프로젝트의 성장에 맞춰 기준을 높여가는 지속적인 노력입니다.
본 기사는 개인 Zenn에서도 공개했습니다.