마감을 맞추려 일부러 단순하게 만들고 나중에 개선하기로 한 것. 문제가 아니라 선택입니다. 다만 갚을 계획을 함께 기록해야 부채로 관리됩니다.
이 파트에서 다루는 내용
기술 부채는 나쁜 코드가 아니라 미룬 비용입니다
기술 부채를 그냥 못 짠 코드로 이해하면 판단이 흐려집니다. 부채는 지금의 속도를 위해 나중의 비용을 빌려 온 상태입니다. 금융 부채처럼, 잘 쓰면 도움이 되고 방치하면 이자가 불어납니다.
빠르게 출시하려고 의도적으로 대충 만든 것도 부채이고, 당시엔 최선이었지만 요구가 바뀌어 안 맞게 된 것도 부채입니다. 전자는 계획된 빚, 후자는 시간이 만든 빚입니다.
요구가 바뀌고 기능이 붙으면서 구조가 안 맞게 된 것. 누구의 잘못도 아니고 자연스러운 현상입니다. 주기적으로 정리하지 않으면 쌓입니다.
부채가 있는 코드는 손댈 때마다 더 오래 걸리고 버그가 잦습니다. 이 이자가 커지면 새 기능 하나 넣는 데도 며칠이 걸립니다.
모든 부채를 갚을 필요는 없습니다
부채를 발견할 때마다 다 고치려 하면 정작 할 일을 못 합니다. 부채도 우선순위로 판단합니다. 기준은 두 가지입니다. 얼마나 자주 건드리는가, 그리고 틀리면 얼마나 위험한가.
매번 수정하는 핵심 코드의 부채는 이자가 큽니다. 여기를 정리하면 이후 모든 작업이 빨라집니다. 우선 상환 대상입니다.
몇 년째 안 바뀌고 잘 도는 코드는 지저분해도 굳이 건드리지 않습니다. 동작하는 것을 위험을 무릅쓰고 고칠 이유가 없습니다.
금액·권한·데이터를 다루는데 부채가 있으면 위험합니다. 자주 안 건드려도 틀렸을 때 피해가 크면 정리 대상입니다.
빈도 × 위험으로 봅니다. 자주 만지고 위험한 곳이 최우선, 안 만지고 안전한 곳은 후순위입니다. 감정이 아니라 이 두 축으로 정합니다.
리팩터링은 동작을 바꾸지 않는다는 약속입니다
리팩터링의 정의는 겉보기 동작을 그대로 두고 내부 구조만 개선하는 것입니다. 기능 추가나 버그 수정과 섞으면 안 됩니다. 섞이는 순간 무엇이 문제를 일으켰는지 알 수 없게 됩니다.
그래서 안전한 리팩터링에는 전제가 있습니다. 동작이 그대로인지 확인할 수단, 즉 테스트입니다.
리팩터링 전에 현재 동작을 테스트로 고정합니다. 그래야 구조를 바꿔도 동작이 같은지 확인됩니다. 테스트 없는 리팩터링은 개선이 아니라 도박입니다.
큰 리팩터링을 한 번에 올리면 리뷰도 롤백도 어렵습니다. 작은 단위로 나눠 각각 동작을 확인하며 진행합니다.
리팩터링 PR과 기능 PR을 나눕니다. 섞이면 리뷰어가 무엇이 구조 변경이고 무엇이 동작 변경인지 구분할 수 없습니다.
이름 변경, 메서드 추출 같은 정형화된 리팩터링은 IDE 기능을 씁니다. 손으로 바꾸는 것보다 안전합니다. IDE 코스에서 다룬 내용입니다.
부채 상환은 팀을 설득해야 시작됩니다
리팩터링은 대개 눈에 보이는 새 기능을 만들지 않습니다. 그래서 이거 왜 하냐는 질문을 받습니다. 부채 상환을 하려면 그 가치를 비개발자도 이해할 언어로 설명할 수 있어야 합니다.
코드가 지저분해요가 아니라, 이 부분 때문에 비슷한 기능마다 이틀씩 더 걸립니다처럼 시간과 비용으로 말합니다. 리드와 기획이 판단할 수 있는 언어입니다.
따로 시간을 받기 어려우면, 관련 기능을 작업할 때 그 주변을 조금씩 정리합니다. 보이스카우트 규칙, 만진 곳을 조금 더 깨끗이 두고 나오는 방식입니다.
전면 재작성은 대개 실패합니다. 오래 걸리고, 기존 기능을 놓치고, 그동안 새 요구를 못 따라갑니다. 점진적 개선이 거의 항상 낫습니다.
발견한 부채를 그때그때 이슈로 남깁니다. 머릿속에만 있으면 관리되지 않습니다. Part 6의 문서, Part 5의 진행 공유와 이어집니다.
기술 부채는 죄가 아니라 관리 대상입니다. 빈도와 위험으로 우선순위를 정하고, 테스트로 안전망을 깐 뒤 작게 리팩터링하고, 가치를 비용의 언어로 설명합니다. 부채를 감정적으로 대하지 않고 비용으로 판단하는 것이 미들 개발자의 성숙함입니다.