리팩토링 계획하기
리팩토링이란.. 누군가에게는 즐거울지도 모르지만 저에게는 폭탄을 해체하는 것만큼이나 까다롭고 두려운 일입니다.
리팩토링을 계획하다 보면 “꼭 해야 할까?”, “수정한 부분에서 버그가 발생하면 어떡하지?”, “아 귀찮아” 등..의 생각이 들어 리팩토링을 미루는 일이 많았습니다.
하지만 지금 보고 있는 이 코드가 영원하다는 보장은 없습니다. 새로운 기능의 추가, 세월의 흐름 등.. 코드는 언제나 버그 발생의 가능성이 있습니다.
단순히 오래된 코드뿐만 아니라 급하게 개발한 기능, 대충 메꾼 핫픽스, 덮어씌우고 덮어씌운 코드 등.. 저는 때때로 이런 곳에서 리팩토링의 대상을 찾습니다.
이제 이러한 코드를 깔끔하게 바꾸기 위해 필요한 것들을 알아보겠습니다.
모든 코드는 자신만의 사연을 가지고 있다.
모든 코드는 자신만의 사연을 가지고 있습니다. 지금 보고 있는 지저분한 이 코드도 깔끔했던 시절이 있었을 것입니다.
projectViewModel.project != null && (!(projectViewModel.project.flag1 || projectViewModel.project.finished) || projectViewModel.project.finished) ||
projectViewModel.hasError1 || projectViewModel.hasError2
하지만 여러 힘든 일(기능 추가)을 겪고 지금의 지저분한 코드가 되었습니다.
이런 슬픈 일을 방지하기 위해 어떤 행동을 취하는 것이 좋을까요?
- 기능 추가를 막는다.
- 기능이 추가될 때마다 모든 코드를 새로 작성한다.
- 최초 설계 단계에 신경을 많이 쓴다.
정답은…
1번! 아니.. 3번입니다!!
하지만 주니어 of 주니어 개발자인 저에게 최초 설계 단계에서 모든 것을 예측하는 것은 매우 매우 어려운 일입니다. (사실상 불가능하다고 봐도..)
그렇다고 손 놓고 볼 수만은 없습니다.
제가 선호하는 방식은 최소한의 코드 수정으로 많은 변경 사항을 해결할 수 있도록 설계하는 것입니다.
예를 들어서, 기존의 것을 수정하는 것보다 새로운 것을 추가하는 방법을 통해 코드 수정을 줄인 경험이 있습니다. 만약 기존에 있던 코드의 수정이 불가피하다면 여러 객체지향의 원칙을 적용하여 수정이 일어나는 곳을 줄이도록 설계할 수 있습니다.
이러한 좋은 설계를 위해서.. 개인적으로 클린 코드 도서를 추천해 드립니다. 클린 코드는 좋은 코드를 작성하는 방법, 좋은 설계 등 개발자들에게 꼭 필요한 지식을 담고 있습니다. 책 자체는 두껍지만 술술 잘 읽을 수 있기에 시간을 내서 읽는 것을 추천해 드립니다.
작은 것부터 시작해보자
작은 부분부터 차근차근 수정해나가다 보면 우리의 큰 목표를 달성할 수 있습니다.
아래는 지난번에 적용했던 방법으로, 간단하지만 큰 효과를 보았습니다.
먼저 지금은 쓰지 않는 변수, 함수, 주석이 된 코드 등을 정리하는 등의 일부터 시작합니다. 그리고 코드를 쭉 읽어봅니다. 이해하거나 읽기에 어려운 부분이 있다면 먼저 그 부분부터 리팩토링을 시작합니다. 보통 변수나 함수 이름이 잘못되었거나 한 줄에 너무 많은 코드가 있을 때 이런 어려움을 느끼게 됩니다.
변수의 이름을 변경하고 한 줄의 긴 코드를 나누고.. 함수의 이름을 변경하려는데 이 함수가 하는 일이 너무 많아 이름을 짓기 어렵습니다.
(마늘도 다지고 파도 다지고 고기도 다지는 친구를 ‘만능다지기’라고 부르지만 함수 이름을 그렇게 짓기에는 조금..)
이제 함수를 분리해줍니다. 열심히 함수를 분리하고 코드를 쭉 둘러봅니다. 코드를 둘러보다 보니 방금 열심히 분리한 함수 중 여기에 있으면 안 될 것 같은 친구가 여럿 보입니다. 이제 함수들을 클래스로 분리해줍니다.
저는 이런 방법으로 큰 효과를 보았는데, 작은 것부터 조금씩 시작하여 큰 위험부담 없이 이전에 동작했던 기능을 이어나갈 수 있기 때문입니다.
하지만 작은 것부터 시작하는 것에 어려움을 느낄 때가 있었습니다. 또한 리팩토링 해도 조금의 시간이 지나면 이전의 상태로 돌아오는 경우도 있었습니다.
주로 기존의 설계 또는 구조가 잘못되어 있을 때 이런 일이 일어나게 됩니다. 이런 경우 저는 아래의 방법을 사용하였습니다.
처음부터 다시 만들기
작은 것 하나도 건드릴 수 없을 때, 이미 돌이킬 수 없는 코드를 발견했을 때, 처음부터 다시 만들고 싶다는 생각을 많이 하였습니다.
처음부터 다시 만드는 방법은 기존의 잘못된 설계와 구조를 바꿀 수 있다는 큰 장점이 있다고 생각합니다.
하지만 아래 주의사항을 마음에 두고 작업하였습니다.
첫 번째로는 열심히 바꾼 설계와 구조가 시간이 지나면서 예전처럼 다시 지저분한 코드가 될 수 있다는 것입니다. 이를 막기 위해 “모든 코드는 자신만의 사연을 가지고 있다.”에서 설명해 드린 수정을 최소한으로 줄이는 설계를 사용하였습니다.
두 번째로, 작은 것부터 리팩토링하는 것보다 위험 부담이 크고 이전 기능을 완벽히 구현하지 못할 수 있다는 것입니다. 하지만 아래 “리팩토링 전 모든 기능을 파악해야 한다.”의 규칙을 따라서 성공적으로 리팩토링을 끝마칠 수 있었습니다.
리팩토링 전 모든 기능을 파악해야한다.
정말 당연한 이야기입니다. 모든 기능을 파악하지 못했다면 리팩토링을 시작할 수 없기 때문입니다.
하지만 의욕만 앞선 저는 아래와 같은 슬픈 경험을 한 적이 있습니다.
(코드를 둘러보던 중…) 엇 여기 코드가 조금 지저분한데 고쳐볼까? → 와 다 고쳤다~~ → 엇 이게 무슨 버그지? → (예전 코드와 비교) → 아.. → 수정 → 반복 → 리팩토링 전과 별로 다른 것이 없음
코드를 리팩토링하기 전, 지금 내 눈앞의 지저분한 코드가 가진 의미와 이런 코드가 탄생하게 된 이유를 찾아야 합니다. “모든 코드는 자신만의 사연을 가지고 있다”와 비슷한 맥락입니다.
한줄 한줄이 무엇을 의미하는지 알아야 과거의 실수를 반복하지 않고 새로운 코드를 작성할 수 있습니다.
글을 마치며
개발자는 깔끔한 코드를 작성하고 싶지만 부족한 시간과 자원(그리고 귀찮음)이 지저분한 코드를 만들게 됩니다.
하지만 지금 작성한 코드가 미래에 어떤 모습으로 나에게 돌아올지는 모릅니다.
큰 짐이 될지, 리팩토링 1순위가 될지, 버그가 될지..
매번 안 좋은 상황(버그, 버그, 버그)이 벌어질 때마다 코드를 보며 생각하는 것은 “왜 이걸 발견하지 못했을까?”입니다.
왜 이걸 발견하지 못했나 생각해보면 알아볼 수 없는 지저분한 코드와 잘못된 설계가 원인이었던 것을 깨닫습니다.
(하지만 정말 근본적인 원인은 저의 부주의 ^^..)
그렇기에 리팩토링의 중요성을 깨닫고 지금부터 조금씩 시작해보려 합니다.
긴 글 읽어주셔서 감사합니다.