3줄 요약
리팩토링은 신중하게 진행해야합니다.
프로그래머의 생산성은 측정하기 어렵기 때문에
그 비효율이 과대평가 되는 경향이 있습니다.
리팩토링은 흔히 이야기되는 주제에 비해, 위험성이나 부작용에 대해서는 간과되어잇는거 같아 글을 적어봅니다.
작업 효율을 위해서 인건 이 글을 읽는 모든 분들이 알고 계실겁니다.
리팩토링을 진행하면 '왜', '어떤' 효율이 증가하는걸까요?
마틴 파울러의 블로그 내용에 따르면,
작업중에는 필연적으로 부스러기 코드 (cruft) 가 쌓입니다.
부스러기 코드는 무엇일까요?
어플리케이션의 현 상황과 맞지 않은 가정들입니다.
즉 살아있는 서비스는 항상 변동하기 때문에, 어떠한 형태로던지 서비스와 잘 들어맞지 않은 부스러기 코드가 발생하는것은 필연적이란 겁니다.
이러한 기술부채는 새로운 기능을 작성할 때 작업자는 불필요한 코드를 파악해야 하게 만들기 때문에, 총 작업소요시간의 증가를 야기합니다.
기술 부채를 잘 관리한 소프트웨어 프로젝트 (파랑색) 는 그렇지 않은 프로젝트 (갈색) 에 비해 완만한 커브를 그리며 개발 난도가 상승할 거라 예측 할 수 있습니다.
하지만, 그래프의 정의역과 치역의 단위를 잘 살펴보면 y축은 개발된 누적 기능, x축은 시간입니다.
두 단위 모두 마땅한 기준단위를 측정하기 어렵습니다.
이 점에서 이 그래프는 pseudo-graph 임을 알 수있는데요.
그 말인즉슨, 모두 두 케이스가 저러한 경향성을 가진다는 것에는 이견이 없을겁니다.
하지만, 과연 '언제' 파랑색 그래프가 갈색 그래프를 추월하는지에 대해서는 명확한 시점을 계산하기 무척 어렵다는 것 입니다.
과연 한 프로젝트가 기술 부채를 따로 관리하지 않았을 때의 개발 불능영역 (기울기가 0에 수렴하는구간) 에는 언제 도달하게되는걸까요?
프로젝트 런칭 직후일까요? 혹은 런칭 후 1개월, 1년, 혹은 10년일까요?
여러분은 그 시점을 특정하기 정말 어렵다는것을 알 수 있을 겁니다.
또한 적극적으로 기술부채를 청산한 프로젝트는, 과연 어떤 이익을 얼마나 얻고 있는지 측정 할 수 있을까요?
이렇게 그 정확한 시점을 특정하기 어려운 이유는, 근본적으로 프로그래머의 성과는 측정하기 매우 어렵다 라는 문제에서 기인합니다.
한 프로그래머의 성과를 line 수, 혹은 PR 수, 개발한 기능 수, 근무시간, 비즈니스적 성과등,
어떠한 기준점을 적용해도 이로 인한 부작용을 쉽게 생각하실 수 있을겁니다.
(ex PR 을 무의미하게 잘게 나누어 올린다던지, 사이즈가 큰 기능을 피하고, 유지보수성 기능만 추가하며 총 개발한 기능수를 늘린다던지, ...)
결국 프로젝트의 생산성은 관리자와 실무자들의 주관적인 체감에 의존에 평가되는 경우가 잦은데
사람의 특성상 레거시 코드를 유지보수하는데에는 스트레스를 받기 쉽기 때문에, 자신이 작업하기 싫은 감정과, 프로젝트의 생산성을 동일시 할 위험이 있습니다.
그러나 리팩토링은 그 자체로서는 비즈니스에 끼치는 영향이 -0 라고 할 수 있는데요,
그 이유는 성공적으로 리팩토링을 완수해도 고객에게 끼치는 영향은 0이기 때문에 단기적으로는 사업에 끼치는 영향이 아예 없다고 할 수 있기 때문입니다.
심지어 발생할수 있는 이슈나 버그에 대한 리스크,
리팩토링을 진행하지 않고 다른 기능을 개발할 수 있었던 기회비용까지 추정하면 리팩토링 자체는 사업적으로 손해를 볼 여지가 아주 다분한 행위라 볼 수 있습니다.
그러면 결론은 리팩토링은 영영 하지 말아야할까요?
그래프의 개발 불능영역이 언제 올지 모르니, 최대한 버티다가 완전히 유지보수 불가판정이 나오면 새로 만들어야할까요?
제목을 하지 말라고 적어놨지만, 사실 필연적으로 해야하긴 합니다.
정확히는 한번에 대청소와 같은 느낌의 "Grand refactor" 를 가능한 하지 말라는 이야기입니다.
앞에 이야기했듯이, code cruft 는 필연적으로 발생합니다.
모든 기술 부채를 상환하고자 하는 행위 조차도 cruft를 만든다고 할 수 있습니다.
목표가 성취감이 아니라 집의 청결이 목적인 경우에,
시험기간에 한번씩만 진행하는 대청소보단 매 저녁에 30분 동안 청소하는것이 더 도움이 되듯
프로젝트의 코드 또한 목표가 성취감이 아니라, 지속가능한 발전에 있다면
작정하고 수행하는 대규모 리팩터링보단 평소 작업에 충분한 시간을 투자하며 조금씩 고쳐가는것이 좋다는 이야기입니다.
여러분은 기술 부채에 결벽증을 가질 필요가 없습니다.
총 자산 = 순자산 + 부채 로 계산되듯이
적절한 정도의 기술부채는 (매 저녁마다 관리 할 수 있는 정도의 이자비용인) 오히려 총 생산성을 더 높이는 요인으로 작동 할 수 있습니다.
여러분이 레거시 코드를 대상으로 맘을 먹고 칼을 빼 들었으면 (대규모 리팩토링이든, PR을 올리는 김에 조금 고치는거든) 어떻게 고치는게 좋을까요?
다시말해 여러분이 한 작업이 단발성으로 끝나지 않고
그 결과가 부채가 아닌 유산으로 남아 프로젝트에 기여하고자 하려면, 어떻게 작업을 수행해야 할까요?
저는 그 해답은 테스트에 있다고 생각합니다.
명문화 되어있지 않았던 요구사항과 가정들을 작성해 발생할 수 있는 위험들을 Left-Shift, QA 혹은 Relese 단계에서만 확인할 수 있었던 가정과 요구사항을 가능한 개발 과정의 왼쪽으로 옮기는것이 그 방법이라 생각합니다.
테스트 중심으로 생각해야 한다는 의견에 동의합니다.
혹시 부채는 갖고 계신 건가요? 탐나네요..