인간이 유지보수할 수 있는 코드를 작성하라 – AI‑생성 중복의 위험
인간이 유지보수할 수 있는 코드를 작성하라 – AI‑생성 중복의 위험
TL;DR
LLM을 사용해 코드를 생성하면서 DRY(중복제거)나 기타 모범‑패턴을 강제하지 않으면, 중복된 조건문이 저장소의 새로운 "스타일"이 되고; 모델은 그 패턴을 재현해 미래 유지보수를 더 어렵게 만든다. 명시적인 리뷰 명령, 프롬프트, 정적 분석을 추가하면 코드베이스를 깔끔하게 유지할 수 있다.
저자가 제시한 문제
저자는 LLM에게 서로 다른 위치(라우트 핸들러, 백그라운드 잡, API 엔드포인트, 웹훅)에서 동일한 접근‑검사 로직을 반복해서 추가하도록 요청하는 워크플로를 설명한다. 각 생성된 스니펫은 다음과 같다:
if (user.isActive && user.hasPermission('read') &&
!user.isSuspended && account.status === 'open') {
// do a thing
}
공유 헬퍼를 추출하는 대신, 코드는 그대로 복사‑붙여넣기하고 테스트가 통과하면 그대로 머지한다. 단기적인 편리함은 장기적인 위험을 가린다: 비슷한 엔드포인트에 대한 새로운 요청마다 같은 조건문이 또 복사되어 중복 패턴이 강화된다. 나중에 리팩터링이 요구되면, LLM은 저장소에 현재 존재하는 다섯 개의 복사본을 모두 그대로 유지한다.
핵심 요점: 코드베이스에 병합된 각 단축키는 모델이 학습해 반복하게 되는 신호가 되며, 일회성 냄새가 만연한 스타일로 변한다.
LLM이 나쁜 패턴을 증폭하는 이유
- 컨텍스트‑드리븐 생성 – LLM은 열어 둔 파일과 최근 커밋을 읽고, 기존 코드를 향후 제안의 템플릿으로 활용한다.
- 패턴 강화 – 중복된 스니펫이 많을수록 이를 재생산하려는 편향이 강해진다.
- 유지보수성에 대한 내재된 개념 부재 – 모델은 프롬프트에 맞는 "동작하는 코드"를 최적화할 뿐, 장기적인 가독성이나 추상화를 고려하지 않는다.
"LLM은 당신이 하는 모든 것을 흡수하고 다시 되돌려 주는 스펀지다. 그러니 좋은 코드를 만들도록 하라." – Original post
커뮤니티가 제안하는 완화 방안
1. 체크리스트가 포함된 리뷰 명령 추가
- 마크다운 파일을 만든다(예:
.claude/commands/review.md). - "새 코드는 기존 로직을 중복하지 않는다"와 같은 구체적인 검사를 나열한다.
- 머지하기 전에 명령(
/review)을 호출한다; 에이전트가 계획을 생성하고 위반 사항을 표시한다.
"에이전트는 일반적인 피드백 벽을 받는다고 신경 쓰지 않고, 모든 항목을 기꺼이 살펴본다. 나는 ‘새로운 것이 이미 존재하는 코드와 중복되지 않도록’을 추가했는데, 정말 깜짝 놀랐다 – 정말로 정리를 계획하기 시작했다!" – cadamsdotcom
2. 최종 코드‑품질 검사를 위한 프롬프트
큰 변경 후 모델에게 다음을 확인하도록 요청한다:
- 관심사의 분리
- 남아 있는 실험 코드 없음
- 문서와의 일관성
"이제 최종 코드 검사를 해라. 모든 것이 깔끔하고 컴포넌트가 관심사 분리 원칙을 따르고 있나?" – planb
3. 정적 분석을 기본선으로 사용
CI 파이프라인에 린터나 코드‑냄새 탐지기(예: Credo, Rubocop, ESLint)를 통합한다. 그런 다음 LLM에게 보고된 구체적인 문제를 수정하도록 요청하면, 결정론적인 안전망을 제공한다.
"더 나아가 정적 코드 분석 도구를 추가하라… 기계적인 기준에 맞춰 검증하고, 필요할 때만 LLM 판단을 겹쳐 적용한다." – chickensong
4. 주기적인 모델‑기반 냄새 탐지 실행
일부 개발자는 일정에 따라 별도의 LLM(또는 전용 냄새 탐지 모델)으로 코드베이스를 스캔해 반복 패턴을 찾아낸다.
"나는 코드베이스를 다양한 모델에 지속적으로 돌려 중복 코드 같은 나쁜 냄새를 찾게 한다. 꽤 효과적이었다." – carimura
반론 및 미묘한 시각
LLM은 유지보수성을 향상시킬 수 있다 – 한 댓글러는 AI가 코드의 관심사 분리와 테스트 가능성을 개선했다고 언급한다.
"AI 덕분에 내 코드는 더 인간 친화적으로 유지보수 가능해졌다. 오래된 주석, 관심사 분리, 테스트 가능성 등에 대해 지적해 주었다…" – andai
모든 중복이 나쁜 것은 아니다 – 프로젝트 초기에 조기 추상화는 해로울 수 있다. 패턴이 안정될 때까지는 중복이 허용될 수 있다.
"프로젝트를 시작할 때는 모든 것이 DRY하지 않으며, 필요해질 때까지 공유 헬퍼를 뽑아내지 않는다." – chickensong
LLM은 기존 추상화를 무시할 수 있다 – 일부 사용자는 깨끗한 추상화가 존재해도 모델이 로직을 새로 구현하는 경우가 많다고 관찰한다.
"최신 LLM은 아무것도 하지 않으며, 그냥 새로 구현해 나간다…" – davnicwil
인간의 규율은 여전히 필수 – 팀이 일관되게 리뷰 프롬프트를 적용한다는 기대는 낙관적이며, 집단 규율이 약화될까 우려한다.
"LLM‑구동 그룹이 집단적으로 이런 규율을 갖는다는 생각은… 어리둥절하고 안타깝다." – MattyRad
AI‑지원 개발을 위한 실용 체크리스트
- 리뷰 체크리스트 정의(중복 감지, DRY, 네이밍 규칙 등). 에이전트가 읽을 수 있는 위치에 저장한다.
- 매 머지 전
/review실행; 출력물을 필수 코드‑리뷰 항목으로 간주한다. - CI에 정적‑분석 단계 추가; 새로운 냄새가 발견되면 빌드를 실패시킨다.
- 주기적인 LLM 냄새 스캔 일정을 잡아 드리프트를 포착한다.
- 유사 로직 추가 시 추상화 요청:
- "공유 헬퍼
hasReadAccess(user, account)를 만들고 모든 새로운 엔드포인트에서 사용해라."
- "공유 헬퍼
- 의도를 코드 주석에 문서화하여 모델이 구현뿐 아니라 이유도 볼 수 있게 한다.
결론
LLM은 빠르게 동작하는 코드를 만들어 내는 데 뛰어나지만, 규율 있는 검증이 없으면 중복되고 유지보수하기 어려운 패턴을 굳혀 버린다. 모델을 팀원으로 대하고 명시적인 가이드(리뷰 명령, 품질 프롬프트, 정적 분석)를 제공하면 코드베이스를 깨끗하게 유지하고 AI가 나쁜 습관을 학습하는 것을 방지할 수 있다.