리펙토링이란 무엇일까? wikipedia에 따르면 다음을 뜻한다.
"리팩토링(refactoring)은 주로 '결과의 변경 없이 코드의 구조를 재조정함'을 뜻한다."
참고 : 영문 위키피디아 (한국 위키엔 아직 내용이 많이 부족하다.)
프로그래밍에 대해 공부를 해본 사람이라면 이 리펙토링을 해야하는 이유에 대해 귀가 따갑도록 이야기를 들었을 것이다.
하지만 리펙토링이라는 것 자체가 "결과의 변경없이 구조를 재조정하는 것"이라는 정의에서와 같이 리펙토링만으론 더 나은 실행 결과를 얻을 수 없다. 또한 잘못된 리펙토링 방법 또는 프로그래머의 실수로 인해 문제없이 잘 운영되던 시스템을 오류 덩어리로 만들수 있기 때문에 조심스럽게 다뤄져야할 기술이다.
그럼에도 불구하고 리펙토링을 하는 이유는 소프트웨어의 디자인을 개선시켜주기 때문이다. 그렇다면 소프트웨어 디자인이 개선됨으로써 무엇을 얻을 수 있을까?
- 소프트웨어를 더 이해하기 쉽게 만든다. (향후 유지보수에 도움이 된다.)
- 버그를 더 잘 찾을 수 있도록 도와준다.
- 소프트웨어 개발 속도를 높여준다.
잘된 리펙토링은 이 외에도 많은 것을 얻을 수 있다.
이렇게 리팩토링은 필수적으로 해야할 프로그래밍 기법이지만 현실에서 리펙토링을 잘 사용하는 사람을 보기는 힘들다. 이유는 앞서 얘기한 것과 같이 외부적으로 얻을 수 있는 향상된 결과는 없고 많은 위험 요소를 안고 있기 때문이다. 또한 실무 프로그래머라면 공감하겠지만 리펙토링을 하기 위한 시간은 프로젝트에 배정되는 경우는 드물다. 이런 이유로 리펙토링의 중요성은 알면서도 할 수 없다는 사람들이 많다. 결국 리펙토링을 잘못했을 때 돌아올 결과를 두려워하는 것이라고 볼 수 있다.
그렇기 때문에 더더욱 리펙토링은 수시로 해야한다고들 말한다.
"한번도 하기 힘든 리펙토링을 자주, 수시로 하라고?"
이런 물음을 가진다면 다시 돌아가서 리펙토링을 두려워하는 이유를 생각해보자.
- 리펙토링할 시간을 별도로 제공하는 프로젝트는 드물다.
- 리펙토링을 잘못하면 새로운 오류를 만들어낸다.
- 레펙토링이란 것에 대해서 잘 모른다. 또는 경험이 없어 익숙치 않다.
우선 첫 번째 이유를 생각해 보자. 일반적으로 실무에서 프로젝트와 프로젝트 사이에 여유란 없다. 겹치지만 않아도 다행인 것을... 그렇다면 모든 개발이 끝나고 리펙토링하는 것은 작업 분량 때문에 사실상 불가능하다. 그러므로 리펙토링의 분량이 적을 때 틈틈이 코드를 개선하는 것이 필요하다.
사실 첫 번째 이유보다 두 번째 이유가 더 중요하다. 프로젝트가 완료되고 한꺼번에 리펙토링을 한다고 가정해 보자. 리펙토링하고자 하는 코드와 관련된 코드의 범위가 방대할 가능성이 높다. 다시말해 수정해야할 코드의 분량이 많기 때문에 오류가 끼어들 여지가 많다. 따라서 관련된 소스 코드가 적을 때 자주 리펙토링을 함으로써 오류의 가능성을 줄일 수 있다.
마지막 이유. "잘 모른다." 사실 다른 이유보다 이것 때문에 리펙토링을 꺼려하는 경우가 많다. 서점에 나와 있는 리펙토링 책을 보니 알아야할 것이 너무 많아 보인다. 무슨 말인지도 잘 모르겠고... 결국 시도할 엄두를 내지 못한다.
하지만 실제 리펙토링을 제대로 하려면 알아야 할 것들이 많겠지만 시작을 위해 알아야할 것은 그렇게 많지 않다. 게다가 요즘은 좋은 개발 도구들이 많아서 작업이 용이하고 오타 등으로 인한 오류의 가능성도 많이 낮출 수 있다.
그럼 조금 더 세부적으로 얼마나 자주 하는게 좋을까? 리펙토링 관련 도서나 여러 곳에서 아래와 같이 조언한다.
- 비슷한 기능을 수행하는 함수를 반복적으로 필요로하게 될 때(재사용성을 개선), 이미 만든 함수와 동일한 기능을 다시 필요로 할 때 바로할 수도 있으나 너무 자주 리펙토링에 시간을 쏟는 것을 막기 위해 평균적으로 세번쩨 필요시에 리펙토링하라고 하기도 한다.
- 새로운 기능을 추가할 때
- 버그 수정이 필요할 때
- 코드 검토(code review)를 할 때
- 중복된 로직을 가지고 있는 프로그램 수정하기 어렵다.
- 실행중인 코드를 변경해야 하는 특별한 동작을 요구하는 프로그램은 수정하기 어렵다.
- 복잡한 조건문이 포함된 프로그램은 수정하기 어렵다.
- 읽기 어려운 코드 수정해야 할 때(읽기 어려운 코드는 수정하기 어렵다.)
반대로 하지 말아야할 시점은 언제일까? 개인적으로는 하지 말아야할 시기는 없다고 생각하지만 일반적으로 아래의 경우엔 피하는게 좋다라는 한다.
- 코드를 처음부터 다시 작성해야 할때
- 마감일에 가까울 때
간단하게 얘기해서 리펙토링할 시간적 여유가 없을 때. 문제는 시간적 여유는 항상 없다는 것이다. 따라서 꾸준히 적절한 시점에 적당한 범위를 정해 리펙토링을 해야만 한다.
그렇다면 적은 시간과 노력으로 보다 효과적인 리펙토링을 위해 필요한 것은 무엇일까?
간단히 얘기하자면 당연하게도 코딩을 잘하는 방법을 아는 것이다. 그리고 적절한 도구를 활용하는 것이다.
코딩을 잘하는 방법을 알고 싶다면 디자인 패턴에 대해 공부하면 큰 도움이 된다. 당연히 디자인 패턴을 잘 안다면 리펙토링이 필요한 코드 자체를 많이 만들지 않게 될 것이다.
리펙토링을 도와줄 도구를 잘 활용하는 것도 중요하다. 이미 많은 사람들이 사용하는 이클립스는 아주 강력한 리펙토링 도구를 제공한다.
그리고 리펙토링을 하다보면 잘못된 길로 접어들어 차라리 원래의 소스로 되돌아 오는게 필요할 수 있다. 이때에 대비해 형상관리도구도 사용하는게 좋다. 사실 형상관리 도구의 필요성은 이것 말고도 많이 있으나 주제에서 벗어나므로 다음 기회로...
또 한가지 중요한 것이 있다. 그것은 바로 TDD(테스트 주도 개발)다. 이것 또한 방대한 주제이므로 다음 기회로...
단, TDD와 리펙토링의 관련성은 짚고 넢어가자. 정확하게 얘기하자면 TDD 자체가 리펙토링과 관련이 되어있기도 하지만 내가 얘기하려는 것은 TDD의 결과 중에 하나인 잘 만들어진 테스트 코드다. 잘 만들어진 테스트 코드가 있다면 리펙토링을 두려워할 필요가 없다.
"리펙토링 과정에서 변형된 코드로 인해 새로운 결함이 발생하지 않을까?"라는 걱정을 테스트 코드가 검증해 줄 것이다.
이러한 도구들을 잘 활용한다면 리펙토링을 잘 몰라도 일단 무작정 시작해 볼 수 있고 새로운 기쁨을 찾게될 것이다. 당연히 제대로된 리펙토링을 위해서는 차차 공부를 해야한다.
"시작이 반이다"라는 것을 알면서도 레펙토링을 두려워하고만 있다면 일단 도구들을 준비해서 시작해보자.
한가지 고민은 앞서 말한 도구들이 하나하나가 공부꺼리라는 것. 배보다 배꼽이 더 큰 상황이 될지도... 하지만 프로그래머라면 필수인 것들...
마틴파울러(Martin Fowler)는 이렇게 말했다.
"컴퓨터가 이해할 수 있는 코드는 어느 바보나 다 짤 수 있다. 좋은 프로그래머는 사람이 이해할 수 있는 코드를 짠다."
그래서 나는 이렇게 말하고 싶다.
"리펙토링을 두려워하지 말자"
처음부터 모든 것을 잘하는 사람은 없다. 많이 부딪치고 실수하고 깨지면서 경험을 쌓고 발전하는 것이다.