Books/리팩토링

리팩토링이 뭐에요?

softserve 2023. 6. 29. 08:48
반응형

리팩토링이 무엇인가

 

리팩토링은 ‘코드를 개선하는 작업’을 일컫는 말입니다. 변수의 이름을 알아먹기 쉽게 바꾸는 것도 리팩토링이라고 할 수 있습니다. 조금 더 정확하게 얘기해 보면 리팩토링은 ‘코드의 역할은 유지하면서 나중에 쉽게 수정할 수 있도록 그 구조를 고쳐나가는 체계적인 작업’ 이라고 할 수 있습니다.

코드를 개선하는 작업의 대전제는 코드가 가지고 있던 기존의 역할을 그대로 유지해야 한다는 것입니다. 시간을 들여 작업을 했더니 잘 작동하던 프로그램이 원래 기능을 수행하지 못하게 되거나 오류가 발생한다면 안 하느니만 못한 일이 되어버립니다.

‘개선된 코드’란 그 목적에 따라서 다양한 형태가 될 수 있습니다. 성능 최적화를 위해 개선된 코드는 읽고 수정하기 어려워질 수 있고 반대로 가독성을 높이기 위한 개선은 성능을 떨어뜨릴 수도 있습니다. 리팩토링은 코드의 가독성과 유지보수성을 높여 수정하기 쉬운 코드를 만드는 데 그 목적이 있습니다.

구조를 고친다라고 뭉뚱 그려 표현했지만 마틴 파울러의 ‘리팩토링’에서는 앞서 말한 것처럼 변수명을 변경하는 작업에서부터 코드 덩어리에서 함수를 추출하고 종류별로 묶고 계층 구조를 수정하는 작업에 이르기까지 다양한 기법과 패턴에 대해 설명하고 있습니다.

리팩토링은 절차에 따라 체계적으로 이루어지는 작업입니다. 리팩토링이란 개발의 고수가 홀연히 나타나 여러분이 작성한 코드를 보면서 ‘코드가 더럽군!’ 하며 단 한 번의 타이핑만으로 수백 줄의 코드를 뜯어고치는 것이라기보다는, 작게 나눠진 단계들을 하나하나 수행하면서 코드가 동일하게 작동하는지 테스트하고 커밋하는 과정을 반복하는 것에 가깝습니다.

 

리팩토링이 왜 필요한가

 

1. 설계를 바로잡을 기회

 

리팩토링은 코딩 이후의 설계라고 할 수 있습니다. ‘클린 아키텍쳐’를 읽으며 “이미 설계는 다 끝났는데 내가 뭘 어떻게 할 수 있나?” 하는 의문을 가졌던 사람들에게 “지금이라도 고치면 된다!”라는 깨달음을 주는 말이죠. 귀찮으니 그냥 이대로 살면 안 되냐고요? 안 됩니다.

코드가 살아있는 한 개선은 계속 되어야 한다

몇 날 며칠을 밤새워가며 작성한 자식같은 코드를 죽이고 싶으신 게 아니라면 지속적인 관심과 사랑을 주셔야 합니다. 아무리 처음부터 완벽하게 설계된 코드라고 하더라도 여러 사람에 의해 새로운 기능이 추가되고 수정되는 과정을 계속 거치다 보면 설계가 무너지기 마련입니다. 이럴 때 리팩토링을 통해서 죽어가는 코드에게 생명력을 불어넣어 줄 수 있습니다.

설계가 제대로 되어있지 않은 코드는 다른 사람, 심지어 본인마저도 읽고 내용을 파악하는 데 어려움을 겪게 됩니다. 따라서 기능을 추가하는 데 더 긴 시간이 걸리고 사소한 수정으로도 오류가 발생할 위험이 커집니다.

저는 한번씩 실수를 할 때마다 회고를 하면서 어떤 점이 문제였고 어떻게 고쳐야 할지를 정리합니다. 그 원인이 제 부주의 때문이었던 경우도 있지만 코드베이스 설계 자체에 문제가 있는 경우도 많았습니다. 그래서 내가 한번 뜯어고쳐 봐야겠다 결심을 하고 리팩토링을 공부하고 있습니다.

 

2. 코드는 사람도 읽는다

 

최근(이라고 썼지만 거진 10년 동안) 채용 공고에서 많이 찾아볼 수 있는 단어가 협업, 커뮤니케이션입니다. 그만큼 프로젝트 규모가 커지고, 여러 개발자가 함께 작업을 하는 경우도 많아졌기 때문이겠죠. 소통은 대면회의나 화상회의, 메신저나, 이메일 등 다양한 매체를 통해서 이루어지지만 개발자들은 주로 코드를 통해서 소통을 합니다.

개발자가 1명 뿐인 작은 회사라고 해도 코드만 남겨놓고 떠나간 사람과의 소통이 필요합니다. 막힌다고 전화해서 물어볼 수도 없기 때문에 얼마나 코드를 깨끗하게 작성했느냐가 중요하게 됩니다. 코드가 엉망이라 무슨 목적을 가지고 작성한 것인지 파악하기 어려운데 연락도 할 수 없고 아무런 기록도 남아있지 않고 기억하는 사람도 없어 난감한 상황에 처해보신 분들이라면 많이 공감하실 겁니다.

컴퓨터가 이해하는 코드는 바보도 작성할 수 있다.
사람이 이해하도록 작성하는 프로그래머가 진정한 실력자다

처음부터 완벽한 코드란 존재하지 않는 법이고 코드를 깨끗하게 만들기 위해 리팩토링이 필요합니다. 비록 나의 전임자는 엉망인 코드만 남겨놓고 떠나갔지만 내 후임한테는 보기 좋은 코드를 선물해주고 싶다는 생각을 많이들 하시게 될 겁니다. 그럴 때 유용하게 활용할 수 있는 도구가 리팩토링입니다.

3. 버그를 찾기 쉽고 개발 속도도 빨라진다.

 

사실 2. 이하의 내용들은 좋은 설계의 부수적인 효과라고 할 수 있습니다. 앞에서 말한 것처럼 중복을 최대한 제거하고 의존성을 낮추는 등 설계가 잘 된 코드는 사람이 이해하기도 쉽고, 버그가 명확하게 드러나게 됩니다. 리팩토링은 시간이 꽤 드는 작업이지만 장기적으로 보면 훨씬 시간을 절약할 수 있습니다.

이 부분을 읽으며 뼈저리게 공감을 할 수 있었던 것이, 제가 맡고 있는 서비스가 바로 이런 상황에 놓여있기 때문입니다.

처음 개발된 코드베이스 자체가 내포하고 있는 문제도 있지만, 여러 사람들의 손을 거치면서 새로운 기능이 추가되고 버그도 추가되고 프로그램이 커질수록 버그가 발견되는 횟수가 늘어나면서 차라리 새로 만들자는 이야기까지 나오는 상황입니다. 기능 하나를 추가하면 또 발견되지 않았던 문제점들이 튀어나오고 그 문제를 해결하면 가려져 있던 문제가 드러나고 여유가 없다 보니 급하게 수정한 것이 다시 버그를 낳고 하는 악순환이 거듭되면서 점점 코드를 알아보기 힘든 지경에 이르고 있죠.

 

리팩토링을 어떻게 하는가

 

기능을 추가하는 것과 리팩토링은 작업의 결이 다릅니다. 그래서 파울러 씨는 두 개의 모자라는 시적 표현으로 이를 설명하고 있습니다. 기능을 추가할 때는 기능 추가 모자를 쓰고 리팩토링을 할 때는 리팩토링 모자를 써서 오로지 그 목적에만 맞게 작업을 해야한다라는 거죠. 코드는 기존의 역할을 유지해야 합니다. 리팩토링을 거치더라도 동일하게 작동을 해야 하고 심지어 버그까지도 똑같이 존재해야 합니다(언젠가 고치긴 해야겠지만).

구체적인 방법론은 차차 알아가기로 하고, 큰 틀에서 리팩토링은 이렇게 이루어집니다.

1. 테스트코드를 작성한다

테스트를 하는 가장 간단한 방법은 프린트해서 값을 찍어보는 것입니다. 하지만 수 십 차례 테스트를 해야하기 때문에 테스트코드에서 직접 결괏값을 비교하고 이상 여부를 판단하도록 만드는 것이 필요합니다.

2. 다양한 기법으로 코드를 수정한다

3. 테스트하고 커밋한다

저는 건 단위로 개발을 하고 그 1건이 완료될 떄마다 커밋을 하고 있었는데 많은 분들이 생각보다 짧은 주기* 로 커밋을 하신다는 걸 알게 되었습니다. 커밋을 자주 하면 그 자체로 히스토리가 되고 나중에 문제가 생겼을 때 되돌리기도 쉽기 때문이겠죠. 

* 30분 ~ 1시간, 물론 시간을 재서 커밋을 하는 건 아니고 유의미한 변경이 있을 때마다 커밋을 하게 되는데 그 주기가 이 정도

4. 2번과 3번을 계속 반복하다가 문제가 발생하면 되돌린다.

 

반응형