9.8.4. 중복 코드(Duplication) 비율 분석을 통한 모듈화 수준 평가
코드 중복(Code Duplication), 일명 ’복붙(Copy & Paste)’은 소프트웨어 아키텍처에서 기술 부채(Technical Debt)를 이자율이 가장 흉악한 사채업자에게 끌어다 쓰는 것과 같다. 한곳에서 치명적인 보안 취약점이나 논리 버그가 발견되어 이를 수정하려 할 때, 코드베이스 전체를 샅샅이 뒤져 변형 복제된 10군데의 스파게티 코드를 똑같이 찾아내어 하나하나 수작업으로 수정해야 하는 유지보수의 비극이 시작되기 때문이다.
거대 언어 모델(LLM)은 그 내부 구조가 본질적으로, 앞서 자신이 방금 작성한 출력 토큰들이나 시스템 프롬프트에 제공된 주변 문맥(Context)을 베팅 보드(Betting Board) 삼아 다음 단어를 가장 확률이 높은 순서대로 이어 붙이는 통계적 텍스트 생성 기계다. 따라서 모델은 추상적인 아키텍처의 구조적 설계를 깊이 고민하며 트리를 짜고 기존 함수를 재사용(Reuse, 모듈 호출)하는 대신, 단순히 컨텍스트 윈도우 안에 눈에 띄는 기존의 비슷한 코드를 통째로 복사해서 변수명만 몇 개 슬쩍 바꾸는 **‘게으른 중복(Lazy Duplication)’**을 저지르려는 강력한 통계적 유혹에 빠지기 일쑤다.
정적 분석 오라클(Static Analysis Oracle)은 AI가 이러한 저비용-고위험(Low-effort, High-risk)의 끔찍한 안티 패턴(Anti-pattern) 코드를 무한정 양산하여 코드베이스를 썩게 만드는 것을 CI 단계에서 철저히 감시하고 차단해야만 한다.
1. 정적 클론 카피 탐지(Clone Detection) 알고리즘의 작동 원리
최신 코드 분석기(Linter) 오라클이 코드베이스에서 중복을 잡아내는 과정은 단순 무식한 ctrl+F 텍스트 문자열 검색이 아니라, 소스 코드를 논리적 트리 구조로 분해한 AST(추상 구문 트리, Abstract Syntax Tree) 서명(Signature) 기반의 매칭 알고리즘을 따른다.
가드레일 오라클은 jscpd, PMD CPD (Copy/Paste Detector), 혹은 SonarQube의 자비 없는 내장 Duplication Engine 같은 강력한 전문 정적 스캐너 엔진을 런타임이 격리된 샌드박스 CI에서 돌려 코드를 해부한다.
- [Type 1 Clone (Exact Match)]: 들여쓰기(Indentation) 공간이나 텍스트 주석(Comment) 문자열만 다르고 실제 구문 비즈니스 로직은 토씨 하나 안 틀리고 완전히 100% 동일한 거울 복사본.
- [Type 2 Clone (Renamed Match)]: 변수명, 클래스명, 메서드명만 동의어나 오타로 미묘하게 다르게 바꾼 기만 패턴. (LLM 챗봇이 컨텍스트 길이를 억지로 채우기 위해 가장 뻔뻔하게 자주 저지르는 행태)
- [Type 3 Clone (Near Miss)]: 전체적인 AST 트리 구조로는 90% 이상 거의 완벽하게 일치하지만, 함수 블록 중간에 한두 줄짜리 커스텀 비즈니스 로직(예: 다른 타입의 로깅 처리, 에러 핸들링 분기)이 살짝 끼어 있는 약삭빠른 패턴.
오라클 시스템 검증 엔진은 AST 단위 노드들의 해시(Hash) 값을 계산하고 전체 파일을 스위핑하며 비교하여, 거대한 모노리포 프로젝트 내에서 연속된 N줄(보통 10~15줄의 Statement 기준) 이상의 로직 단위가 소름 돋게 겹치는 클론 구간을 수백 밀리초 단위 만에 역추적하여 붉은색으로 색출해 낸다.
2. 모듈화 레이더(Modularity Radar) 지표와 엄격한 임계값 대시보드 강제
조직의 DevOps 오라클 파이프라인은 PR(Pull Request) 리뷰 스테이지에서 ‘전체 라인 수 대비 중복 코드 비율(Duplicated Lines Density)’ 메트릭에 대한 자비 없는 수학적 상한선을 두어야 한다.
- [엔터프라이즈 하드 임계값(Threshold)]: 코드의 확장과 생성이 활발한 일반적인 대규모 엔터프라이즈 모노리포(Monorepo) 코드베이스에서는, 특정 패키지(Module) 또는 전체 프로젝트 전체 용량 대비 중복 코드의 비중을 3% ~ 5% 이하의 가혹한 수준으로 타이트하게 통제한다.
- [DRY 법칙 위반 자동 낙인]: 만일 AI 개발 에이전트가 새로 작성하여 커밋(Commit)으로 밀어 넣은 코드 뭉치 브랜치 덕분에, 프로젝트 전체의 누적 중복 비율 지표가 이 임계값을 위로 돌파해버리거나, 혹은 방금 새로 생성된 파일 단일 객체 클래스 자체의 중복률 스코어가 10%를 넘는 부끄러운 수치를 기록한다면, 해당 코드는 그 즉시 소프트웨어 공학의 절대 방탄 원칙인 DRY(Don’t Repeat Yourself) 법칙 위반으로 낙인찍히고 파이프라인에서 자동 폐기(Reject) 상태로 튕겨 나간다.
3. “Extract Method” 아키텍처 수술을 강요하는 구체적 리팩토링 프롬프트 주입
파이프라인에서 중복 코드를 잔뜩 뱉어내다 스캐너에 적발된 AI 봇 모델에게, 역으로 피드백 루프를 돌려 수정 기회를 줄 때 단순히 *“당신의 코드에 중복이 너무 많으니 알아서 줄이세요”*라고 모호한 자연어로 훈계 지시하면, LLM은 심각한 확률적 혼란에 빠진다. 모델은 중복을 없앤답시고 엉뚱하게 정상적인 핵심 비즈니스 로직을 멋대로 축소 및 파괴하거나, 변수명을 전혀 도메인 맥락에 맞지 않게 암호처럼 더 난해하게 꼬아놓고 로직을 억지로 숨겨서 정규식 기반의 Type 3 클론 체커 엔진 감시망 레이더를 꼼수로 우회(Bypass)하려고만 시도한다.
구조 가드레일 오라클이 실패 상황 시 LLM 컨텍스트로 쏘아 올리는 재시도(Retry) 에러 수정 피드백 스택 로직은 극도로 구체적이고 아키텍처 설계적이어야 한다.
[오라클의 리팩토링 개입 강력 피드백 로그 예시]
“[Duplication Oracle Reject Error] 치명적 중복 감지: 당신(AI)이
UserAuth.ts클래스 파일 브랜치에 방금 새로 작성한verifyEmailAddress()함수의 15~32라인 제어문 영역 전체 블록이, 기존 메인 코드베이스의PasswordReset.ts클래스 안에 깊이 묻혀 있는 유효성 검사 로직 단위와 AST 레벨에서 92% 이상 의미론적으로 일치하는 중복(Type 2 Clone) 지표를 보입니다.
이 형편없는 코드 복붙(Copy&Paste) 구조를 당장 파기하십시오. 이 이메일 검증 로직 부분 블록을 완전히 밖으로 뜯어 분리하여,ValidationUtil.ts와 같은 범용 공통 싱글턴 헬퍼 클래스로 함수를 상향(Extract Method & Move) 제안시키고, 기존 클래스와 당신이 짠 신규 클래스 양쪽 컴포넌트 모두에서 해당 공통 모듈 함수 라인 하나만을 재호출하도록 (Reuse) 아키텍처 의존성을 리팩토링한 코드를 다시 제출하십시오.”
중복률 정적 오라클을 CI/CD 파이프라인 파사드(Facade) 최전선의 무자비한 수문장(Gatekeeper)으로 세우면, 백엔드 AI 에이전트는 더 이상 텍스트 생성의 단순한 편의성과 확률적 관성(Probability Inertia)에 굴복해 코드 스니펫을 아무렇게나 복사해서 늘여놓고 PR을 던지지 못하게 된다. 새로운 비즈니스 기능을 무리하게 확장 추가할 때마다, 기존 아키텍처 폴더 트리의 빈 공간을 스스로 파악하고 선행 학습하며, 공통된 유틸리티 모듈로 책임(Responsibility)을 똑바르게 잘라내어 클래스의 추상화 수준을 스스로 한 단계 끌어올리는, 진정한 의미의 시니어급 소프트웨어 객체 지향 설계(Object-Oriented Design) 로직 훈련을 기계적으로 강제받게 되는 것이다.