7.0 KiB
7.0 KiB
Scratch Refactoring (스크래치 리팩토링)
📌 Brief 임무
Scratch Refactoring(스크래치 리팩토링)은 테스트 코드가 없고 파악하기 어려운 레거시 코드를 이해하기 위해 안전장치 없이 자유롭게 코드를 수정해보는 탐색적 기법입니다 [1, 2]. 이 기법의 목적은 코드를 실제로 정리하는 것이 아니라 코드의 동작 방식을 친숙하게 파악하는 데 있습니다 [2]. 탐색이 끝난 후에는 수정한 내용을 반드시 원래 상태로 되돌리고(revert) 정식 프로세스를 시작해야 하는 것이 핵심 규칙입니다 [2].
📖 Core Content
- 목적과 활용 배경: 마이클 페더스(Michael Feathers)의 저서 "Working Effectively with Legacy Code"에서 소개된 이 기법은, 개발자가 직접 작성하지 않았고 테스트와 문서화가 부족하여 어디서부터 시작해야 할지 막막한 레거시 코드를 다룰 때 사용됩니다 [1-3].
- 실행 방식: 스크래치 리팩토링의 유일한 규칙은 '작업이 끝난 후 변경 사항을 되돌린다(revert)'는 것입니다 [2]. 최종적으로 코드를 폐기할 것이기 때문에, 개발자는 시스템을 망가뜨릴 걱정 없이 불안전한 변경(unsafe changes)을 자유롭게 시도할 수 있습니다 [2]. 코드를 파악하기 위해 함수를 추출해 보거나, 구조를 단순화하거나, 변수 이름을 마음껏 변경하는 등 코드와 적극적으로 상호작용합니다 [2].
- 사후 처리: 코드를 충분히 파악하고 나면, 시도했던 모든 변경 사항을 취소하여 원래 상태로 되돌립니다 [2]. 그런 다음 확보한 코드에 대한 이해도를 바탕으로 적절한 자동화 테스트를 작성하고, 이후 실제 적용할 안전한 변경과 리팩토링을 정식으로 다시 시작하게 됩니다 [2, 4].
⚖️ Trade-offs & Caveats
- 엄격한 원상 복구(Revert)의 의무: 이 기법은 테스트라는 안전망 없이 코드를 변경하는 것이기 때문에, 실수로 변경 사항을 커밋하거나 남겨두면 시스템에 심각한 버그를 유발할 수 있는 위험(Risk)이 따릅니다 [2, 4]. 따라서 목적 달성 후 반드시 코드를 되돌려야 한다는 엄격한 제약 사항이 존재합니다 [2].
- 단기적인 시간 소모: 결국 버려질 코드 변경 작업에 시간을 투자해야 하므로 단기적으로는 비효율적인 것처럼 보일 수 있습니다. 하지만 이는 복잡한 코드를 이해하고 이후에 안전한 테스트를 작성하기 위한 발판을 마련하는 것이므로, 장기적인 관점에서는 기술 부채를 다루기 위한 유용한 투자로 볼 수 있습니다 [2].
🔗 Knowledge Connections
Related Concepts
[작업 대상 및 환경]
- Legacy Code (레거시 코드)
- 연결 이유: 스크래치 리팩토링이 주로 적용되는 대상이며, 저서에서는 이를 '테스트가 없는 코드'로 정의합니다 [1].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 스크래치 리팩토링이 왜 필요하며, 어떤 환경(테스트 부재, 높은 복잡도)에서 그 가치를 발휘하는지 이해할 수 있습니다.
[연계 기법 및 후속 조치]
- Automated Tests (자동화된 테스트)
- 연결 이유: 스크래치 리팩토링으로 코드를 이해하고 원상 복구한 뒤, 가장 먼저 수행해야 하는 핵심 단계입니다 [2, 4].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 리팩토링 시 기능이 깨지지 않았음을 보장하는 피드백 루프의 중요성과 불안전한 변경과 안전한 변경의 차이를 파악할 수 있습니다.
- Exploratory Refactoring (탐색적 리팩토링)
- 연결 이유: 얽혀있는 코드베이스를 파악하기 위해 다른 접근법으로 시간을 할애하여 코드를 분석하는, 유사한 성격을 지닌 기법으로 함께 언급됩니다 [5].
- 이 개념을 통해 더 깊게 이해할 수 있는 부분: 복잡한 레거시 코드를 파악하는 다양한 실무적 방법론과 마인드셋을 비교하며 확장할 수 있습니다.
Deeper Research Questions
- 스크래치 리팩토링 과정에서 얻은 함수 분리 및 변수명 변경의 아이디어를 코드 복구(revert) 이후에 어떻게 유실 없이 효율적으로 정식 리팩토링에 반영할 수 있는가?
- 안전하지 않은 변경(unsafe changes)을 기반으로 코드를 파악할 때, 부수 효과(side effects)가 큰 언어나 프레임워크 환경에서 주의해야 할 한계점은 무엇인가?
- 스크래치 리팩토링을 진행하는 동안 파악하게 되는 의존성 문제들을 'Seams(접점)'을 찾는 과정과 어떻게 체계적으로 연결할 수 있는가?
- 시간적 압박이 심한 스프린트 내에서, 결국 되돌려야 하는 스크래치 리팩토링에 할애할 시간을 어떻게 산정하고 정당화할 수 있는가?
- 순수 탐색 목적인 '스크래치 리팩토링'과 '탐색적 리팩토링(Exploratory Refactoring)' 간의 실무 절차상의 구체적인 차이점은 무엇인가?
Practical Application Contexts
- Implementation: 테스트가 없고 복잡한 레거시 코드를 처음 수정해야 할 때, 코드를 직접 분해해보고 리네이밍해보는 등 부담 없는 실습 및 분석 도구로 활용합니다 [2].
- System Design: 문서화되지 않아 블랙박스처럼 작동하는 시스템의 내부 동작 흐름과 데이터 의존성을 파악하는 사전 조사 단계로 사용됩니다 [2].
- Operation / Maintenance: 유지보수 과정에서 이해할 수 없는 코드를 만나 변경이 망설여질 때, 원상 복구를 전제로 과감한 변경을 시도하여 시스템의 동작 원리를 터득하는 데 적용합니다 [2, 3].
- Learning Path: "효과적인 레거시 코드 작업(Working Effectively with Legacy Code)"을 배우는 과정 중, 테스트 코드를 작성할 진입점을 찾지 못할 때 돌파구를 마련하는 필수 학습 기법으로 다뤄집니다 [1, 2].
- My Project Relevance: 문서화 및 테스트가 전무한 외부 코드를 인수인계받아 긴급한 기능을 추가해야 할 때, 사전 코드 분석 및 안전한 리팩토링 전략을 수립하기 위해 도입할 수 있습니다.
Adjacent Topics
- Seams (접점)
- 확장 방향: 스크래치 리팩토링을 통해 코드의 흐름을 이해한 후, 테스트를 주입하기 위해 소스 코드를 편집하지 않고도 프로그램의 동작을 바꿀 수 있는 '접점'을 식별하는 방법론으로 학습을 확장합니다 [4, 6].
- Sprout & Wrap Techniques (스프라우트와 랩 기법)
- 확장 방향: 스크래치 리팩토링 후에도 전체 클래스나 함수에 테스트를 작성할 시간이 부족할 때, 새로운 코드를 격리하여 추가하는 대안적인 레거시 코드 대처 기법으로 연결하여 살펴볼 수 있습니다 [7-9].
Last updated: 2026-05-03