펌프 앤 덤프 소프트웨어 시대: 빠르게 만들고 버리는 개발 문화의 실체
펌프 앤 덤프 소프트웨어의 시대: 기술 부채를 떠넘기는 개발 문화
우리 업계에 새로운 유행이 있다. 빠르게 만들고, 화려하게 포장하고, 문제가 터지기 전에 빠져나가는 것. 주식 시장의 “펌프 앤 덤프(pump and dump)” 사기와 똑같은 패턴이 소프트웨어 개발에서도 벌어지고 있다. 그리고 이 쓰레기를 치우는 건 항상 다음 팀, 다음 개발자의 몫이다.
펌프 앤 덤프 소프트웨어란 무엇인가
펌프 앤 덤프 소프트웨어는 단기적인 성과와 데모를 위해 설계된 코드를 말한다. 겉으로는 작동하는 것처럼 보이지만, 실제로는 유지보수가 불가능하고 확장성이 없으며, 기술 부채 덩어리다.
이런 코드의 특징은 명확하다:
# 전형적인 펌프 앤 덤프 코드
def process_user_data(data):
# TODO: 나중에 리팩토링 (2019년에 작성됨)
# FIXME: 이거 왜 작동하는지 모르겠음
try:
result = data['user']['profile']['settings']['preferences']['theme']
except:
result = "default" # 모든 예외를 삼켜버리기
# 하드코딩된 값들
if result == "dark":
return {"color": "#000000", "bg": "#1a1a1a"}
else:
return {"color": "#ffffff", "bg": "#fafafa"}
이 코드는 작동한다. 데모에서도 잘 돌아간다. 하지만 3개월 후 다른 테마를 추가해야 할 때? 6개월 후 data 구조가 바뀔 때? 그때는 원래 개발자는 이미 다른 프로젝트로, 아니면 다른 회사로 떠났다.
왜 이런 현상이 만연해졌나
인센티브 구조의 문제
대부분의 회사에서 개발자는 “배포한 기능 수”로 평가받는다. 코드 품질? 측정하기 어렵다. 기술 부채 감소? 경영진 눈에 보이지 않는다.
// 평가 시즌에 작성되는 코드
const quickWin = async (userId) => {
// 직접 DB 쿼리 (ORM? 그게 뭔데?)
const result = await db.raw(`
SELECT * FROM users
WHERE id = ${userId} // SQL 인젝션? 뭐 어때
`);
// 캐싱? 다음 분기에 하죠
// 에러 핸들링? 프로덕션에서 테스트하면 되죠
return result[0];
};
짧아지는 재직 기간
평균 재직 기간이 2년도 안 되는 시대다. 내가 작성한 코드의 결과를 내가 책임질 일이 없다. 이직하면 끝이다.
스타트업 문화의 그림자
“일단 출시하고 나중에 고치자”는 말은 PMF(Product-Market Fit)를 찾는 초기 스타트업에서는 합리적이다. 문제는 시리즈 C 받은 500명 규모 회사에서도 같은 논리가 통용된다는 것이다.
실제 피해 사례: 코드로 보는 참상
유지보수 불가능한 코드가 어떻게 생겼는지 보자.
// "빠르게" 만들어진 API 엔드포인트
export const handleRequest = async (req: any, res: any) => {
// any 타입의 향연
const data: any = req.body;
// 비즈니스 로직 500줄이 한 함수에
if (data.type === "create") {
// 100줄의 로직...
} else if (data.type === "update") {
// 또 다른 100줄...
} else if (data.type === "delete") {
// 그리고 또...
} else if (data.type === "createOrUpdate") {
// 왜 이게 있지?
} else if (data.type === "softDelete") {
// 아...
} else if (data.type === "hardDelete") {
// 제발...
}
// 테스트? 작성자가 퇴사해서 불가능
res.json({ success: true }); // 항상 성공
};
이런 코드를 물려받으면 선택지는 두 가지다. 전체를 다시 짜거나(시간과 예산 없음), 그 위에 또 다른 펌프 앤 덤프 코드를 얹거나.
펌프 앤 덤프를 방지하는 방법
1. 코드 리뷰의 진짜 의미를 되찾자
LGTM 도장 찍기 식의 코드 리뷰는 무의미하다. 진짜 질문을 해야 한다.
❌ "LGTM"
❌ "몇 가지 nit이 있지만 approve"
✅ "이 함수가 400줄인데, 왜 분리가 안 될까요?"
✅ "여기 try-catch가 모든 예외를 삼키는데, 로깅이라도 해야 하지 않을까요?"
✅ "이 로직이 다른 곳에서 재사용될 것 같은데, 테스트가 없네요"
2. 기술 부채를 가시화하라
# tech-debt.yaml - 기술 부채 트래킹
- id: TD-001
created: 2024-01-15
author: "kim@company.com"
severity: high
description: "User 서비스에 any 타입 남용"
estimated_fix_hours: 16
blocking_features: ["user-analytics", "audit-log"]
- id: TD-002
created: 2024-01-20
author: "lee@company.com"
severity: critical
description: "결제 모듈 테스트 커버리지 0%"
estimated_fix_hours: 40
blocking_features: ["international-payment"]
이런 파일이 있으면 최소한 “몰랐다”는 변명은 못 한다.
3. 퇴사 전 코드 정리를 문화로
# 퇴사 체크리스트 (제안)
□ 내가 작성한 코드 중 TODO/FIXME 정리
□ 문서화되지 않은 암묵적 지식 정리
□ 후임자와 페어 프로그래밍 세션 2회 이상
□ 내가 만든 기술 부채 목록 작성
솔직한 의견: 이건 시스템의 문제다
개인을 탓하기 쉽다. 하지만 인센티브가 잘못되면 행동도 잘못된다. 빠른 배포를 보상하고 품질은 무시하는 시스템에서, 품질 좋은 코드를 기대하는 건 순진한 생각이다.
해결책? 측정할 수 없으면 관리할 수 없다.
# 빌드 파이프라인에 품질 게이트 추가
quality_metrics = {
"test_coverage": 80, # 최소 80%
"cyclomatic_complexity": 10, # 함수당 최대 10
"any_type_count": 0, # TypeScript any 금지
"todo_count_delta": 0, # TODO 증가 금지
}
if not meets_quality_gate(quality_metrics):
sys.exit(1) # 머지 불가
강제하지 않으면 안 한다. 슬프지만 현실이다.
펌프 앤 덤프 소프트웨어는 기술 부채 그 이상이다. 그건 다음 개발자에게 보내는 저주 편지다. 우리 모두 언젠가 그 다음 개발자가 된다는 걸 기억하자.
댓글남기기