콘텐츠로 이동

소스코드가 비대해지는 걸 막지 못한 것

파일 하나가 어느새 1,200줄이 되어 있었습니다. 아무도 그 파일을 열고 싶어 하지 않게 되었을 때, 저는 비로소 “이건 처음부터 막았어야 했다”는 걸 깨달았습니다. 더 무서운 사실은 따로 있었습니다 — AI와 함께 개발하면 이 비대화는 사람이 혼자 짤 때보다 훨씬 빨리, 훨씬 조용히 자란다는 것입니다.

처음엔 다들 멀쩡합니다. 어떤 업무를 담당하는 서비스 파일 하나가 200줄, 적당히 읽을 만합니다. 문제는 그 다음입니다. 기능을 더할 때마다 같은 파일에 코드가 쌓입니다. 한 번은 휴가 종류를 추가하고, 한 번은 결재선 검증을 넣고, 한 번은 통계 계산을 붙입니다. 그렇게 한 줄 한 줄, 아무도 “이쯤에서 나누자”고 말하지 않은 채 파일은 부풀어 오릅니다.

SL.AIMS에서 가장 크게 자란 파일 몇 개의 당시 크기입니다. 모듈의 핵심일수록 더 크게 부풀었다는 점에 주목해 주세요. 핵심이라 자주 손대고, 자주 손대니 더 커지는 악순환입니다.

파일(역할)줄 수권장 상한 대비
labs (연구소)약 1,279줄4.3배
leave (연차)약 1,133줄3.8배
documents (전자결재)약 1,104줄3.7배
건강한 상한선약 300줄1.0배

이게 한 번에 그렇게 된 게 아니라는 게 핵심입니다. 세션을 거치며 조금씩 쌓인 결과입니다.

1279 640 0 200 250 400 600 750 900 1100 1279 세션1 세션4 세션7 세션8 건강선 ≈300줄
한 파일이 세션을 거치며 커지는 모습(개념도). 파랑(안전) → 주황(경고) → 빨강(위험). 어느 한 세션도 "잘못한" 게 아닙니다. 각자 조금씩 더했을 뿐인데 결과가 1,279줄입니다.

왜 AI와 협업하면 더 빨리 커지나

섹션 제목: “왜 AI와 협업하면 더 빨리 커지나”

이건 사람만의 문제가 아닙니다. 오히려 AI와 짝을 이뤄 개발할 때 더 심해집니다. 이유는 단순합니다.

실제로는 이렇게 흘러갑니다.

  1. 세션 1 — 연구소 실험 기록 기능을 만듭니다. 서비스 파일이 200줄. 깔끔합니다.
  2. 세션 2 — 며칠 뒤 다른 작업. “실험 결과 통계도 넣어주세요.” AI는 같은 파일을 열고 통계 함수를 덧붙입니다. 250줄.
  3. 세션 3 — “장비 예약 기능도요.” 또 같은 파일. 400줄. 이쯤부터 스크롤이 길어집니다.
  4. 세션 4~7 — 매번 “관련 기능이니 여기에.” 600 → 750 → 900 → 1,100줄.
  5. 세션 8 — 1,279줄. 이제 이 파일을 고치라는 요청이 오면, AI든 사람이든 **“어디를 건드려야 안 깨지지?”**부터 한참 헤맵니다.

왜 위험한가 — 부채에는 이자가 붙는다

섹션 제목: “왜 위험한가 — 부채에는 이자가 붙는다”

기술 부채(technical debt)는 금융 부채와 똑같이 이자가 붙습니다. “나중에 정리하자”며 미룬 비용은 시간이 갈수록 불어납니다.

시점파일 크기수정 한 건 비용심리
초기300줄30분”금방 고치지”
6개월 후1,200줄3시간 + 버그 위험”이거 건드려도 되나…“
1년 후건드리기 두려움옆에 새 파일을 또 만듦 → 중복”차라리 새로 짜자”

비대한 파일은 단지 보기 싫은 게 아닙니다. 구체적으로 네 가지 비용이 있습니다. (1) 테스트가 어려워지고, (2) 비슷한 로직을 옆에 또 짜서 중복이 번지고, (3) 1,200줄에서 “그 로직”을 찾는 데만 한참 걸리고, (4) AI 특유의 비용 — 큰 파일을 통째로 읽느라 컨텍스트 창이 가득 차고, 토큰이 폭증하고, 결국 환각이 늘어납니다.

뒤늦게, 그러나 확실하게 — 두 가지 처방

섹션 제목: “뒤늦게, 그러나 확실하게 — 두 가지 처방”

문제를 인식한 뒤 두 가지를 했습니다. 하나는 이미 커진 것을 나누는 것(분할), 다른 하나는 다시는 커지지 못하게 **물리적으로 막는 것(게이트)**입니다.

거대 서비스를 기능별 작은 서비스로 쪼개되, 원래 이름은 그대로 둡니다. 원래 파일은 “안내 창구(facade)“만 남기고, 실제 일은 뒤에 새로 만든 작은 파일들에 넘깁니다. 바깥에서 부르는 방식은 하나도 안 바뀌고, 내부만 깔끔해집니다.

그때 (1개 파일) documents.service 약 1,104줄 생성·상신·승인 ·반려·이력·공유 ·통계·검증… 전부 한 파일에 지금 (facade + 하위) documents.service (facade) 바깥 호출은 그대로 — 얇은 창구 생성·상신 승인·반려 이력·공유 통계·검증 각 파일이 작아 → 읽기·테스트·수정 쉬움
facade 패턴: 바깥에서 보는 입구는 그대로 두고, 실제 일은 작은 파일들로 분산. "이사를 했지만 집 주소는 그대로"인 셈이라 다른 코드를 안 깨뜨립니다.

처방 ② ratchet 게이트 — 다시는 커지지 못하게

섹션 제목: “처방 ② ratchet 게이트 — 다시는 커지지 못하게”

분할만으로는 부족합니다. 막지 않으면 또 자랍니다. 그래서 커밋(저장) 단계에 “ratchet” 게이트를 심었습니다. ratchet은 한쪽으로만 돌아가는 톱니(자전거 뒷바퀴, 케이블타이를 떠올리면 됩니다)입니다. 핵심은 한 문장입니다 — “줄이는 건 자유, 늘리는 건 차단.”

상황ratchet 게이트의 판정
새 파일이 상한선(예: 300줄)을 넘김🚫 차단 — 처음부터 크게 만들지 마라
이미 큰 파일(1,104줄)을 더 키움 → 1,150줄🚫 차단 — “현재 크기”를 기준선으로 동결
이미 큰 파일을 1,104 → 1,080줄로 줄임✅ 통과 — 좋아지는 방향은 환영

이 모든 건 프로젝트 첫날 30분이면 세팅할 수 있는 규칙이었습니다. 파일 크기 한도 하나만 처음부터 걸어 뒀다면, god 파일 9개를 분할하느라 쓴 시간을 통째로 아꼈을 것입니다. “나중에 정리하자”는 생각이 정확히 이 부채를 만들었고, 그 “나중”은 늘 더 비싼 모습으로 찾아왔습니다.


이 글은 SL.AIMS를 만들며 겪은 현장 회고 중 하나입니다. 전체 그림은 〈사례연구: SL.AIMS〉에, 이런 폭주를 막는 규칙 체계는 〈AI에게 코드를 맡기되 폭주를 막는 법〉에 있습니다.