thumbnail
리팩터링 원칙
JavaScript
2023.10.05.

리팩터링 원칙

리팩터링 정의

  • 저자 마틴 파울러가 생각하는 리팩터링의 정의는 일반적으로 통용되는 리팩터링의 의미와는 다소 다른 점이 있다.

  • 그가 책에서 언급하는 리팩터링은 명사, 동사형 버전이 있다.

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

    리팩터링: [동사] 소프트웨어 겉보기 동작은 그대로 유지한 채, 여러 가지 리팩터링 기법을 적용해서 소프트웨어를 재구성하다.

  • 일반적으로 통용되는 의미는 코드 정리 작업 전반을 의미하지만, 저자는 정의에 기반한 특정 방식에 의한 코드 정리만을 리팩터링이라고 한다. 전자의 경우는 리스트럭쳐링 또는 재구성(restructuring)이라는 포괄적 표현을 사용하길 선호한다고 말한다.

  • 리팩터링에 있어서 가장 중요한 점은 겉보기 동작(observable behavior)이며, 이는 리팩터링 전 후 코드가 똑같이 동작해야함을 의미한다. (심지어 리팩터링 과정 발견된 버그 조차, 리팩터링 후에는 그대로 남아있어야 한다. 단, 아무도 발견하지 못한 숨은 버그는 수정해도 괜찮다.)

리팩터링하는 이유

리팩터링하면 소프트웨어 설계가 좋아진다

  • 반대로 말하면 리팩터링하지 않으면 소프트웨어 내부 설계(아키텍처)가 썩기 쉽다. 규칙적인 리팩터링을 통해 코드 구조를 지탱해줄 필요가 있다.
  • 중복 코드 제거를 통해 코드량을 감소시키면 수정하는데 드는 노력을 줄일 수 있고, 고유한 일을 수행함을 보장할 수 있다.

리팩터링하면 소프트웨어를 이해하기 쉬워진다

  • 프로그래밍은 컴퓨터와의 대화와도 같다. 즉, 컴퓨터에게 시키려는 일과 이를 표현한 코드간의 간격을 줄여야 한다. 하지만 소스 코드는 컴퓨터만 보는 것이 아니라, 다른 프로그래머도 보기 때문에 이를 배려할 필요가 있다.
  • 프로그램 동작에만 신경써서 코드를 작성하면 다른 프로그래머, 혹은 대부분의 경우 나 스스로 이해하지 못하는 경우도 종종 발생한다. 그렇기 때문에 리팩터링을 통해 이해하기 쉬운 코드를 작성할 필요가 있다.

리팩터링하면 버그를 쉽게 찾을 수 있다.

  • 리팩터링을 통해 프로그램 구조를 다듬다 보면, 어디서 버그가 발생하는지 좀 더 명확하게 파악할 수 있게 된다. 견고한 코드 작성을 위해서도 리팩터링은 필요하다.

리팩터링하면 프로그래밍 속도를 높일 수 있다.

  • 흔히 리팩터링을 하면 전체 개발 속도가 떨어질까봐 걱정하지만, 새로운 기능 추가를 염두에 둔다면 전체적인 프로그래밍 개발 속도는 더욱 빨라질 수 밖에 없다.
    • 가령, 기존 코드베이스가 복잡하여 분석하는데 걸리는 시간, 방법을 찾는 시간, 버그 발생 시 해결 시간이 복잡한 코드에서는 늘어날 수 밖에 없다. 하지만 리팩토링을 통해 이를 예방할 수 있다.

언제 리팩터링해야 할까?

준비를 위한 리팩터링 : 기능을 쉽게 추가하게 만들기

  • 가장 좋은 시점은 코드베이스에 기능을 새로 추가하기 직전이다. 구조를 살짝 바꾸면 다른 작업을 하기 훨씬 쉬워질 만한 부분을 찾는다.

이해를 위한 리팩터링 : 코드를 이해하기 쉽게 만들기

  • 코드의 의도가 명확하게 드러나도록 리팩터링 할 여지는 없는지 찾아본다.

쓰레기 줍기 리팩터링

  • 간단히 수정할 수 있는 것은 즉시 고치고, 시간이 좀 걸리는 일은 짧은 메모와 함께 하던 일 처리 후 처리하는 방식을 쓰레기 줍기 리팩터링(Litter-Pickup Refactoring)이라 한다.
  • 코드를 훑어볼 때 마다 조금씩 개선하다 보면 결국 문제는 해결된다.

계획된 리팩터링과 수시로 하는 리팩터링

  • 리팩터링은 프로그래밍과 구분되는 별개의 활동이 아니기 때문에 대부분의 리팩터링을 다른 일을 하는 중에 처리한다.
  • 보기 싫은 코드를 발견하면 리팩터링한다.
  • 잘 작성된 코드 역시 수많은 리팩터링을 필요로 한다.
  • 소프트웨어 개발은 추가하는 과정으로만 여겨지기 쉽지만, 뛰어난 개발자는 새 기능을 추가하기 쉽도록 코드를 수정한다.
  • 리팩터링 작업 대부분은 드러나지 않게, 기회가 될 때마다 해야 한다.
  • 리팩터링 커밋과 기능 추가 커밋을 구분하는 것은 장단점이 있기 때문에 팀에 적합한 방식을 찾아서 적용해야 한다.

오래 걸리는 리팩터링

  • 대부분의 리팩터링은 몇 분 안에 끝나고 길어야 몇 시간 정도지만, 가끔 대규모 리팩터링도 발생할 수 있다. 이때 저자는 팀 전체가 리팩터링에 매달리기 보다는 주어진 문제를 몇 주게 걸쳐 해결하는 것이 효과적으로 본다.

코드 리뷰에 리팩터링 활용하기

  • 리팩터링은 다른 이의 코드를 리뷰하거나 코드 리뷰 결과를 더 구체적으로 도출하는 데 도움이 된다.
  • 다만, pull request 방식 보다는 작성자와 함께 리뷰하는 방식이 더 효율적이다.

관리자 설득하기

  • 기술을 잘 아는 관리자라면 설득할 가치가 있지만, 그렇지 않은 경우에는 리팩터링한다고 하지 말고 리팩터링 하는 것을 권한다.
  • 프로 개발자의 역할은 효과적인 소프트웨어를 최대한 빨리 만드는 것이기 때문에, 구체적인 방법은 개발자가 판단해야 한다.
  • 프로 개발자에게 주어진 임무는 새로운 기능을 빠르게 구현하는 것이고, 가장 빠른 방법은 리팩터링이다.

리팩터링하지 말아야 할 때

  • 굳이 수정할 필요가 없는 코드 (호출해서 사용하는 코드), 처음부터 새로 작성하는 게 쉬운 코드 등의 경우에는 리팩터링 안하는 것이 낫다.

리팩터링 시 고려할 문제

새 기능 개발 속도 저하

  • 리팩터링의 궁극적인 목적은 개발 속도를 높여서, 더 적은 노력으로 더 많은 가치를 창출하는 것이다.
  • 저자는 기능 추가와 리팩터링의 판단의 균형점을 잡기를 권유하지만 쉽지 않다고 말한다.
  • 저자는 리팩터링은 경제적인 이유(개발 생산성) 때문에 하는 것이라고 주장한다.

코드 소유권

  • 코드 소유권이 나뉘어 있으면 리팩터링에 방해가 되는데, 이 때문에 저자는 코드 소유권을 작은 단위로 나눠 엄격히 관리하는 데는 반대한다.
    • 코드 소유권을 팀에 두어서 누구나 수정할 수 있게 하기를 권한다.

브랜치

  • 지속적 통합(CI, Continuous Integration), 트렁크 기반 개발(TBD, Trunk-Based Development) 방식을 권유한다.
    • 이 방법을 사용하기 위해서는 마스터 브랜치를 건강하게 유지하고, 거대한 기능을 잘게 쪼개고, 각 기능을 끌 수 있는 토글(기능 플래그)를 적용하여 완료되지 않은 기능이 시스템 전체를 망치지 않도록 해야 한다.
    • CI, TBD는 리팩터링과 궁합이 좋으며, 통합 주기를 가능한한 짧게 가져가는 것이 핵심이다.

테스팅

  • 리팩터링의 가장 큰 특징은 프로그램의 겉보기 동작은 똑같이 유지되어야 한다는 점이다. 따라서 리팩터링 과정에서 오류가 발생하면 빨리 잡아야 하고, 이를 위한 자가 테스트 코드(Self-testing code)가 필요하다.
  • 자가 테스트 코드는 버그에 대한 불안감을 해소시킬 수 있고, CI&CD의 핵심 요소이기도 하다.

레거시 코드

  • 레거시 시스템 파악 시 리팩터링은 도움이 된다.
  • 대규모 레거시 시스템을 리팩터링 할 때는 테스트 코드가 필요한데, 쉽지 않은 것은 사실이다. 이를 위한 조언으로 저자는 프로그램에서 테스트를 추가할 틈새를 찾아서 시스템을 테스트해야 한다고 말한다.(『레거시 코드 활용 전략』(에이콘, 2018) 참조)
  • 안전한 자동 리팩터링 도구를 사용하는 것도 한 가지 방법이다.

그 외 내용 요약

위에 정리한 내용 외에도 리팩터링 도서의 해당 챕터에는 리팩터링 지식 관련 다양한 내용들이 포함되어 있지만, 이 포스트에 모두 다루는 것은 비효율적이기 때문에 일부 생략하기로 했다. 대신 저자가 말하고자 하는 핵심은 다음과 같이 정리할 수 있다.

  • 리팩터링은 더욱 코드를 빠르게 생산할 수 있는 경제 효과를 가져온다.
  • 최근에는 자동 리팩터링 도구들이 발달해서 잘 사용하는 것이 좋지만, 일부 문제가 발생할 수 있기 때문에 테스트를 통한 보완을 필요로 한다.
  • 본서 외에 참고할만한 도서로는 『리팩터링 워크북』(인사이트,2006), 『패턴을 활용한 리팩터링』(인사이트,2011), 『리팩터링 데이터베이스』(위키북스,2007), 『레거시 코드 활용 전략』(에이콘, 2018) 같은 것들이 있다.

© 2022 Developer Abel, Powered By Gatsby.