이메일 보기
Book

리팩토링 2판 정리 - 테스트코드 구축하기

최종 수정일2024년 12월 14일

최근 테스트코드에 대해 관심을 가지고 공부를 하고 있습니다. 그리고 일주일 전 많은 개발자분들이 추천하는 책인 파틴 파울러의 리팩토링을 읽어보았는데요. 리팩토링에 앞서 테스트코드의 중요성을 강조하고 있다는 점에 상당히 놀랐습니다. ⌜테스트코드 구축하기⌟라는 챕터를 따로 할애할 정도로 말이죠. 오늘은 리팩토링 2판 챕터 4 ⌜테스트코드 구축하기⌟를 보며 리팩토링에서 왜 테스트코드가 중요한지, 어떻게 테스트코드를 구축해야 할 지 정리해 보겠습니다.

들어가기 전에


리팩토링 2판 표지

자바스크립트로 예시가 작성된 리팩토링 2판의 내용을 정리했습니다.


리팩토링과 테스트코드의 상관관계


리팩토링과 테스트코드, 도대체 어떤 관계가 있길래 한 챕터에서 테스트코드에 대한 이야기만 할까요? 일단 리팩토링의 정의에 대해 알아보겠습니다.


리팩토링이란?


리팩터링이란 소프트웨어의 겉보기 동작은 그대로 유지한 채, 코드를 이해하고 수정하기 쉽도록 내부 구조를 변경하는 기법입니다.


여기서 중요한 포인트는 겉보기 동작은 그대로 유지한다는 점입니다. 특히 버그가 보여도 리팩터링을 할 때에는 일단 무시하고 코드의 내부 구조만 변경해야 한다고 합니다. (하지만 아무도 발견하지 못한 버그라면 살짝 고쳐도 된다고 합니다🤭) 리팩토링을 하면서 기능이 변경되거나 코드가 깨지면 그것은 리팩터링이 아닌 것이죠.


리팩토링을 할 때 테스트코드의 역할


이때 테스트코드는 내부 구조가 변경되어도 기능이 문제 없이 동작한다는 것을 보장합니다. 작업을 하면서 수시로 테스트를 돌려 기능이 깨지는 시점을 빠르게 캐치하고 수정할 수 있으며 최종적으로 변경된 코드에 문제가 없음을 보장할 수 있게 됩니다.


혹시 코드를 수정하다 뒤늦게 기존 동작이 깨지는 경험을 해본 적이 있으신가요? 저는 그런 경험이 있는데요. 꽤 작업이 진행된 후라 언제부터 기능이 깨졌는지, 어느 부분이 문제인지 디버깅하느라 시간을 허비하게 되었습니다. 만약 테스트코드가 있었다면 문제가 발생할 당시에 바로 알아차려 수정할 수 있었을 것입니다.


이처럼 내부 구조를 손보는 리팩토링 작업을 할 때 테스트코드를 통해 불가피하게 저지르는 실수를 바로잡을 수 있습니다.


테스트코드 작성 시 중요 포인트


  1. 모든 테스트를 자동화하고 자주 테스트하자

책에서는 작성 중인 코드는 최소한 몇 분 간격으로 테스트하고 적어도 하루에 한 번은 전체 테스트할 것을 권장합니다. 추가한 코드에 문제가 없는지, 리팩터링을 하면서 실수한 것은 없는지 수시로 확인하며 디버깅 시간을 줄이고 코드의 안정성을 보장할 수 있기 때문입니다.


  1. 코드를 성격에 따라 분리하자

비즈니스 로직과 UI가 결합해 있다면 테스트코드도 자연히 복잡해질 것입니다. 이를 방지하기 위해 비즈니스 로직과 UI를 분리하는 등 성격에 따른 코드 분리가 필요합니다. 이렇게 테스트코드 작성을 위해 자연스럽게 좋은 코드를 작성하게 될 수 있다는 장점도 있습니다.


  1. 실패해야 할 상황에서는 반드시 실패하게 만들자

테스트코드를 작성하다 보면 테스트가 통과되는 기쁨에 취해 이 테스트코드가 정말로 요구사항을 잘 검증하고 있는지 놓칠 때가 있습니다. 때문에 일부러 테스트가 실패하는 모습을 확인하여 정말로 유의미한 테스트코드인지 확인해보는 과정이 필요합니다.


  1. 테스트는 위험 요소를 중심으로 작성하자

테스트코드를 도입하지 않은 경우 막막함에 아예 테스트코드 작성을 포기할 수도 있습니다. 하지만 완벽하게 만드느라 테스트를 수행하지 못하느니, 불완전한 테스트라도 작성하는 것이 낫다고 마틴 파울러는 이야기합니다. 모든 버그를 잡아낼 수 없다고 생각하여 테스트를 작성하지 않는다면 대다수의 버그를 잡을 기회를 날리는 것이라고 하면서 말이죠.


  1. 문제가 생길 가능성이 있는 경계 조건 검사하기

요구사항을 충족할 수 있도록 테스트코드를 작성하는 것도 중요하지만 문제가 생길만한 경계 조건을 검사해보아야 합니다. 예외나 실패가 존재하지 않은 happy path 상황에만 집중하면 다양한 예외 케이스에 대응할 수 없기 때문입니다. 함수에 인자를 넘기지 않는다거나 고객 수요 최솟값이 음수가 되는 등 범위를 벗어나는 경계 지점에서 문제가 생기면 어떤 일이 벌어지는지 확인하는 테스트코드를 작성하다보면 예외 상황을 어떻게 처리할지 고민할 수 있습니다. (마틴 파울러는 의식적으로 프로그램을 망가뜨리는 방법을 모색하며 생산성과 재미를 끌어올렸다고 합니다. 이런 게 바로 진짜 광기...?👻)


  1. 버그 리포트를 받으면 그 버그를 드러내는 단위 테스트부터 작성하자

충분한 테스트를 갖추었는지 판단하는 기준은 주관적입니다. 테스트 커버리지가 높다고 해서 안정적인 테스트 환경을 갖추었다고 확신할 수 없습니다. 그렇기에 '누군가 결함을 심으면 테스트가 발견할 수 있다는 믿음'을 가질 정도로 테스트코드를 구축해 둔 것 만으로도 테스트코드의 목적은 달성되었다고 할 수 있습니다.


포스팅을 마무리하며


이렇게 리팩토링 2판 챕터 4 ⌜테스트코드 구축하기⌟를 살펴보며 리팩토링에 있어 테스트코드가 왜 중요한 요소인지, 테스트코드 작성 시 중요하다고 생각되는 포인트들을 정리해 보았습니다. 테스트코드가 없는 환경에서 코드를 수정하며 디버깅에 애를 먹은 경험이 있기에 더욱 공감이 가는 내용이었던 것 같습니다. 이제 막 테스트코드를 공부하기 시작한 입장에서 그 필요성을 다시금 느끼게 된 계기도 되었고요. 이 외에도 좋은 코드를 작성하기 위한 꿀팁을 알고 싶으시다면 리팩토링 책을 읽어보시는 것을 추천합니다👍

게시글의 오류 지적, 내용 보충, 질문 등의 피드백은 언제나 환영입니다.
아래 댓글창 혹은 ysisys0202@gmail.com으로 남겨주세요.