리팩터링 원칙

Minju Kim·2022년 12월 14일
2

리팩터링 2판

목록 보기
2/3
post-thumbnail
post-custom-banner

1. 리팩토링 정의

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

  • 목표 : 1) 코드의 복잡성 감소 2) 가독성 향상 3) 유지 보수성을 개선 4) 확장성을 높임
  • 금지 : 기능 변경/추가, 버그 수정, 성능 개선, 버전 업데이트
  • 함수 추출하기 , 조건부 로직을 다형성으로 바꾸기 처럼 이름 붙은 리팩터링 기법들이 이 정의에 해당한다.
  • 더 단순하고, 깔끔하고, 표현력이 뛰어난 코드, 내부 아키텍처/객체 모델을 만듬

2. 리팩토링이 왜 필요할까?

요약

  • 개발 초기 단계부터 완벽한 코드/시스템 설계의 어려움
  • 프로그램의 요구사항은 꾸준히 변경됨 (기능 추가/변경)
  • 더럽고 복잡한 코드는 이해하기 어려움
  • 예상하지 못한 에러가 발생하기 쉬움
  • 복잡한 코드의 유지보수는 어려움(수정 시간이 오래걸림)

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

  • 코드만 봐서는 설계를 파악하기 어려워지며, 코드 구조가 무너지면 악효과가 누적된다.
  • 같은 일을 하더라도 설계가 나쁘면 코드가 길어지기 십상이다.
  • 중복 코드를 제거하면 모든 코드가 언제나 고유한 일을 수행함을 보장할 수 있으며, 이는 바람직한 설계의 핵심이다.

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

  • 코드를 이해하기 쉽다는 말은 버그를 찾기 쉽다는 말이기도 하다.
  • 코드가 하는 일을 깊이 파악하게 되면서 새로 깨달은 것을 곧바로 코드에 반영하게 된다.

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

  • 내부 설계가 잘 된 소프트웨어는 새로운 기능을 추가할 지점과 어떻게 고칠지를 쉽게 찾을 수 있다.
  • 모듈화가 잘 되어 있으면 전체 코드베이스 중 작은 일부만 이해하면 된다.
  • 코드가 명확하면 버그를 만들 가능성도 줄고, 디버깅도 쉽다.
  • 내부 품질이 뛰어난 코드베이스는 새 기능 구축을 돕는 견고한 토대가 된다.

3. 어떻게 리팩토링을 하는걸까?

소프트웨어 기능을 보존하면서 설계, 구조 및 구현을 개선

  • 코드의 나쁜 냄새에 따라 여러 리팩토링 기법을 점진적으로 적용해 나가면 된다.
  • 중간중간에 기존 프로그램의 기능과 동작이 잘 유지되는지 확인해 주어야 한다. (테스트 코드를 마련한 후, 테스트 코드를 기반으로 확인한다.)

4. 언제 리팩토링해야 할까?

요약

“수시로!”

  1. 프로젝트 시작단계 : 기능 구현을 위한 코드를 작성 → 테스트 코드를 작성하고 코드리뷰, 기능추가시 잘 이해할 수 있고 재사용성 높이는 방향으로 리팩토링을 한다.
  2. 프로젝트 유지보수 단계 : 버그를 검증할 수 있는 테스트 코드를 작성하고, 코드를 이해하기 쉽게, 변경하기 쉽게 변경한다. 그 후 기능을 추가한다.
  3. 오래된 프로젝트 : 수정이 필요한 모듈/코드 한정적으로 테스트 추가. 그 이후 리팩토링 하고 코드 수정 또는 기능 추가를 한다.

3의 법칙

비슷한 일을 세 번째 하게 되면 리팩토링 한다.

1) 처음에는 그냥 한다.

2) 비슷한 일을 두 번째로 하게 되면, 일단 계속 진행한다.

3) 비슷한 일을 세 번째 하게 되면 리팩터링 한다.

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

리팩터링하기 가장 좋은 시점은 코드베이스에 기능을 새로 추가하기 직전이다. 이 시점에 현재 코들르 살펴보면서, 구조를 살짝 바꾸면 다른 작업을 하기가 훨씬 쉬워질 만한 부분을 찾는다.

버그를 잡을 때도 마찬가지다. 오류를 일으키는 코드가 세 곳에 복제되어 퍼져 있다면, 우선 한 곳으로 합ㅊ치는 편이 작업하기에 훨씬 편하다.

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

코드를 수정하려면 먼저 그 코드가 하는 일을 파악해야 한다. 코드를 파악할 떄마다 그 코드의 의도가 더 명확하게 드러나도록 리팩터링할 여지는 없는지 찾아본다.

3) 쓰레기 줍기 리팩터링

코드를 파악하던 중에 일을 비효율적으로 처리하는 모습을 발견할 때가 있다. 간단히 수정할 수 있는 것은 즉시 고치고, 시간이 좀 걸리는 일은 짧은 메모만 남긴 다음, 하던 일을 끝내고 나서 처리한다.

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

앞에서 본 리팩터링은 모두 기회가 될 때에만 진행하는 리팩터링이다. 그러나 기능을 추가하거나 버그를 잡는 동안 리팩터링도 함께 하는게 좋다. 프로그래밍 과정에 자연스럽게 녹이는 것이다.

보기 싫은 코드를 발견하면 리팩터링하자. 그런데 잘 작성된 코드 역시 수많은 리팩터링을 거쳐야 한다.

5) 오래 걸리는 리팩터링

팀 전체가 달려들어도 몇 주는 걸리는 대규모 리팩터링도 있다. 이런 상황에 처하더라도 팀 전체가 리팩터링에 매달리는 데는 회의적이다. 그보다는 주어진 문제를 몇 주에 걸쳐 조금씩 해결해가는 편이 효과적일 때가 많다.

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

코드 리뷰는 개밡팀 전체에 지식을 전파나는 데 좋고, 다른 이의 코드를 리뷰하는 데도 도움이 된다.

그리고 PR 리뷰모다는 짝 프로그래밍으로 진행되는 리뷰 형태에서 더욱 효과적일 수 있다. 프로그래밍 과정 안에 지속적인 코드 리뷰가 녹아있기 때문이다.

7) 관리자에게는 뭐라고 말해야 할까?

소프트웨어 개발자는 프로다. 프로 개발자의 역할은 효과적인 소프트웨어를 최대한 빨리 만드는 것이다. 리팩터링하면 소프트웨어를 빠르게 만드는 데 아주 효과적이다. 새 함수를 추가하려는데 현재 설계가 적합하지 않다면 먼저 리팩터링하고 나서 함수를 추가하는 편이 빠르다. 버그를 수정하려면 현재 소프트웨어의 작동 방식을 이해해야 한다. 이때도 리팩터링부터 하는 편이 가장 빠르다.

프로 개발자에게 주어진 업무는 새로운 기능을 빠르게 구현하는 것이고, 가장 빠른 방법은 리팩터링이다. 그래서 리팩터링부터 한다.

8) 리팩터링하지 말아야 할 때

지저분한 코드를 발견해도 굳이 수정할 필요가 없다면 리팩터링하지 않는다. 리팩터링하는 것보다 처음부터 새로 작성하는 게 쉬울 때도 리팩터링하지 않는다.

5. 리팩토링의 중요한 포인트!

요약

무결점 클린코드, 완벽한 설계는 존재하지 않는다를 인정!

YAGNI(You Ain’t Gonna Need It)

  • 깨끗하게, 변경이 쉽게, 유지보수 용이하게 만드는 것은 좋지만, 지금 당장 필요하지 않는 기능, 지나치게 미래지향적인 방향으로 만들면서 시간을 낭비하지 않는다.

리팩터링은 좋은 기법이지만, 이에 딸려오는 문제도 엄연히 있기에, 이런 문제가 언제 발생하고 어떻게 대처해야 할지를 반드시 알고 있어야 한다.

1) 새 기능 개발 속도 저하

리팩터링의 궁극적인 목적은 개발 속도를 높여서, 더 적은 노력으로 더 많은 가치를 창출하는 것이다. 그렇더라도 상황에 맞게 조율해야 한다. 예를 들어 리팩터링이 필요해 보이지만, 추가하려는 새 기능이 아주 작아서 기능 추가부터 하고 싶은 상황에 마주칠 수 있다. 이럴 때는 프로 개발자로서 가진 경험을 잘 발휘해서 결정해야 한다.

내가 직접 건드릴 일이 거의 없거나, 불편한 정도가 그리 심하지 않다고 판단되면 리팩터링 하지 않는게 나을 수 있다.

리팩터링은 오로지 경제적인 이유로 하는 것이다. 리팩터링은 개발 기간을 단축하고자 하는 것이다. 기능 추가 시간을 줄이고, 버그 수정 시간을 줄여준다.

2) 코드 소유권

팀원이라면 누구나 팀이 소유한 코드를 수정할 수 있어야 한다.

3) 브랜치

기능별 브랜치의 통합 주기를 2~3일 단위로 짧게 관리해야 한다고 주장하는 사람이 많은데, 마틴 파울러는 이보다 더 짧게 통합해야 한다고 주장한다. 이 방식을 지속적 통합(Continuous Integration)또는 트렁크 기반 개발(Trunk-Based Development)이라 한다.

마스터를 건강하게 유지하고, 거대한 기능을 잘게 쪼개는 법을 배우고, 각 기능을 끌 수 있는 기능 토글을 적용하여 완료되지 않은 기능이 시스템 전체를 망치지 않도록 해야 한다.

CI와 리팩터링을 합쳐서 익스트림 프로그래밍(eXtreme Programming(XP))이라고 한다.

4) 테스팅

리팩터링의 두드러진 특성은 프로그램의 겉보기 동작은 똑같이 유지된다는 것이다. 여기서 핵심은 오류를 재빨리 잡는 데 있다. 리팩터링하기 위핵서는 자가 테스트 코드를 마련해야 한다는 뜻이다.

테스트 코드는 리팩터링을 할 수 있게 해줄 뿐만 아니라, 새 기능 추가도 훨씬 안전하게 진행할 수 있도록 도와준다.

5) 레거시 코드

레거시 시스템을 파악할 때 리팩터링이 굉장히 도움된다. 하지만 조금의 수정이 큰 재앙을 불러 일으킬 수 있기에, 테스트 보강이 필요하다. 프로그램에서 테스트를 추가할 틈새를 찾아서 시슽템을 테스트해야 한다.

서로 관련된 부분끼리 나눠서 하나씩 공략하는 방법이 좋다. 코드의 한 부분을 훑고 넘어갈 때마다 예전보다 조금이라도 개선하려고 노력한다.

profile
⚓ A smooth sea never made a skillful mariner
post-custom-banner

0개의 댓글