본문으로 건너뛰기

AI 생성 코드의 품질을 강제하기

  • 2026-05-26 (modified: 2026-06-04)

에이전트 기반 코딩을 하거나 바이브 코딩을 하는 경우 코드 품질이 크게 낮아지는 경우가 있다(2025년 8월 기준). 하지만 AI 시대에도 소스코드 품질은 여전히 중요하므로 잘 관리할 필요가 있다.

개요

소스 코드의 품질을 정량적으로 평가하거나 특정 설계를 강제할 수 있는 도구들이 제법 있으니 이런 것들을 AI가 잘 활용할 수 있도록 설정해두면 품질을 일정 수준 이상으로 자동 관리할 수 있다.

AI 모델이 얼마나 똑똑해지는지도 중요하지만, 모델에게 적절한 도구들을 제공하여 모델이 일을 잘 할 수 있는 인지적 적소를 구축해주는 일 또한 매우 중요하다. (이걸 요즘에는 하네스라고 부르더라.)

쓸만한 조합 후보

다음은 내가 사용해본 제법 괜찮은 조합.

토큰과 AI 시간을 더 쓰더라도 품질 좋은 코드를 만들어야 지속 가능성이 높아진다. 자바스크립트 기준이지만 다른 언어를 쓰는 경우에도 대체로 유사한 도구가 있다.

  • 기본적인 정적 타입 검사: tsc --noEmit
  • 린터를 이용한 추가 제약:
    • typescript-eslintrecommended 말고 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%로 시작했다가 점진적으로 올리기.