# [[레거시 코드 (Legacy Code)]]

## 📌 Brief Summary
레거시 코드는 전통적으로 다른 사람이 작성했거나 이해하고 변경하기 어려운 복잡한 코드를 의미하기도 하지만, 마이클 페더스(Michael Feathers)의 정의에 따르면 "테스트가 없는 코드"를 뜻합니다[1-3]. 아무리 구조가 좋고 객체지향적으로 잘 작성되었더라도 테스트가 없다면 동작의 변경을 빠르고 검증 가능하게 수행할 수 없으므로 나쁜 코드로 간주됩니다[4]. 이러한 레거시 코드는 변경 시 즉각적인 피드백을 받을 수 없어 소프트웨어 개발에 소요되는 시간과 비용을 고갈시키는 주된 원인이 됩니다[5].

## 📖 Core Content
* **레거시 코드의 딜레마와 의존성 문제**
  레거시 코드를 안전하게 수정하려면 테스트가 필요하지만, 테스트를 작성하기 위해서는 기존 코드의 강한 의존성을 끊어내기 위해 코드를 먼저 수정해야 하는 모순적인 상황이 발생하며 이를 '레거시 코드의 딜레마'라고 부릅니다[6, 7]. 레거시 코드의 가장 핵심적인 문제는 코드가 서로 너무 강하게 결합되어 있어 독립적인 테스트가 불가능하다는 점입니다[7].

* **레거시 코드 개선 알고리즘**
  레거시 시스템을 점진적으로 개선하기 위해서는 최소한의 안전한 리팩토링을 수행해야 하며, 다음의 알고리즘을 따릅니다[6, 8].
  1. **변경 지점 및 테스트 지점 식별:** 수정이 필요한 로직의 위치와 해당 로직을 보호할 수 있는 테스트 작성 위치를 찾습니다.
  2. **접점(Seams) 활용 및 의존성 제거:** 접점이란 소스 코드를 직접 수정하지 않고도 프로그램의 동작을 바꿀 수 있는 지점(예: 인터페이스 추상화 및 가짜 객체 주입)을 의미합니다[7, 9, 10]. 이를 통해 테스트 실행을 방해하는 의존성을 끊어냅니다.
  3. **테스트 작성:** 현재 어떻게 동작하는지를 기록하는 승인 테스트(Approval Tests) 또는 캐릭터리제이션 테스트(Characterization Tests)를 작성하여 안전망을 확보합니다[8].
  4. **기능 수정 및 리팩토링:** 테스트가 확보된 후 요구사항을 반영하고 코드를 리팩토링합니다[6, 8].

* **시간이 부족할 때의 대처 기법 (Sprout & Wrap)**
  테스트가 없는 방대한 코드를 전면적으로 리팩토링할 시간이 없을 때 사용할 수 있는 기법입니다[11].
  * **스프라우트 기법(Sprout Technique):** 기존의 거대한 메서드에 코드를 덧붙이는 대신, 새로운 로직을 별도의 독립되고 검증된 함수(또는 클래스)로 작성한 후 기존 코드의 삽입 지점에서 이를 호출하는 방식입니다[8, 12].
  * **랩 기법(Wrap Technique):** 기존 메서드와 동일한 이름의 새 메서드를 만들고, 그 안에서 기존 메서드를 호출하기 전이나 후에 새로운 테스트 가능한 로직을 배치하여 감싸는 방식입니다[13].

* **스크래치 리팩토링 (Scratch Refactoring)**
  이해하기 어렵고 테스트가 없는 코드를 파악하기 위해 사용하는 기법입니다. 변수명을 바꾸거나 함수를 추출하는 등 코드를 자유롭게 변경하며 구조를 이해한 뒤, 파악이 끝나면 작성한 변경 사항을 모두 되돌리고(revert) 적절한 테스트와 함께 처음부터 다시 작업을 시작합니다[14, 15].

## ⚖️ Trade-offs & Caveats
* **초기 테스트 도입의 위험성:** 레거시 코드에 테스트를 도입하기 위해 의존성을 끊는 작업 자체는 아직 테스트 안전망이 없는 상태에서 코드를 변경해야 하므로 상당한 위험을 수반합니다[3]. 따라서 아주 국소적이고 안전한 최소한의 변경만을 수행해야 합니다[6].
* **미학적 타협의 필요성:** 레거시 코드를 테스트 가능한 상태로 만드는 과정(예: 의존성 분리를 위한 임시 조치 등)에서 일시적으로 코드의 형태가 기존보다 다소 더 지저분해질 수 있습니다[16]. 이는 외과 수술을 위해 절개를 하는 것과 같으며, 코드를 더 건강한 상태로 옮기기 위해 미학적 판단을 유보해야 할 때가 있습니다. 완벽함('best')을 추구하느라 더 나아짐('better')을 포기해서는 안 됩니다[16].
* **스프라우트와 랩 기법의 한계:** 스프라우트(Sprout)와 랩(Wrap) 기법은 기존 레거시 코드를 건드리지 않고 안전하게 새 기능을 추가할 수 있게 해주지만, 이상적인 해결책은 아닙니다[17]. 이 기법들만을 남용할 경우 원래의 레거시 코드는 리팩토링되지 않은 채 계속 방치될 수 있으므로 주의해야 합니다[11, 17].


---
*Last updated: 2026-05-03*