반쯤 만든 기능 캐비닛: 버려진 개발 작업을 다시 살려내는 실용 시스템
흩어져 버린 반쯤 완성된 기능들을 ‘노력의 무덤’이 아니라, 팀이 안전하게 구조·재사용·완성할 수 있는 구조적인 “기능 캐비닛”으로 전환하는 방법을 소개합니다.
반쯤 만든 기능 캐비닛: 처음부터 다시 만들지 않고 버려진 개발 작업을 구조하는 간단한 시스템
어느 팀에나 있다. 브랜치 속에 숨어 있는 반쯤 만든 기능들, 잊힌 티켓들, 먼지 쌓인 PR. 지워 버리기엔 너무 많이 진척됐지만, 다시 손대기엔 너무 지저분한 작업들. 그래서 그대로 방치된 채로, 조용히 팀의 정신적 리소스를 잠식한다.
이 미완성 작업들을 없는 셈 치거나, 죄책감과 망각 사이를 왔다 갔다 할 필요는 없다. 대신 그들에게 제대로 된 집을 만들어 줄 수 있다. 바로 **반쯤 만든 기능 캐비닛(Half-Finished Feature Cabinet)**이다.
이 캐비닛은 다음을 위한 구조적인 시스템이라고 생각하면 된다.
- 버려진 작업을 묻어 두지 말고 보이게 만들기
- 최소한의 맥락을 남겨 안전하게 재사용할 수 있게 만들기
- 거대한 미지의 영역을 작고 잘 정의된 구조 작업으로 쪼개기
- 언제 구조할지, 언제 보내줄지 결정하기
이 글에서는 코드베이스(와 양심)를 깔끔하게 유지해 주는 기능 캐비닛을 어떻게 설계하고 운영할지 단계별로 살펴본다.
무덤 대신 “기능 캐비닛”이 필요한 이유
대부분의 팀에는 이미 사실상 무덤 같은 곳이 있다.
- 이름에
final-final-wip같은 수식어가 붙은 옛 브랜치들 - JIRA에서
Blocked로 옮겨진 뒤 조용히 잊힌 티켓들 - 끝내 머지되지 못한
Draft상태의 PR들
작업이 중단된 것 자체는 문제 아니다. 그건 흔한 일이다. 문제는 다음과 같다.
- 보이지 않는다 – “우리가 이미 시작해 둔 미완성 작업이 뭐가 있지?”에 아무도 제대로 답을 못 한다.
- 맥락이 없다 – 설령 뭔가를 찾아도, 무엇이 끝났고 무엇이 안 끝났는지 믿을 만한 기록이 없다.
- 의사결정 과정이 없다 – 기능이 영원히 떠돈다. 분명히 구조되거나, 분명히 종료되지 못한 채로.
기능 캐비닛은 이 흐름을 완전히 뒤집는다.
기능 캐비닛은 반쯤 끝난 작업들의 목록을 한눈에 볼 수 있게 모아두고, 간단하고 일관된 템플릿으로 문서화하며, 언제 구조하고 언제 버릴지에 대한 규칙으로 관리하는 시스템이다.
여기는 코드가 죽으러 가는 곳이 아니다. 대신 코드가 다음 둘 중 하나의 결말을 맞는 곳이다.
- 작고 명확한 후속 작업으로 깔끔하게 구조되거나,
- 영원한 보류 대신, 분명한 “아니오”와 함께 의식적으로 아카이브된다.
1단계: 기능 캐비닛을 “보이게” 만든다
우선, 모두가 볼 수 있는 하나의 공유 리스트를 만든다. 어떤 도구를 쓰든 상관없다. 다음 조건만 만족하면 된다.
- 중앙화 – 여러 리스트가 아니라 오직 하나
- 검색 가능 – 기능 이름, 도메인, 기술 스택 등으로 검색 가능
- 업데이트가 쉽다 – 번거로우면 아무도 안 쓴다
예시 옵션:
- 프로젝트 관리 도구 안에 전용 보드/컬럼:
Half-Finished Feature Cabinet(또는 한글 이름) - Notion / Confluence에 테이블 형태의 페이지 하나
- GitHub Projects 보드 +
half-finished같은 전용 라벨
최소한 각 항목에는 다음 정보가 있어야 한다.
- 제목 – 기능이나 작업을 한눈에 알 수 있는 이름
- (과거) 담당자 – 마지막으로 작업했던 사람
- 상태(Status) – 예:
Candidate,Ready to Rescue,Archived - 링크 – 관련 브랜치 / PR / 티켓 링크
이 리스트가 곧 “우리가 시작만 해두고 마치지 않은 것들”에 대한 **단일 진실의 원천(single source of truth)**이 된다.
2단계: 각 반쯤 만든 기능에 간단한 템플릿을 적용한다
무언가를 캐비닛에 추가할 때, 링크만 던져 놓지 말자. 나중에 다른 개발자가 안전하게 다시 집어 들 수 있을 정도의 최소 정보를 적어 둬야 한다.
다음처럼 표준 템플릿을 쓰는 것이 좋다.
반쯤 만든 기능 템플릿
- 요약(Summary): 이 기능이 무엇을 하는지, 왜 시작했는지 2–3문장으로 설명.
- 기술 스택 / 영역(Tech Stack / Area): 예) React + TypeScript 프론트엔드, Node.js API, PostgreSQL 마이그레이션 등
- 완료된 부분(What’s Done):
- 끝난 작업을 불릿 리스트로 정리
- 어떤 부분이 테스트됐거나 수동으로 검증됐는지 표시
- 부족한 부분(What’s Missing):
- 남은 작업, 미지의 부분, 필요한 의사결정을 불릿 리스트로 정리
- 주의사항 / 리스크(Gotchas / Risks):
- 알려진 버그, 성능 이슈, 까다로운 엣지 케이스
- 구조적·아키텍처 측면에서 민감한 부분 (예: “auth에 영향 있음”, “billing 로직 수정” 등)
- 현재 상태(Current State):
- 관련 브랜치 / PR 링크
- 마지막 업데이트 날짜
- 원래의 맥락(Original Context):
- 작업이 멈춘 이유 (우선순위 변경, 스코프 변경, 외부 의존성 블로킹 등)
길게 쓸 필요는 없다. 핵심은 완벽함보다 명확함이다. 미래의 나(또는 동료)에게 “이걸 구조할 가치가 있는지 판단할 수 있을 만큼의 지도”만 주면 된다.
팁: 이 템플릿을 Notion/Confluence 등에 복사해서 바로 쓸 수 있는 블록으로 만들어 두면, 10분 안에 작성할 수 있어 부담이 줄어든다.
3단계: 버려진 기능을 작은 “구조 작업”으로 쪼갠다
“이 반쯤 만든 기능 마저 끝내기” 같은 태스크는 좋지 않다. 모호하고, 부담스럽고, 추정도 어렵다.
템플릿을 채웠다면 다음 단계는 **해당 기능을 작고, 명확하게 범위가 정의된 구조 작업(rescue tasks)**으로 쪼개는 것이다.
예를 들어, 다음과 같은 태스크 대신:
- "새 리포팅 대시보드 마무리하기"
이렇게 쪼갤 수 있다.
- "대시보드 UI를 기존 metrics API에 연결하기"
- "페이지네이션 및 기본 필터 기능 구현하기"
- "대시보드 API에 대한 해피 패스 테스트 추가"
- "Feature flag와 롤아웃 설정 연동하기"
각 구조 작업은 다음을 만족해야 한다.
- 한 번의 스프린트 안에서 무리 없이 끝낼 만큼 작을 것
- **명확한 완료 조건(Definition of Done)**을 가질 것
- 원본 캐비닛 항목에 대한 링크를 포함할 것
이렇게 하면 개발자는:
- 캐비닛 항목을 열고
- 템플릿을 통해 현재 상태를 이해한 뒤
- 구조 작업 하나를 집어 들어, 의미 있는 결과물을 배포할 수 있다.
4단계: 죄책감이나 연차(오래됨)가 아니라 “효과와 노력”으로 우선순위를 정한다
구조 대상을 정하는 최악의 방식은 다음과 같다.
- "이게 제일 오래됐으니 이거부터 하자" (시간/신규성 편향)
- "여기에 이미 시간 많이 썼으니, 마저 끝내야지" (매몰비용에 대한 죄책감)
구조 작업도 다른 모든 일과 마찬가지로 비즈니스 케이스가 있어야 한다.
캐비닛 항목을 평가할 때는 이렇게 물어보자.
- 효과(Impact): 이 기능이 지금 완성된다면, 얼마나 큰 가치를 낼까?
- 여전히 유효한 고객 문제를 해결하는가?
- 현재 제품 전략과 방향성에 부합하는가?
- 노력(Effort): 템플릿 기준으로 남은 작업량은 어느 정도인가?
- 며칠 정도면 되는 일인가, 몇 주가 걸리는 일인가?
- 리스크(Risk): 이 작업을 이어가는 과정에서 기술적/조직적 리스크가 생기지 않는가?
간단한 스코어링 모델을 사용할 수 있다.
- Impact: 1–5
- Effort: 1–5 (역점수; 1 = 크다, 5 = 작다)
- Risk: 1–5 (역점수; 1 = 위험 크다, 5 = 안전하다)
Impact + Effort + Risk 합계가 높은 순으로 정렬해 구조 대상을 고른다. 이렇게 하면 감정이 아니라 합리적인 기준으로 의사결정할 수 있다.
5단계: 무엇을 구조하고, 무엇을 버릴지에 대한 규칙을 만든다
캐비닛에 있는 모든 것을 구조할 필요는 없다. 사실, 건강한 캐비닛은 꾸준히 아카이브되는 항목이 있는 상태다.
애매한 결정을 끝없이 미루지 않도록, 명확한 규칙을 정하자.
예시 규칙:
다음에 해당하면 구조한다(Rescue):
- 해당 기능이 여전히 현재 제품 전략·로드맵과 맞는다.
- 남은 작업량 추정이 작거나 중간 수준(너무 거대하지 않다).
- 작업을 멈추게 만들었던 의존성·블로킹 이슈가 해결됐다.
- 팀 내에서 이 구조 작업을 책임지고 가져갈 사람이 최소 한 명 있다.
다음에 해당하면 버리고 아카이브한다(Archive):
- 원래 겨냥했던 사용자 니즈가 더 이상 유효하지 않거나, 더 나은 솔루션이 이미 있다.
- 기술 스택·아키텍처가 너무 많이 바뀌어서, 구조하는 것보다 새로 만드는 게 더 싸다.
- 지금 기준의 코드 품질·아키텍처 요구사항을 도저히 맞추기 어렵다.
- 리뷰를 해 봐도 아무도 기능의 가치나 의도를 설득력 있게 설명하지 못한다.
버리기로 했다면, 의식적으로 아카이브하자.
- 캐비닛 항목의 상태를
Archived로 표시한다. - 한 줄짜리 이유를 남긴다. (예: “2025 Q3 신규 billing 플로우로 대체됨”)
- 코드/브랜치를 삭제할지, 참고용으로 남길지 결정한다.
분명한 "안 한다"는 선언은, 좀비 작업을 계속 떠돌게 두는 것보다 훨씬 낫다.
6단계: 구조 시간을 정기적인 플래닝에 포함시킨다
"시간 남으면 구조 작업 하자"라고 생각하면, 그 시간은 절대 오지 않는다.
대신 스프린트나 이터레이션 계획에 구조 시간을 명시적으로 예산으로 잡자.
예시 방식:
- 고정 비율 할당: 매 스프린트 용량의 10–15% 정도를 캐비닛 구조·클린업에 배정
- 순번 구조 담당제: 매 스프린트마다 1–2명의 개발자가 구조 작업을 주요 미션으로 담당
- 테마 스프린트: 가끔은 스프린트를 통째로 “Rescue & Refine” 주제로 잡아, 가치 높은 항목들을 한 번에 처리
스프린트 플래닝 중에는:
- 우선순위가 매겨진 캐비닛 리스트를 확인하고
- 상위 구조 작업 몇 개를 이번 스프린트로 끌어오며
- 이 작업들이 일반 티켓과 비슷한 크기·명확한 오너를 갖도록 맞춘다.
이렇게 하면 구조 작업이 죄책감에 떠밀린 번외 과제가 아니라, 정규 프로세스의 일부가 된다.
7단계: 구조하는 모든 작업에 최소 품질 기준을 적용한다
반쯤 만든 작업을 구조한다고 해서, 눈 감고 기술 부채를 떠안는다는 뜻은 아니다. 다음에 대해 최소 품질·구조 기준을 정해 두자.
- 코드 구조(Code structure): 현재의 패턴·아키텍처를 따르거나, 구조 과정에서 그 수준까지 리팩터링할 계획이 있을 것
- 테스트(Tests): 새 로직·변경된 로직은 테스트 가능해야 하며, 구조 작업의 일부로 테스트를 추가할 것
- 문서화(Documentation): 필요하다면 최소한의 docstring, 주석, 간단한 README 수준의 설명은 남길 것
- Feature flag / 롤아웃: 위험도가 있거나 사용자에게 직접 노출되는 기능은, 점진적 롤아웃·롤백이 가능하도록 제어 수단을 둘 것
기존 코드가 합리적인 범위 안에서 이 기준을 맞출 수 없다고 판단되면, 그건 구조가 아니라 아카이브 신호에 가깝다.
이 원칙을 지키면, 기능 캐비닛은 미래의 두통 거리 더미가 아니라 레버리지가 높은 작업의 보고가 된다.
정리: 모두 합쳐 보면
건강한 반쯤 만든 기능 캐비닛은 다음과 같은 모습이다.
- 보이는 리스트: 모든 미완성 작업이 한 곳에 모여 있는 단일 목록
- 간단한 템플릿: 각 항목에 완료·미완성 부분, 기술 스택, 리스크가 정리돼 있음
- 구조 작업 단위: 큰·모호한 작업이 작고 명확한 티켓 단위로 쪼개져 있음
- 효과 기반 우선순위: 죄책감이 아니라 가치와 노력, 리스크 기준으로 구조 대상을 고름
- 명시적인 규칙: 무엇을 구조하고 무엇을 버릴지에 대한 명확한 기준이 있음
- 계획된 시간: “시간 나면”이 아니라, 스프린트 용량 안에 구조 작업이 예산으로 반영됨
- 품질 기준: 구조된 작업은 유지보수 가능성에 대한 최소 기준을 충족해야 함
이렇게 운영하면, 반쯤 만든 기능들은 조용히 팀을 갉아먹는 부담이 아니라 가치 있는 기회가 잠재된 구조 가능한 백로그로 바뀐다. 쓸 만한 작업을 굳이 버리지 않고, 보이지 않는 인지 부하를 줄이며, 팀은 시작과 중단을 모두 더 건강하게 다루는 습관을 갖게 된다.
코드베이스에는 언제나 미완성 스레드가 조금씩 존재할 것이다. 목표는 그것들을 전부 없애는 게 아니다. 의식적으로 관리하는 것이다. 기능 캐비닛은 바로 그걸 가능하게 해 준다. 조용하고, 눈에 잘 보이며, 실용적인 방식으로 “무엇에 두 번째 기회를 줄지, 무엇을 이제 놓아줄지”를 결정할 수 있게 해 주는 도구다.