기술 부채는 "나중에 고치자"는 말로 쌓이고, 숫자가 없으면 끝까지 갚지 못한다. 애플리케이션 아키텍트(AA)가 할 일은 부채를 없애는 것이 아니라 보이게 만들고, 이자가 큰 것부터 갚을 순서와 예산을 확보하는 것이다. 이 글은 부채를 분류하고 대장에 올리는 법, 우선순위를 정하는 기준, 그리고 구조·흐름·코드 세 층의 품질 지표를 정리한 것이다.

한눈에 보기
| 단계 | 할 일 | 남길 것 |
|---|---|---|
| 찾기 | 코드 분석, 개발자 인터뷰, 장애·변경 이력 검토 | 부채 후보 목록 |
| 기록 | 원인, 이자, 상환 비용, 담당을 적는다 | 기술 부채 대장 |
| 순서 | 이자 × 변경 빈도로 줄 세운다 | 상환 우선순위 |
| 측정 | 구조·흐름·코드 지표를 정기적으로 뽑는다 | 품질 지표 추이 |
| 상환 | 스프린트마다 고정 비율을 쓴다 | 상환 결과와 지표 변화 |
다섯 단계는 한 번으로 끝나지 않는다. 상환하고 나면 다시 측정하고, 새로 생긴 부채를 대장에 올린다.
기술 부채는 빌린 시간이다
이 말은 워드 커닝햄(Ward Cunningham)이 1992년 OOPSLA 경험 보고에서 쓴 비유다. 충분히 이해하지 못한 채 코드를 내보내는 것은 돈을 빌리는 것과 같아서, 빨리 갈 수 있지만 고치지 않으면 이자가 붙는다는 뜻이다.
AA에게 쓸모 있는 부분은 이자라는 개념이다.
- 원금: 지금 고치는 데 드는 비용. 예: 순환 의존을 끊는 데 3일.
- 이자: 고치지 않아서 매번 더 드는 비용. 예: 그 모듈을 건드릴 때마다 영향 분석과 회귀 테스트에 반나절.
- 이자는 그 코드를 바꿀 때만 낸다. 아무도 건드리지 않는 낡은 코드는 보기 싫어도 이자가 거의 없다.
부채와 버그는 다르다. 버그는 지금 틀린 동작이고, 부채는 지금은 맞게 동작하지만 바꾸기 비싼 구조다. 둘을 한 목록에 섞으면 버그가 늘 먼저 처리되고 부채는 밀린다.
부채의 네 종류: Fowler 사분면
마틴 파울러(Martin Fowler)는 부채를 "알고 졌는가(의도적/비의도적)"와 "판단이 신중했는가(신중/무모)"로 나눴다.
| 의도적 | 비의도적 | |
|---|---|---|
| 무모 | "설계할 시간 없다" | "레이어가 뭔데?" |
| 신중 | "지금 출시하고, 결과는 감수한다" | "이제야 어떻게 했어야 했는지 안다" |
이 구분은 탓하려는 것이 아니라 대응을 고르려는 것이다.
- 신중·의도적: 일정 때문에 고른 지름길이다. 지는 순간 ADR에 "언제, 어떤 조건에서 갚는다"를 같이 적는다.
- 무모·의도적: 표준과 리뷰로 막는다. 대장보다 개발 표준과 코드 리뷰 규칙의 문제다.
- 무모·비의도적: 교육과 샘플 코드로 막는다. 같은 실수가 여러 모듈에서 반복되는 것이 신호다.
- 신중·비의도적: 피할 수 없다. 도메인을 이해할수록 생긴다. 발견하면 대장에 올린다.
기술 부채 대장을 만든다
말로만 도는 부채는 우선순위 회의에서 항상 진다. 위험 목록처럼 한 줄에 한 건씩 적는다.
- id: TD-014
항목: 주문 모듈과 정산 모듈의 순환 의존
종류: 신중·비의도적
원인: 정산 요구사항이 개발 중반에 주문 화면에 붙음
이자: 주문 변경마다 정산 회귀 테스트 필요, 수정 1회당 약 4시간 추가 (예시)
변경 빈도: 최근 6개월 커밋 38회 (예시)
상환 비용: 이벤트로 분리, 약 5일 (예시)
상환 조건: 2차 오픈 전, 정산 개편 착수 시
담당: 주문 파트 리더
등록일: 2026-10-15
상태: 대기
- 이자는 "복잡하다"가 아니라 시간이나 횟수로 적는다. 숫자가 없으면 발주처를 설득할 수 없다.
- 상환 조건을 적는다. 기한만 적으면 계속 미뤄지고, "정산 개편 착수 시"처럼 사건에 묶으면 그때 같이 처리된다.
- 대장은 이슈 관리 도구에
기술부채라벨로 둬도 된다. 중요한 것은 한 곳에 모여 있고 담당이 있는 것이다.
이자 × 변경 빈도로 순서를 정한다
모든 부채를 갚을 예산은 없다. 순서는 두 축으로 정한다. 가로는 그 코드가 얼마나 자주 바뀌는가, 세로는 바뀔 때마다 얼마나 더 드는가다.

변경 빈도는 git 이력에서 바로 뽑을 수 있다.
# 최근 6개월 동안 가장 자주 바뀐 파일 20개
git log --since="6 months ago" --name-only --format= \
| grep '\.java$' | sort | uniq -c | sort -rn | head -20
이 목록과 복잡도(SonarQube의 인지 복잡도 등)를 겹쳐서 둘 다 높은 파일을 찾는다. 애덤 톤힐(Adam Tornhill)이 핫스팟이라고 부른 방식이다. 복잡하지만 1년 동안 아무도 안 건드린 파일은 고쳐도 돌아오는 것이 적다. 반대로 자주 바뀌는데 복잡한 파일은 매주 이자를 낸다.
품질 지표 1: 구조
구조 지표는 "설계한 대로 지어지고 있는가"를 본다.
순환 의존
모듈 A가 B를 부르고 B가 다시 A를 부르면 둘은 따로 바꿀 수도, 따로 배포할 수도 없다. 개수를 세고 0을 목표로 둔다.
@ArchTest
static final ArchRule noCycles =
slices().matching("kr.example.app.(*)..").should().beFreeOfCycles();
// 이미 있는 위반은 기록해 두고 새 위반만 실패시킨다
@ArchTest
static final ArchRule noNewCycles = FreezingArchRule.freeze(noCycles);
FreezingArchRule은 부채 관리에 맞는 도구다. 기존 위반을 한 번에 다 고칠 수 없을 때 지금 상태를 기준선으로 얼리고, 위반이 늘어나는 것만 막는다. 위반 수가 줄어드는 추이가 곧 상환 실적이 된다.
레이어 위반
Controller가 Repository를 직접 부르는 식의 위반 건수다. 규칙을 ArchUnit 테스트로 만드는 방법은 감리 증적 자동 수집 글에 예시가 있다.
모듈 결합도
로버트 마틴(Robert C. Martin)의 지표를 쓰면 숫자로 비교할 수 있다. 들어오는 의존 수(Ca), 나가는 의존 수(Ce), 불안정성 I = Ce / (Ca + Ce)다. 공통 모듈처럼 많은 곳이 기대는 모듈은 I가 0에 가까워야 한다. 공통 모듈의 I가 높다면 자주 바뀌는 코드에 모두가 기대고 있다는 뜻이다.
품질 지표 2: 흐름과 코드
흐름: DORA 네 지표
구조가 나빠지면 결국 변경이 느려지고 자주 깨진다. DORA 연구의 네 지표가 이것을 잰다.
| 지표 | 무엇을 재나 |
|---|---|
| 배포 빈도 | 운영에 얼마나 자주 배포하나 |
| 변경 리드 타임 | 커밋에서 운영 반영까지 걸리는 시간 |
| 변경 실패율 | 배포 중 장애·롤백·긴급 수정으로 이어진 비율 |
| 서비스 복구 시간 | 장애에서 정상으로 돌아오는 시간 (최근 보고서는 '실패한 배포 복구 시간'으로 부른다) |
앞의 둘은 속도, 뒤의 둘은 안정성이다. 한쪽만 보면 안 된다. 공공 SI처럼 배포 주기가 정해진 환경에서는 배포 빈도보다 리드 타임과 변경 실패율이 부채의 영향을 더 잘 보여 준다.
코드: SonarQube
- 기술 부채 비율: 고치는 데 드는 추정 시간을 코드를 새로 짜는 추정 시간으로 나눈 값이다.
- 유지보수성 등급: 부채 비율로 A~E를 매긴다. 기본 설정에서 A는 5% 이하다.
- 중복률: 중복된 줄의 비율. 중복은 한 곳만 고치고 다른 곳을 놓치는 버그를 만든다.
- 인지 복잡도: 사람이 읽기 어려운 정도. 메서드별로 기준값(기본 15)을 넘는 곳을 찾는다.
절대값보다 새 코드 기준을 먼저 건다. 전체 등급을 갑자기 A로 올릴 수는 없지만, 이번 스프린트에 바뀐 코드가 기준을 넘지 않게 하는 것은 바로 할 수 있다.
PM과 발주처에 보고하고 예산을 받는다
부채 보고는 기술 용어가 아니라 비용과 위험으로 한다.
| 보고 항목 | 누가 보나 | 없으면 생기는 일 |
|---|---|---|
| 상위 5개 부채와 이자(시간) | PM, 발주처 | "리팩터링하고 싶다"는 요청이 일정 핑계로 들림 |
| 핫스팟 목록 | 파트 리더 | 고쳐도 효과 없는 곳에 시간을 씀 |
| 순환 의존·레이어 위반 추이 | AA, 감리 | 설계 이탈이 누적돼도 아무도 모름 |
| 리드 타임·변경 실패율 추이 | PM | 개발 속도가 왜 떨어지는지 설명 못 함 |
상환 예산은 스프린트마다 고정 비율로 받는 방식이 운영하기 쉽다. 많은 팀이 용량의 일부(예: 10~20%)를 떼어 둔다. 비율은 팀이 정하지만, 고정해 두면 매번 협상하지 않아도 되고 일정이 급할 때 0이 되는 것을 막는다. 큰 부채(대규모 분리, 프레임워크 교체)는 비율 예산으로 안 끝나므로 별도 과업으로 계획서에 올린다. 이것이 아키텍처 문서인지 관리 문서인지는 산출물 구분 글의 기준을 따른다.
자주 하는 실수
- 부채를 버그 목록에 섞는다. 버그가 늘 급하므로 부채는 영원히 순번이 오지 않는다.
- 이자를 형용사로 적는다. "유지보수가 어렵다"로는 예산을 받을 수 없다. 수정 1회당 몇 시간인지 적는다.
- 안 바뀌는 코드부터 고친다. 보기 싫은 코드와 비싼 코드는 다르다. 변경 빈도를 먼저 본다.
- 전체 지표를 한 번에 올리려 한다. 기존 위반은 얼리고(
FreezingArchRule, 새 코드 기준) 늘어나는 것만 막는다. - 상환 결과를 측정하지 않는다. 갚은 뒤 리드 타임이나 위반 수가 줄었는지 보여 주지 못하면 다음 예산이 없다.
점검표
- 부채가 버그와 다른 목록(또는 라벨)으로 관리된다
- 대장의 모든 항목에 이자, 상환 비용, 담당이 있다
- 의도적으로 진 부채는 ADR에 상환 조건이 적혀 있다
- 최근 6개월 변경 빈도와 복잡도를 겹친 핫스팟 목록이 있다
- 순환 의존 금지 규칙이 테스트로 돌고, 기존 위반은 기준선으로 얼려 있다
- 레이어 위반 건수가 빌드마다 집계된다
- 변경 리드 타임과 변경 실패율을 월 단위로 볼 수 있다
- SonarQube 품질 게이트가 새 코드 기준으로 걸려 있다
- 스프린트마다 상환 비율이 정해져 있고 실제 사용량을 기록한다
- 상위 부채와 지표 추이를 PM·발주처 보고에 넣고 있다
기술 부채 관리는 깨끗한 코드를 고집하는 일이 아니라, 무엇에 이자를 내고 있는지 숫자로 보여 주고 가장 비싼 것부터 갚을 시간을 확보하는 일이다.
댓글 0개
아직 댓글이 없습니다. 첫 댓글을 남겨보세요.