리팩토링
“동작은 유지한 채 내부 구조를 개선해 유지보수성을 높이는 작업.”
리팩토링이란
리팩토링(Refactoring)은 소프트웨어가 외부에서 관찰되는 동작은 그대로 유지하면서 내부 구조만 개선해 이해하기 쉽고 바꾸기 쉬운 상태로 다듬는 작업이다. 핵심 전제는 기능을 추가하거나 결함을 고치는 일과 구조를 정리하는 일을 분리한다는 데 있다.
같은 결과를 내더라도 코드가 점점 읽기 어려워지면 변경의 비용이 누적되어 결국 작은 수정조차 위험해지므로, 그 부담을 정기적으로 덜어내는 활동이 필요하다. 따라서 리팩토링은 코드를 다시 쓰는 것이 아니라, 동작의 경계를 침범하지 않은 채 내부 질서를 회복하는 절제된 개선이다.
동작 보존이라는 원칙
리팩토링을 다른 변경과 구분하는 결정적 기준은 동작 보존이다. 구조를 바꾸는 동안 입력에 대한 출력과 외부 계약이 달라지지 않아야 하며, 이 약속이 깨지면 그것은 이미 리팩토링이 아니라 기능 변경이다.
동작 보존을 보장하는 현실적 장치가 바로 테스트인데, 충분한 테스트가 있어야 구조를 바꾼 뒤에도 행위가 유지되었음을 즉시 확인할 수 있다. 테스트 없이 진행하는 구조 변경은 개선이 아니라 검증되지 않은 도박에 가깝다.
그래서 리팩토링과 자동화된 검증은 사실상 한 쌍으로 다뤄진다.
작은 단계로 나아가기
리팩토링의 안전성은 한 번에 바꾸는 폭을 최소화하는 데서 나온다. 큰 구조 변경을 단번에 시도하면 어디서 동작이 어긋났는지 추적하기 어렵지만, 작고 의미가 분명한 단계로 쪼개 매 단계마다 검증하면 문제의 범위가 항상 좁게 유지된다.
각 단계가 그 자체로 동작을 보존하므로 언제든 멈추거나 되돌릴 수 있고, 진행 중에도 코드는 항상 동작하는 상태로 남는다. 이런 점진성이 리팩토링을 위험한 대수술이 아니라 일상적 정비로 만든다.
변경의 크기를 줄이는 감각이 곧 리팩토링의 숙련도다.
| 구분 | 리팩토링 | 기능 변경 |
|---|---|---|
| 외부 동작 | 그대로 보존 | 달라짐 |
| 목적 | 내부 구조 개선 | 요구 추가 수정 |
| 검증 | 테스트로 확인 | 신규 동작 확인 |
디자인 패턴과의 관계
리팩토링은 종종 코드를 알려진 디자인 패턴의 형태로 수렴시키는 방향으로 진행된다. 중복과 과도한 결합처럼 변경을 어렵게 만드는 신호가 쌓인 지점을 정리하다 보면, 그 해법이 자연스럽게 검증된 패턴의 구조와 맞아떨어지는 경우가 많기 때문이다.
이는 패턴을 미리 추측해 박아 넣는 것과 반대 방향으로, 실제 필요가 확인된 뒤 구조를 옮겨가므로 과설계의 위험이 낮다. 따라서 리팩토링은 패턴을 향해 가는 통로이자, 패턴이 과하게 적용된 코드를 다시 단순화하는 통로이기도 하다.
두 활동은 설계를 살아 있게 유지하는 양방향의 힘이다.
기술 부채와 리팩토링
리팩토링은 누적된 기술 부채를 갚는 핵심 수단이다. 일정에 쫓겨 임시방편으로 쌓은 구조는 당장은 동작하지만, 시간이 지날수록 변경을 가로막는 이자로 돌아온다.
부채를 방치하면 기능 추가 속도가 점점 느려지고 결함이 늘어나므로, 변경이 잦은 영역을 우선해 구조를 정리하는 판단이 필요하다. 다만 모든 코드를 완벽히 다듬을 수는 없으므로, 자주 손대는 영역과 거의 바뀌지 않는 영역을 구분해 투자할 곳을 고르는 일이 중요하다.
부채 상환의 우선순위를 정하는 능력이 곧 유지보수 전략의 핵심이다.
일정 안에 녹이는 법
리팩토링을 별도의 거대한 과제로 떼어내 일정을 따로 잡으려 하면 우선순위에서 밀려 영영 착수되지 못하기 쉽다. 더 현실적인 방식은 기능 변경이나 결함 수정으로 어차피 그 코드를 건드릴 때, 그 직전이나 직후에 주변 구조를 조금씩 함께 정비하는 것이다.
이렇게 일상 작업에 녹여 두면 부채가 한꺼번에 폭발하지 않고 꾸준히 통제된다. 반대로 구조 개선을 무한정 미루다 한 번에 갚으려 하면 위험과 비용이 동시에 커진다.
작은 정비를 거르지 않는 습관이 결국 가장 저렴한 유지보수 전략이 된다.
관련 용어