콘텐츠로 바로가기

Maintenance & Tech Debt

1. **Stage 1: Fundamentals (Weight: 1)** * Maintenance Types and Software Evolution Laws. 2. **Stage 2: Quantification (Weight: 2)** * Tech Debt Me...

Article
M

Me

hyunyoun's Blog

software-engineering-devopssoftware-engineeringdev-opsmaintenancetech-debtreliabilityobservabilitytechnical-debt10 min read

1. Overview

유지보수 및 기술 부채(Maintenance & Tech Debt, MTD)는 세상에 배포되어 작동하기 시작한 소프트웨어가 세월과 비즈니스 변화에 부딪혀 어떻게 서서히 늙어가고, 부패하며, 다시 현대화(Modernization)되는지를 다루는 공학적 생명 연장의 학문입니다.

출시된 소프트웨어는 버려진 자동차처럼 썩어가는 것이 아니라(Software Aging), 매일매일 들어오는 요구사항 수정 때문에 스파게티처럼 엉키며 망가집니다. 학습자는 이 지연 비용을 워드 커닝햄의 **기술 부채(Technical Debt)**라는 위대한 메타포로 이해합니다. "일단 굴러가게" 짠 코드가 어떻게 이자를 불려 결국 개발 속도를 0으로 수렴하게 만드는지 그 파산 과정을 정량적으로 분석하고, 코드 스멜(Code Smell)을 제거하는 리팩토링과 교살자 무화과(Strangler Fig) 패턴을 통해 거대한 레거시 시스템의 심장을 멈추지 않고 수술하는 아키텍트의 수리 역학을 갖춥니다.

2. Scope & Boundaries

In-Scope

  • 소프트웨어 진화의 법칙 (Software Evolution): 리먼의 법칙(Lehman's Laws), 유지보수의 4대 유형(교정적, 적응적, 완전화, 예방적).
  • 기술 부채의 정량화 (Technical Debt): 무지한 부채 vs 신중한 부채, 기술 부채 비율(Technical Debt Ratio, TDR) 및 이자(Cost of Delay) 측정 물리.
  • 리팩토링 메커니즘 (Refactoring Mechanics): 코드 스멜(Code Smell) 감지, 구조는 개선하되 외부 동작은 유지하는 릴레이 테스트 기법.
  • 레거시 현대화 (Legacy Modernization): 리플랫포밍(Replatforming), API 래핑(Wrapping), Strangler Fig Pattern을 이용한 점진적 마이그레이션.

Out-of-Scope

  • 새로운 언어의 문법 최적화 공부: Python 2를 Python 3로 올리는 단순 문법 변환 \rightarrow 05-02. FPL 영역으로 위임.
  • 기존 인프라를 클라우드로 통째로 옮기기 (Lift and Shift): 애플리케이션 코드는 건드리지 않고 AWS VM으로만 옮기는 작업 \rightarrow 09-05. DevOps 영역으로 위임.

Boundaries

  • MTD vs. QA (09-04): QA(09-04)가 '코드가 버그 없이 명세대로 동작하는가'를 확인하는 것이라면, MTD는 동작은 멀쩡히 잘 되더라도 '코드가 너무 지저분해서 다음 주에 새 기능을 넣을 때 회사가 망할 확률이 얼마인가'를 측정하는 내부 구조의 경제학입니다.

3. Counterexample

  • "버그 수정이 곧 유지보수"라는 오해 (Maintenance Fallacy): 유지보수 기간을 단순히 고객이 찾아낸 에러를 고치는(Corrective) 기간으로만 생각하는 주니어의 시각. 실제 소프트웨어 유지보수 예산의 70% 이상은 에러 수정이 아니라, 운영체제나 브라우저가 업그레이드되어서 코드를 맞추거나(적응적), 속도를 개선하고 코드를 예쁘게 가다듬는 작업(완전화, 예방적)에 쓰입니다. 유지보수는 '에러 처리'가 아니라 '환경에 대한 진화'입니다.
  • 기능 개발 멈추고 한 달간 리팩토링만 하기 (Big Bang Refactoring Fallacy): 기술 부채가 쌓였다고 기획팀에게 "이번 달은 새 기능 출시 못 합니다. 코드 좀 뜯어고칠게요"라고 선언하는 행위. 이는 비즈니스와 엔지니어링의 타협점을 무시한 폭력입니다. 진정한 리팩토링 역학은 보이스카우트 규칙(Boy Scout Rule: 떠날 때는 머물 때보다 더 깨끗하게)을 적용하여, 새 기능을 짤 때 그 기능과 맞닿은 10%의 코드만 매일매일 조금씩 개선하는 점진적 상환(Repayment)의 원리를 따릅니다.

4. Prerequisites

  • 아키텍처 및 설계 기초 (Basic): 코드가 어떻게 꼬여 있는지(강결합) 알려면 SOLID 원칙과 아키텍처 패턴의 기초를 알아야 합니다. (09-03. SAD)
  • 테스트 자동화 (Recommended): 리팩토링 중 기존 기능이 깨지지 않았는지 1초 만에 확인해 줄 단위 테스트 파이프라인이 없으면 수술(리팩토링) 자체가 불가능합니다. (09-04. TQA)

5. Learning Map

Sequence Core Cluster Objective & Description Evidence (BoK)
1 Evolution Laws 배포된 소프트웨어는 생물과 같아서, 지속해서 환경에 맞춰 수정해주지 않으면 쇠퇴한다는 진화의 법칙을 깨우칩니다. P2
2 Quantification 감으로 "코드 더러워요"라고 말하는 대신, 정적 분석 도구를 이용해 기술 부채를 숫자로(TDR) 계산하여 보고서에 올립니다. P2
3 Refactoring Tactics 냄새나는 코드(Code Smell)의 패턴을 감별하고, 기능은 1%도 훼손하지 않으면서 내부 구조만 갈아엎는 메스를 듭니다. Industry
4 Legacy Modernization 도무지 손댈 수 없는 거대한 구시대의 괴물(Legacy)을, 점진적으로 질식시켜 새 시스템으로 이관하는 거시적 전략을 배웁니다. Industry

6. Learning Topics

Basic

Core Topic 01: 소프트웨어 진화와 유지보수 유형 (Software Evolution)

  • Why to Learn: 프로그램은 완성되는 순간 죽어가는 역설을 인지하고, 배포 이후에 더 많은 공학적 노력(비용의 60% 이상)이 들어감을 계획하기 위함입니다.
  • What to Learn:
    • Concepts: 리먼(Lehman)의 소프트웨어 진화 법칙 (계속적 변경, 복잡도 증가 등).
    • Skills: 4대 유지보수 유형 분별 (Corrective-수정형, Adaptive-적응형, Perfective-완전형, Preventive-예방형).
    • Tools: 이슈 트래커 (이슈 레이블링).
    • Trade-offs: 요구사항 변경을 적극 수용하는 유연한 태도 vs 잦은 변경으로 인해 시스템 전체의 구조적 무결성(Structural Integrity)이 서서히 붕괴하는 엔트로피 증가 현상.
  • How to Learn:
    • 1단계: Jira 등에 쌓여있는 지난 1년간의 과거 티켓들을 분석하여, "DB 버전 업그레이드 지원", "속도 20% 개선", "눌리지 않는 버튼 수정" 등의 작업이 4가지 유지보수 중 각각 어디에 해당하는지 파이(Pie) 차트로 분류합니다.
    • 2단계: 리먼의 '복잡도 증가의 법칙'을 실증하기 위해, 처음 설계 문서의 클래스 다이어그램과 2년 뒤 땜질이 반복된 현재 코드의 구조를 비교하여 얼마나 결합도(Coupling)가 거미줄처럼 엉켰는지 도식화합니다.
  • Implement: 특정 레거시 프로젝트의 최근 6개월간 커밋 로그를 분석하여, 유지보수 활동 비율(수정, 적응, 완전, 예방)을 정량화하고 향후 방어적 예산 편성을 제안하는 분석 리포트.

Core Topic 02: 기술 부채의 메타포와 정량화 (Tech Debt Quantification)

  • Why to Learn: 경영진에게 "코드를 고쳐야 하니 시간을 달라"고 설득하기 위해, 보이지 않는 코드 품질을 보이는 '돈(부채와 이자)'으로 치환하기 위해서입니다.
  • What to Learn:
    • Concepts: 워드 커닝햄의 기술 부채(Technical Debt) 사분면 (무지한/신중한, 고의적/비고의적 부채), 복리의 이자(Cost of Delay).
    • Skills: SQALE(Software Quality Assessment based on Lifecycle Expectations) 방법론, 기술 부채 비율(TDR) 측정.
    • Tools: SonarQube 정적 코드 분석기.
    • Trade-offs: 당장 이번 달에 제품을 내놓기 위해 복사 붙여넣기로 하드코딩을 하는 것(원금 대출) vs 1년 뒤 새로운 기능을 붙일 때 1주일이면 할 일을 3달 동안 뜯어고치게 되는 비용(이자 폭탄).
  • How to Learn:
    • 1단계: 프로젝트에 SonarQube를 연동하고, "중복 코드 100줄, 복잡도 초과 함수 5개" 등으로 뜬 알림을 보고, 도구가 제시하는 "이 부채를 갚기 위해 필요한 예상 리팩토링 시간(예: 3 Days)"의 의미를 해석합니다.
    • 2단계: '무지해서 발생한 부채(디자인 패턴을 몰라서 엉망으로 짬)'와 '전략적인 부채(투자를 받기 위해 1주일 만에 날림으로 MVP를 만듦)'의 비즈니스적 차이를 토론하며 부채가 항상 나쁜 것만은 아님을 이해합니다.
  • Implement: 팀 내 소스 코드 저장소에 정적 분석 도구를 붙이고, 전체 프로젝트의 TDR(기술 부채 비율)을 측정한 뒤 우선적으로 청산해야 할 악성 부채 Top 3 목록을 뽑아낸 청산 계획서.

Practical

Core Topic 03: 리팩토링 역학과 릴레이 테스트 (Refactoring Mechanics)

  • Why to Learn: 썩어가는 코드를 발견했을 때 겉으로 드러나는 동작(API 스펙)은 1바이트도 건드리지 않고, 내부의 더러운 내장(구조)만 아름답게 들어내는 수술 기법을 익히기 위함입니다.
  • What to Learn:
    • Concepts: 코드 스멜(Code Smell: 긴 함수, 거대한 클래스, 데이터 클럼프 등), 보이스카우트 규칙.
    • Skills: 마틴 파울러의 리팩토링 기법 (메서드 추출, 다형성으로 조건문 대체, 변수 캡슐화), 불변성(Invariant) 테스트 보존.
    • Tools: IDE 자동 리팩토링 도구, 단위 테스트 프레임워크.
    • Trade-offs: 더 깨끗한 구조를 위해 매번 메서드를 분리하고 클래스를 쪼개는 미학 vs 오버엔지니어링으로 인해 코드가 수십 개의 파일로 파편화되어 읽기 더 힘들어지는 추상화의 함정.
  • How to Learn:
    • 1단계: 1,000줄짜리 GodClass.java에서 '스위치(switch)문'이 덕지덕지 붙은 냄새(Smell)를 찾고, 이를 인터페이스와 다형성(Polymorphism)을 활용한 전략(Strategy) 패턴으로 쪼개어 리팩토링하는 실습을 진행합니다.
    • 2단계: 리팩토링 전과 후의 코드가 정확히 동일하게 작동함을 증명하기 위해, 기존에 작성된 100개의 단위 테스트(Unit Test)를 돌려 모두 초록불(Green)이 들어오는지 확인하는 릴레이 검증 물리를 체험합니다. (테스트가 없으면 리팩토링은 절대 할 수 없습니다.)
  • Implement: 오픈 소스나 과거 프로젝트에서 '가장 코드 스멜이 심각한' 로직 하나를 선정하여, 마틴 파울러의 명명법에 맞게 단계별(Commit 단위)로 리팩토링해 나가는 전 과정 증명 보고서.

Advanced

Core Topic 04: 레거시 현대화와 교살자 무화과 패턴 (Legacy Modernization)

  • Why to Learn: 도무지 코드를 까볼 엄두가 안 나는 10년 된 낡은 모놀리식 시스템(Legacy)을, 서비스 중단 없이 최신의 클라우드 네이티브(MSA) 환경으로 안전하게 이주시키기 위해서입니다.
  • What to Learn:
    • Concepts: 빅뱅(Big-bang) 마이그레이션의 위험성, 리플랫포밍(Replatforming), 안티 코럽션 레이어(Anti-corruption Layer).
    • Skills: 교살자 무화과 패턴(Strangler Fig Pattern), API 게이트웨이를 이용한 점진적 트래픽 스위칭, 병렬 실행(Dark Launching).
    • Tools: Nginx / API Gateway (라우팅 제어), Feature Toggle(기능 스위치).
    • Trade-offs: 기존 시스템을 버리고 옆에 새 시스템을 100% 만들어 한 번에 오픈하는 방식(속도는 빠르나 실패 시 회사 파산) vs 새 시스템을 모듈별로 하나씩 갈아 끼우는 교살자 패턴(안전하나 1~2년간 두 시스템을 동시에 운영해야 하는 비용 고통).
  • How to Learn:
    • 1단계: 프록시(API Gateway)를 세워 모든 트래픽을 구형(Legacy) 서버로 보내다가, '결제' 모듈만 최신(Modern) 서버로 개발한 뒤 트래픽 라우팅을 /pay 경로만 새 서버로 살짝 꺾어주는(Strangling) 물리적 라우팅 역학을 스케치합니다.
    • 2단계: 새 결제 모듈이 기존 구형 데이터베이스의 스키마와 충돌하지 않도록, 중간에 번역기 역할을 하는 '부패 방지 계층(Anti-corruption Layer)'을 두어 레거시의 더러운 데이터 구조가 새 시스템으로 오염되는 것을 막는 방어벽을 설계합니다.
  • Implement: 거대한 모놀리식 이커머스 시스템을 마이크로서비스로 분리한다고 가정할 때, 트래픽 유도, 데이터베이스 마이그레이션, 롤백 시나리오를 포함한 4단계 Strangler Fig 마이그레이션 아키텍처 다이어그램.

7. Terminology

Term (EN / ko, abbr) 1문장 정의 단계(기본/권장/실무/심화) 역할/맥락 관련 개념 유사/대비/함께 사용 오해 포인트 Evidence(Primary/Secondary/Industry) Flags(core)
Technical Debt (기술 부채) 당장 제품을 출시하기 위해 고의로 혹은 무지로 엉망으로 짠 코드가, 훗날 끔찍한 이자(수정 비용 폭증)를 발생시키는 금융적 은유입니다. 기본 개발 속도와 설계 품질 간의 트레이드오프 수량화 Refactoring / Code Smell Bug (버그) 버그는 '기능이 안 되는 것'이고, 기술 부채는 '기능은 되는데 코드가 썩어있는 것'임. 부채가 쌓이면 결국 새 기능 추가 속도가 0으로 수렴함 P2:SWEBOK core
Code Smell (코드 냄새) 1,000줄이 넘어가는 함수나 중복된 로직처럼, 시스템이 심각한 기술 부채를 안고 있음을 후각적으로 알려주는 패턴입니다. 권장 리팩토링의 징후(Symptom) 식별 Refactoring / Anti-pattern Design Pattern (디자인 패턴) 버그나 에러가 아님. 동작은 잘 하지만, 코드를 읽는 인간의 뇌 메모리를 박살 내어 유지보수성을 극도로 떨어뜨리는 암묵적 결함임 Industry core
Refactoring (리팩토링) 외부에서 바라보는 코드의 동작(API)은 단 1비트도 변하지 않게 유지하면서, 내부의 구조(설계)만 뜯어고쳐 더러운 내장을 청소하는 수술 기법입니다. 실무 코드 냄새(Code Smell) 제거 및 부채 탕감 Unit Test / TDD Rewrite (다시 짜기) 리팩토링은 '조금씩 구조만 바꾸는 것'이지 코드를 싹 다 갈아엎고 새로 짜는(Rewrite) 것이 아님. 단위 테스트가 없다면 리팩토링이 아니라 그냥 파괴행위임 Industry core
Strangler Fig Pattern (교살자 무화과 패턴) 거대한 레거시 시스템을 한 번에 버리는 대신, 겉에 새 껍질(API Gateway)을 씌워 새 모듈로 트래픽을 조금씩 꺾으면서(Strangling) 낡은 시스템을 천천히 말라 죽게 만드는 마이그레이션 패턴입니다. 심화 무중단 현대화(Modernization) 및 마이그레이션 리스크 억제 Anti-corruption Layer / API Gateway Big-bang Migration (빅뱅 마이그레이션) "내일 새벽 2시에 새 서버 엽니다!" 식의 빅뱅 오픈을 피하고, 1~2년에 걸쳐 구형과 신형 서버가 공존하며 서서히 체액을 빨아먹는 방식임 Industry core

8. References

Primary

  • [P2] SWEBOK v3 - Software Maintenance (Evolution, Tech Debt)
  • [P5] SFIA - Systems development management (DLMG)

Secondary

  • [Refactoring] Martin Fowler - Code smells and refactoring mechanics
  • [Working Effectively with Legacy Code] Michael Feathers - Testing legacy code

Industry

  • [Strangler Fig Pattern] Martin Fowler - Legacy modernization
  • Repo-Local ZK: 20_ZK/22_Permanent/10-learning/00-tech-cs/tech/ZK-maintenance-tech-debt.md

9. Final Checklist

Primary

  • 소프트웨어 유지보수가 단순히 버그를 잡는 것(Corrective)을 넘어, OS나 브라우저의 변화에 적응(Adaptive)하고 구조를 개선(Perfective)하는 '진화(Evolution)'의 과정임을 리먼의 법칙을 들어 설명할 수 있는가?
  • 당장의 출시 속도를 높이기 위해 무지 혹은 의도적으로 엉망으로 짠 코드가 훗날 어떤 복리의 이자(수정 시간 폭증)를 발생시키는지 워드 커닝햄의 '기술 부채(Technical Debt)' 사분면으로 논증할 수 있는가?

Secondary

  • 수천 줄짜리 GodClass나 5번 이상 복붙된 중복 로직 등 코드 스멜(Code Smell)을 감지하고, 기존 API의 외부 동작을 1%도 훼손하지 않으면서 내부 구조만 갈아엎는 리팩토링(Refactoring)의 역학을 렌더링할 수 있는가?
  • 단위 테스트(Unit Test)의 든든한 방어막 없이 무작정 리팩토링을 감행하는 것이 왜 "안대를 쓴 채 진행하는 심장 수술"과 같은 자살 행위인지, 릴레이 검증 물리의 관점에서 설명할 수 있는가?

Industry

  • SonarQube 등 정적 분석 도구를 이용해 레거시 코드의 냄새를 맡고, 이를 기술 부채 비율(TDR)이라는 '숫자'로 정량화하여 비즈니스 부서에 리팩토링 예산(일정)을 타당하게 요구할 수 있는가?
  • 10년 된 거대한 모놀리식 레거시 시스템을 빅뱅(Big-bang) 방식으로 한 번에 교체하려다 파산하는 대신, API 게이트웨이와 교살자 무화과 패턴(Strangler Fig)을 이용해 2년에 걸쳐 서서히 질식시키는 현대화 파이프라인을 설계할 수 있는가?

Reliability, Observability & Technical Debt

5 / 8