AI 생성 코드의 품질을 강제하기
- 2026-05-26 (modified: 2026-06-04)
에이전트 기반 코딩을 하거나 바이브 코딩을 하는 경우 코드 품질이 크게 낮아지는 경우가 있다(2025년 8월 기준). 하지만 AI 시대에도 소스코드 품질은 여전히 중요하므로 잘 관리할 필요가 있다.
개요
소스 코드의 품질을 정량적으로 평가하거나 특정 설계를 강제할 수 있는 도구들이 제법 있으니 이런 것들을 AI가 잘 활용할 수 있도록 설정해두면 품질을 일정 수준 이상으로 자동 관리할 수 있다.
AI 모델이 얼마나 똑똑해지는지도 중요하지만, 모델에게 적절한 도구들을 제공하여 모델이 일을 잘 할 수 있는 인지적 적소를 구축해주는 일 또한 매우 중요하다. (이걸 요즘에는 하네스라고 부르더라.)
쓸만한 조합 후보
다음은 내가 사용해본 제법 괜찮은 조합.
토큰과 AI 시간을 더 쓰더라도 품질 좋은 코드를 만들어야 지속 가능성이 높아진다. 자바스크립트 기준이지만 다른 언어를 쓰는 경우에도 대체로 유사한 도구가 있다.
- 기본적인 정적 타입 검사:
tsc --noEmit - 린터를 이용한 추가 제약:
typescript-eslint는recommended말고strictTypeChecked를 사용- 파일 최대 길이, 함수 최대 길이, 함수 최대 문장 수 제약
- 인지복잡도 제약(
eslint-plugin-sonarcode) switch문에서 모든 분기 검사(@typescript/switch-exhaustiveness-check), 매직 넘버 금지(@typescript-eslint/no-magic-numbers, 일부 예외 허용) 등
- 의존 관계 강제:
- 비즈니스 로직이 렌더링 관련 코드에 의존하지 못하도록 하기(
dependency-cruiser) - Feature-Sliced Design을 하는 경우 각 feature가 독립적이게 강제하기(
dependency-cruiser) - 각 모듈이 너무 많은 모듈에 의존하지 못하게 하기(
eslint-plugin-import) - 그 밖에 내가 원한 설계 기준을 벗어나지 못하도록 강제
- 비즈니스 로직이 렌더링 관련 코드에 의존하지 못하도록 하기(
- 코드 중복 검사:
jscpd등으로 구조적으로 동일한 코드 덩어리가 있으면 에러가 발생하도록 강제. 덩어리의 크기는 적당히 설정. nose를 쓰면 형식이 동일한 코드 뿐 아니라 동작이 동일한 코드도 일부 찾아준다. 리팩토롱 보조 도구로 활용하기에 좋다. - 테스트 커버리지: 단위 테스트와 인수 테스트와 테스트 커버리지 측정(
vitest등)하고 특정 기준 미만이면 오류를 내기 - 죽은 코드 검사: 코딩 에이전트를 코드를 지우는 일을 좀처럼 하지 않는다. 안쓰는 코드를 자동으로 검사해서 지우도록 할 필요가 있다.
knip등 사용 - 테스트-프로덕션 코드 비율 강제. AI에게 단위 테스트를 만들어달라고 시키면 같은 경로를 반복적으로 지나고 동일한 로직을 중복해서 검사하는 테스트를 너무 많이 만드는 경향이 있다. 테스트 대 프로덕션 코드 비율이 특정 수준(예: 100%, 인수 테스트를 포함하는 경우 120%)을 넘지 않도록 강제하면 이런 문제를 막을 수 있다. (
tokei등) - 뮤테이션 테스트: 테스트 커버리지만으로는 안심하기 어렵다. 코드를 임의로 수정했을 때 테스트가 깨지지 않는다면 테스트에 문제가 있다는 뜻. Stryker Mutator 등 사용. 단 느리기 때문에 무턱대고 쓸 수는 없다. 3시간에 한 번씩 돌면서 최근 커밋된 파일과 나머지 전체 파일에서 층화임의추출을 해서 이 파일을 대상으로 뮤테이션 테스트를 하게 하면 자주 변경되는 파일에 대해 더 높은 빈도로 적용해볼 수 있다. mutation score는 낮게 시작해서 점진적으로 올린다. (뮤테이션 테스트는 밤에만 비동기로 돌린다는 동료의 아이디어에서 착안)
조합의 중요성
여러 도구를 잘 조합하는 게 중요하다. 원래도 있던 문제지만 AI 에이전트를 쓰는 경우 문제가 더 극단적으로 발생하는 경향이 있다. 예시:
- 테스트-프로덕션 코드 비율을 강제하지 않으면서 테스트 커버리지만 검사하면 테스트 갯수가 한없이 늘어나는 문제가 있다.
- 인지복잡도를 측정하지 않으면서 중복만 계속 제거하라고 하면 로직이 한없이 복잡해진다.
점진적으로 도입하기
프로젝트 중간에 도입하는 경우엔 점진적으로 하면 좋다. “점진적”에는 두 가지 뜻이 있다:
- 한 번에 모든 도구를 다 도입하지 않기. 예: 처음에는 테스트 커버리지 검사를 먼저 도입하고, 그 다음에 중복 검사를 도입하고. 이런 식으로.
- 한 번에 지나치게 강한 제약을 걸지 않기: 예: 커버리지 기준을 처음에는 30%로 시작했다가 점진적으로 올리기.