3개월치 AI 생성 코드를 전부 삭제했다. 그리고 배운 것들.
I mass deleted 3 months of AI generated code last week. Here is what I learned.
TL;DR Highlight
AI로 빠르게 만들었지만 이해 못 하는 코드베이스, 70% 삭제 후 2주 만에 재작성하니 절반 크기에 완전히 이해 가능해졌다.
Who Should Read
Claude, ChatGPT, Copilot 등 AI 코딩 도구를 실무 사이드 프로젝트에 적극 활용하고 있는 개발자. 특히 AI가 짜준 코드를 그대로 합치다 보니 전체 구조가 흐릿해진 경험이 있는 사람.
Core Mechanics
- AI는 단일 설정값에도 Configuration 클래스를 만들고, 직접 함수 호출이면 충분한 곳에 Event System을 끼워넣는 등 불필요한 추상화를 기본값으로 선택한다.
- 빠르게 output을 뽑는 것처럼 느껴졌지만 실제로는 '혼란이 생산성보다 더 빠르게 쌓이는' 상태였다. 체감 속도와 실제 복잡도 증가 속도가 달랐다.
- 기능을 추가하려고 코드베이스 전체를 건드려야 할 때, 내가 짠 게 아닌 패턴들이라 로직을 머릿속으로 추적하는 게 불가능했다.
- 전체의 70%를 삭제하고 2주 만에 재작성한 결과, 코드 라인 수가 절반으로 줄고 모든 부분을 직접 이해할 수 있게 됐다.
- AI 결과물을 '최종 코드'가 아니라 '이해하고 단순화해야 할 첫 번째 초안(first draft)'으로 다루는 방식으로 접근이 바뀌었다.
Evidence
- 3개월간 AI로 작성한 코드의 약 70%를 삭제 후, 2주 만에 재작성 완료.
- 재작성 후 코드 라인 수가 기존 대비 약 50% 수준으로 감소.
- ChatGPT, Claude, Copilot 세 가지 도구를 병행 사용한 실제 사이드 프로젝트 기반 경험.
How to Apply
- AI가 생성한 코드를 커밋 전에 반드시 '내가 이 로직을 말로 설명할 수 있는가?' 기준으로 검토한다. 설명 못 하면 이해한 게 아니니 직접 단순화한다.
- AI가 wrapper class, 설정 시스템, 이벤트 버스를 제안하면 '지금 당장 여러 곳에서 재사용되는가?'를 묻는다. 아니라면 직접 함수 호출이나 단순 변수로 대체한다.
- 새 기능 추가 전에 '기존 코드를 머릿속으로 추적할 수 있는가?' 테스트를 해본다. 안 된다면 기능 추가 전에 이해 가능한 수준으로 리팩터링을 먼저 한다.
Code Example
snippet
# AI가 만든 과도한 추상화 예시
class SingletonConfigManager:
_instance = None
def __init__(self):
self.config = {"debug": True} # 단 하나의 설정값
@classmethod
def get_instance(cls):
if not cls._instance:
cls._instance = cls()
return cls._instance
# 재작성 후 (이게 전부)
DEBUG = TrueTerminology
추상화구체적인 구현을 숨기고 인터페이스만 노출하는 설계 패턴. 잘 쓰면 복잡도 관리에 유용하지만, 과도하면 오히려 코드를 이해하기 어렵게 만든다.
Event System함수를 직접 호출하는 대신 '이벤트를 발행하고 구독자가 반응하는' 방식의 구조. 여러 곳에서 동일 이벤트를 처리해야 할 때 유용하지만, 단순한 1:1 호출에 쓰면 오버킬.
first draft최종 결과물이 아닌 첫 번째 초안. 여기서는 AI 출력물을 그대로 쓰지 말고 이해·단순화의 출발점으로 삼으라는 의미.
CopilotGitHub이 만든 AI 코드 자동완성 도구. 에디터 안에서 현재 맥락을 보고 다음 코드를 제안해준다.
wrapper class기존 클래스나 함수를 감싸는 새 클래스. 인터페이스를 바꾸거나 기능을 추가할 때 쓰지만, 아무 이유 없이 감싸면 레이어만 늘어난다.