기술 부채란 무엇인가: 솔로 빌더 실전 가이드
요약
기술 부채는 빠른 출시를 위한 지름길의 누적 비용이다. 솔로 빌더는 팀보다 빠르게 부채가 쌓이지만, 네 가지 유형을 이해하고 작은 단계로 지속적으로 관리하면 개발을 멈추지 않고 줄일 수 있다.
기술 부채란 무엇인가? 더 빠르게 출시하기 위해 선택한 모든 지름길의 누적 비용이다. Ward Cunningham이 1992년 재정적 부채의 비유로 만들어낸 이 개념은 단순한 나쁜 코드와는 다르다. 의도가 있기 때문이다. 단기적인 속도와 장기적인 유지보수성 사이의 절충으로, 의식적이든 무의식적이든 발생한다.
파일에 TODO 주석을 남긴 적 있는가. 금요일까지 출시해야 해서 값을 하드코딩한 적이 있는가. 공유 모듈을 추출하는 대신 함수를 복사한 적이 있는가. 그렇다면 기술 부채를 진 것이다. 대부분의 사이드 프로젝트는 기술 부채 위에 지어지고, 대부분의 솔로 개발자는 자신이 생각하는 것보다 더 많은 부채를 지고 있다.
솔로 빌더가 팀보다 빠르게 부채를 쌓는 이유
팀에는 마찰이 내재되어 있다. 코드 리뷰, 아키텍처 논의, 표준 문서. 이것들은 속도를 늦추지만 부채 축적도 함께 늦춘다. 솔로 개발자에게는 그런 마찰이 없다. 모든 절충을 스스로 결정한다. 밤 11시에, 그냥 결과를 보고 싶을 때.
결과는 시간 압박 속에서 이루어진 모든 타협을 반영하는 코드베이스다. 이것은 성격적 결함이 아니다. 혼자 빌드하는 것의 구조적 현실이다. 문제는 부채가 복리로 불어난다는 점이다. 하드코딩된 API 키 하나는 한 시간짜리 수정이다. 같은 패턴이 여섯 개 파일에 걸쳐 스무 개로 퍼지면, 수정을 시작하기 전에 하루 종일 발굴 작업을 해야 한다.
더 미묘한 형태의 축적도 있다. 프로젝트가 작을 때 내린 결정에서 비롯된 아키텍처 부채는, 프로젝트가 실제 견인력을 얻으면 유지되지 않는다. JSON 파일을 데이터베이스로 사용하는 것은 사용자가 없을 때는 괜찮다. 사용자가 500명이 되면 문제다. 타이베이에 사는 본업과 병행해 사이드 프로젝트를 운영하는 개발자들이 이것을 끊임없이 겪는다. 출시 속도에 최적화하고, 부채를 흡수하고, 나중에 재협상한다. 나중이 오면.
실제로 중요한 기술 부채의 네 가지 유형
모든 부채가 동등하지 않다. 사이드 프로젝트에 특화된 실용적인 분류다.
코드 부채가 가장 흔하다. 코드 자체의 지름길을 포괄한다. 중복된 로직, 너무 많은 일을 하는 함수, 6개월이 지나도 여전히 남아 있는 temp2라는 이름의 변수. 기능을 추가할 때마다 기존 코드가 무엇을 하는지 파악하는 데 30분을 써야만 변경을 시작할 수 있는 부채다.
문서화 부채는 솔로 빌더들이 과소평가한다. 혼란을 줄 다른 사람이 없기 때문이다. 그러다 3주 동안 프로젝트를 떠났다가 돌아와서 왜 그 방식으로 API를 만들었는지 파악하는 데 4시간을 보낸다. 두 달 전 자신의 선택에 스스로가 혼란스러워진다. 맥락을 기억할 것이라는 가정은 거의 항상 틀린다.
보안 부채는 입력 유효성 검사를 건너뛰거나, 개발 중 관리자 경로를 보호하지 않은 채 잊어버리거나, 6버전 전에 패치된 심각한 취약점이 있는 라이브러리를 계속 실행할 때 쌓인다. 사이드 프로젝트에서는 보통 실제 사용자가 생기기 직전까지 위험이 낮아 보인다. 그때는 더 이상 이론적인 문제가 아니다.
도구 부채는 빌더들이 가장 적게 논의하는 종류다. 배포 파이프라인 없음. 수동 릴리즈 단계. 문서화된 형식 없이 노트북에만 존재하는 .env 파일. 프로덕션에서 무언가가 고장나면, 이 부채가 30분 수정을 세 시간짜리 복구 작업으로 만든다. 그 과정에서 배포 방식에 대한 맥락도 다시 재구축해야 한다.

부채를 지는 것이 올바른 선택일 때
엔터프라이즈 소프트웨어 문헌이 틀린 부분이 있다. 부채를 일률적으로 나쁜 것으로 취급한다. 솔로 빌더나 인디 해커에게 어떤 부채는 올바른 결정이다.
2주 안에 검증하고 싶은 사이드 프로젝트가 있다고 하자. 사용자가 있는지 알기도 전에 전체 테스트 스위트를 작성하는 것은 엔지니어링 규율이 아니다. 그럴듯한 이름을 단 미루기다. 사용자가 없을 때 테스트를 건너뛰고 유료 고객이 10명 생기면 추가하는 것은 의도적이고 합리적인 절충이다. Ward Cunningham 자신이 이것을 신중하고 의도적인 부채라고 불렀다. 부채를 지고 있다는 것을 알고, 결과를 이해하고, 갚을 계획을 세운다.
문제는 빌더들이 부채를 인식하지 못하고 지거나, 의도적으로 지면서도 상환 계획을 세우지 않을 때다. 계획 없는 부채는 그냥 엔트로피다.
실제로 작동하는 규칙이 있다. 부채는 경계가 있을 때 괜찮다. 하드코딩된 설정값 하나는 관리 가능하다. 같은 패턴이 30개의 다른 파일에 적용되면, 자신을 포함해 누구도 작업할 수 없는 코드베이스가 된다. 실제로 막히는 부분은 대부분의 솔로 빌더가 부채를 추적하지 않는다는 것이다. 막연한 불편함으로 머릿속 한켠에 존재할 뿐이다. 그것이 진짜 문제다. 부채 자체가 아니라, 부채가 실제로 무엇인지와 수정하는 데 얼마나 걸릴지에 대한 가시성 부재가.
비용이 발생하기 전에 부채를 파악하는 방법
가장 저렴한 부채 관리 형태는 부채를 가시화하는 것이다. 복잡한 프로세스가 필요 없다. 레포 루트에 간단한 DEBT.md 파일을 만들고 절충을 할 때마다 기록하면 된다. 항목당 30초가 걸리고 나중에 재발견하는 수시간을 절약한다.
일반적인 항목은 다음과 같이 생길 수 있다.
## [2026-08-03] api/users.ts에 하드코딩된 DB 연결 문자열
이유: 금요일 데모 출시가 필요했음.
비용: 환경별로 다르며, 다른 사람이 로컬에서 실행하려 하면 실패.
수정: dotenv로 환경 변수로 이동. 예상 20분.
우선순위: 높음, 협업자 합류 전에.형식은 중요하지 않다. 작성하는 행위가 중요하다. 절충을 코드에 조용히 스며들게 두는 대신, 명시적으로 표현하게 만들기 때문이다.
정적 분석 도구는 자동으로 다른 버전의 이 작업을 한다. SonarQube나 CodeClimate 같은 도구는 코드베이스를 스캔하고 코드 냄새, 중복, 보안 핫스팟, 복잡도 점수를 표시한다. 자신이 인식하지 못한 채 만들어낸 부채를 잡는 데 더 유용하다. 12번 연속으로 스스로 적용하고 있다는 것을 인식하지 못한 패턴에서 비롯된 의도치 않은 종류의 부채를.
CodeScene은 커밋 이력을 분석해 함께 변경되는 파일과 시간 압박 하에 반복적으로 수정되는 핫스팟을 식별한다. 솔로 프로젝트의 경우, 이런 신호는 정적 스냅샷보다 실행 가능성이 더 높다. 지금 코드가 나빠 보이는 곳이 아니라, 반복적으로 타협했던 곳을 보여주기 때문이다.
개발을 멈추지 않고 부채를 갚는 세 가지 방법
실수는 다음 달에 예정하고 결코 실행하지 않는 전용 스프린트로 부채 상환을 처리하는 것이다. 올바른 접근 방식은 정상적인 흐름에 내장된 소량으로 지속적으로 갚는 것이다.
코드에 적용하는 보이스카우트 규칙: 편집하는 파일을 찾았을 때보다 약간 더 좋게 만들어 놓는다. 이미 코드 안에 있는 동안 혼란스러운 변수 이름을 바꾼다. 이미 수정하는 동안 중복된 로직을 함수로 추출한다. 이것은 세션당 5분에서 15분이 걸리고 수개월간 일관된 작업을 통해 상당히 복리로 쌓인다.
활성 개발 중 부채 예산 배분: 새 기능을 만들고 있다면, 시간의 20%를 인접 코드의 부채 수정에 할당한다. 코드베이스의 먼 부분에서 발견한 부채가 아니다. 지금 당장 만들고 있는 것에 직접 닿는 부채를 수정한다. 이는 새 기능이 그 위에 쌓이기 때문에 기존 부채를 더 악화시키는 일반적인 패턴을 방지한다.
폭발 반경에 의한 우선순위 선별: 모든 부채가 동등한 주의를 받을 가치는 없다. 매주 수정하는 코드의 부채는 4개월 동안 열지 않은 모듈의 부채보다 중요하다. 무엇을 해결할지 결정할 때 물어보라. 이것이 고장나거나 변경되어야 한다면, 얼마나 많은 다른 것들이 영향을 받는가? 높은 폭발 반경은 높은 우선순위다. 거의 방문하지 않는 구석에 있는 낮은 폭발 반경의 부채는 그곳에 있어도 된다.
3대1 규칙이 활성 개발에 효과적이다. 새 기능을 만드는 세 번의 세션마다 부채 상환에 한 번의 세션을 보낸다. 이렇게 하면 진행을 중단하지 않고 비율이 통제 불능이 되는 것을 막는다.

현재 부채 수준이 말해주는 것
프로젝트 6개월차에 코드베이스의 부채 분포는 압박 속에서 내린 결정의 상당히 정확한 지도다. 인증 모듈의 높은 부채는 그것을 만들 때 서둘렀다는 뜻이다. API 레이어의 방대한 중복은 기능을 빠르게 검증하고 통합을 위해 멈추지 않았다는 뜻이다. 특정 파일의 고밀도 복잡도는 보통 아키텍처가 불명확할 때 해당 파일이 쓰레기장이 되었다는 것을 의미한다.
이것은 진정으로 유용한 정보다. 자신감 있게 만들어진 코드베이스의 부분과 불확실성 속에서 만들어진 부분을 보여준다. 불확실성 속에서 만들어진 부분은 결과적으로 중요하지 않은 부분인 경우도 많다. 빠르게 검증하고 우선순위를 낮춘 기능들. 거기서 쌓인 부채는 그 경로가 어디로도 이어지지 않기 때문에 갚을 필요가 없을 수도 있다.
중요했던 부분들, 즉 핵심 사용자 흐름, 데이터 모델, API 계약, 인증, 이것들이 부채 상환이 실제로 효과를 내는 곳이다. 모든 곳에서 완벽한 코드를 작성하려는 것이 아니다. 하중을 지지하는 벽이 어디인지 파악하고 그것을 깨끗하게 유지하는 것이다.
코드베이스가 기능을 추가하는 것이 새 코드를 작성하는 것보다 기존 동작을 디버깅하는 데 더 많은 시간이 걸리는 지점에 도달했다면, 그것이 신호다. 모든 것을 멈추고 리라이트하라는 신호가 아니다. 속도 저하를 일으키는 특정 모듈에서 3주에서 4주 동안 목표 부채 감소에 전념하라는 신호다. 리라이트는 생각보다 두 배나 걸린다고 추정된다.
리라이트할 것인가, 리팩터링할 것인가?
부채가 관리할 수 없다고 느껴질 때 솔로 빌더들이 직면하는 질문이다. 답은 거의 항상 리라이트가 아니라 리팩터링이다.
리라이트는 실제로 걸리는 시간의 절반 정도라고 추정된다. 또한 기존 코드에 내재된 축적된 지식을 잃는다. 처리된 엣지 케이스, 수정된 버그, 어렵게 발견한 서드파티 API 특이점의 우회 방법. 원래 부채를 두 번 지불한다. 한 번은 그것을 갖고 있을 때, 또 한 번은 리빌드하면서 모든 것을 재발견할 때.
리팩터링은 목표를 명확히 할 때 효과가 있다. 가장 구체적인 고통을 일으키는 모듈을 선택한다. 변경하기 가장 느리고, 버그가 가장 많이 발생하고, 이해하기 가장 어려운 것. 무엇을 하는지 완전히 파악하기 전에는 변경하지 않는다. 인접한 동작을 깨뜨리지 않고 안전하게 리팩터링할 수 있도록 경계 주변에 테스트를 추가한다. 에너지가 소진되면 반쯤 완성된 상태로 남기는 하나의 긴 영웅적 스프린트가 아니라, 여러 세션에 걸쳐 점진적으로 변경한다.
리팩터링할 세 가지 이유, 하지 않을 한 가지 이유. 코드베이스에서 트래픽이 많은 영역에 부채가 있을 때, 그 위에 무언가를 만들려고 할 때, 또는 실제 버그를 일으키고 있을 때 리팩터링한다. 모듈이 안정적이고, 거의 변경되지 않으며, 부채가 자체적으로 포함되어 있을 때는 건너뛴다. 기술 부채 관리의 지속 가능한 버전은 부채 제로가 아니다. 이해하고, 표현할 수 있고, 적극적으로 갖고 있거나 갚기로 결정하는 부채다. 그 명확성이 실제 목표다.