chapter 2 리팩터링 원칙

이민택·2021년 3월 14일
1
post-thumbnail

2.1 리팩터링 정의

리팩터링이란 어플리케이션 외부에서 동작하는 기능은 유지한 채 코드의 가독성, 유지 보수성을 높여주도록 코드의 구조를 바꾸는 것이다

  • refactoring 과 restructuring 의 다른점
    • restructuring 은 코드를 정리하거나 구조를 바꾸는 모든 작업을 이야기한다
    • refactoring 은 기존에 작동하는 기능은 유지한채 코드의 가독성과 유지보수성을 높이는데 초점을 맞춰서 코드의 구조를 바꾸는 것이다

2.2 두 개의 모자

저자는 소프트웨어를 개발하면서 두가지 경우를 명확히 나누어서 개발한다고 한다 하나는 '기능추가', 다른 하나는 '리팩터링' 이다 이 두가지를 가지고 '두가지 모자' 라고 부른다고 한다 이렇게 두가지를 명확하게 구분해서 작업을 한다 기능 추가를 할 때에는 기존의 코드를 무조건 건들지 않고 새 기능을 추가한다 리팩터링을 할 때는 새로운 기능을 추가하지 않는다

2.3 리팩터링하는 이유

  • 리팩터링을 하면 소프트웨어 설계가 좋아진다.
  • 리팩터링하면 소프트웨어를 이해하기 쉬어진다.
  • 리팩터링하면 버그를 쉽게 찾을 수 있다.
  • 리팩터링하면 프로그래밍 속도를 높일 수 있다.(구조 파악이 쉬우면 기능 추가 역시 간다하다)

위 와 같은 장점은 모두 가독성과 유지보수성이 높아지면서 발생하는 이점이다 코드를 리팩터링해주지 않으면 설계를 유지하기 힘들다 (저자는 리팩터링을 하지 않으면 내부 설계가 썩기 쉽다고 표현한다)

2.4 언제 리팩터링해야 할까?

저자는 한 시간 간격으로 리팩터링한다고 한다 리팩터링을 해야할 시기를 아래와 같이 설명한다

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

이 적용 시점은 새로운 기능을 추가하기 바로 직전을 의미한다 어떤 기능을 추가할 때 구조를 조금만 바꾸면 적용하기 쉬워질만한 부분을 찾아서 수정하는 것이다

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

이미 작성된 코드의 의도가 좀 더 명확하게 전달되기 위해 작성하는 리팩터링을 의미한다

쓰레기 줍기 리팩터링

코드를 파악하던 도중 비효율적으로 처리하는 모습을 발견했을 때이다
이 때 주의할 점은 원래하려던 작업에 비해 너무 많은 시간을 사용할 것 같다면 메모해놓고 즉시 수정가능한 곳을 수정한다

예시: 매개변수화한 함수 하나면 될 일을 거의 똑같은 함수 여러 개로 작성해 놨을 경우

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

저자는 리팩토링을 프로그래밍의 하나의 일부라고 생각하기 때문에 굳이 계획해서 리팩토링을 하지 않는다고 했다, 그러나 프로그램이 매우 곪아서 수정해야될 곳이 많은 경우라면 여러명이 정기적으로 달려들어야 될 경우도 있다

  • 잘 작성된 코드라고해도 깔끔하게 짜여진 기준이 다를 수 있으므로 잘짜여진 코드 또한 리팩터링해야된다.
  • 새로운 기능을 추가하는 가장 빠른길은 기능을 추가하기 쉽게 코드를 수정하는 것이다

오래 걸리는 리팩터링

라이브러리 교체, 공유를 위한 컴포넌트 분리, 의존성 정리 등등 여러 경우가 있다 이런 경우 팀전체가 리팩터링에 매달리는 것 보다 몇주에 걸쳐 조금씩 해결하는 것이 효율적이다. 리팩토링의 기존의 코드를 깨뜨리지 않는 장접을 이용

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

코드 리뷰를 통해 리팩토링을 활용하다 보면 떠올린 아이디어의 모습을 명확하게 확인할 수 있고 한차원 높은 아이디어를 도출할 수 있다. 이 리뷰에서는 pr 방식 보다 페어 프로그래밍 형식으로 해야 작성자에게 맥락을 설명해 주기 좋다

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

저자는 리팩토링의 가치를 이해한 관리자에게는 말해도 상관없지만 그렇지 않은 관리자에게는 굳이 이야기하지 않는 것이 좋을 수 있다고 한다.

리팩터링 하지 말아야 할 때

외부 API 다루듯 호출해서 쓰는 경우( 해당 코드에 대한 이해가 되지 않았을 때),리팩터링하는 것 보다 새로 작성하는게 쉬울 경우이다 그러나 이는 작성하기 전까지는 오로지 뛰어난 경험의 의해서만 판단할 수 있다

2.5 리팩터링 시 고려할 문제

새 기능 개발 속도 저하

리팩토링의 본질적인 목표는 새로운 기능 추가에 대한 시간 절감 과 버그 수정 시간 절감이 있다 그러나 이런 점을 직접 실무에서 경험하지 않고서는 이런 생각을 가지기는 쉽지 않다 그래서 개발팀의 리더라면 이런 생각을 자신의 팀원들이 가질 수 있게 잘 이끌어줘야 한다

코드 소유권

코드의 소유권이 자신에게 있지 않는 경우나 어디서 호출하는지도 명확하지 않느 코드는 리팩터링하기 난감할 수 있다. 이럴 때는 기존 함수를 유지하면서 함수 내부에서 호출하는 방법도 있다. 그러나 이런 번거로운 방식 말고 오픈소스처럼 코드 수정 권한을 팀에게 주면 이런 일을 좀 더 유연하게 처리 할 수 있다 이 방식을 적용할 때는 각 팀원에게 권한에 따른 책임생긴다

브랜치

리팩토링을 적용하기 위해서는 CI 방식을 적용하는게 더 건전한 코드베이스를 만들기 수월하다 리팩터링 과정은 자잘하게 수정해야될 부분이 많기 때문이다

테스팅

리팩터링 과정에서 기존에 작동하는 기능이 정상적으로 확인이 가능한지 지속적으로 체크해야되기 때문에 자가 테스트 코드가 필요하다

레거시 코드

레거시 시스템을 파악할 때는 리팩터링이 굉장히 도움된다 그러나 이는 테스트 코드가 존재했을 경우 해당한다 그래서 레거시를 리팩터링하고 싶다면 테스트 코드를 작성해야한다 하지만 테스트는 초기 설계당시 염두하지 않고 작성했다면 테스트를 추가하는 조차 힘들수 있다 이를 위해서는
테스트를 추가 할 수 있는 틈새를 만들어야 된다는 것이다 ("레거시 코드 활용")

레거시를 리팩터링할 때 코드를 훑는 횟수가 많은 부분을 리팩터링했을 때 그 효과가 크다

데이터베이스

데이터베이스의 리팩터링은은 마이그레이션 스크립트와 관련있다 이 과정을 기존 리팩터링 처럼 잘게 쪼개고 새로운 필드의 추가를 위해 마이그레이션 수정 클라이언트 수정을 맞춰가면서 새 필드 업데이트에 대한 데이터 베이스 리팩터링을 진행 할 수 있다 이런 방식을 병렬 수정 이라고 한다

2.6 리팩터링, 아키택쳐, 애그니(YAGNI)

애그니 방식은 사용자의 요구사항을 맞게 간결하게 설계하고 이를 점진적으로 리팩터링으로 좀 더 구체적인 요구사항과 설계를 반영하는 방식이다 이는 설계를 소홀이 하라는 뜻은 아니므로 주의가 필요

2.7 리팩터링과 소프트웨어 개발 프로세스

애자일 방법론을 제대로 적용하려면 리팩터링에 대한 팀의 역량과 열저이 뒷받침되어야 프로세스 전반에 리팩터링이 스며 들 수 있다

자가 테스트 코드, 지속적 통합(CI), 리팩터링은 서로 강력한 시너지 효과를 내며 이느 또 애그니(YAGNI)와 궁합이 잘맞는다
간결하게 요구사항에 맞게 짠 코드가 리팩터링과 통합이 훨씬 쉽기 때문이다

2.8 리팩터링과 성능

리팩터링을 통해 성능이 느려질 수 도 있지만 그와 동시에 성능을 튜닝하기도 더 쉬워진다 그래서 튜닝을 하고 싶다면
튜닝하기 쉽게 리팩터링 먼저 해야된다 (성능 튜닝 과정은 아래와 같다)

  • 리팩터링 기준에 맞춰 프로그램을 리팩터링한다
  • 리팩터링이 완료되면 프로파일러를 이용해서 시간과 공간을 많이 잡아먹는 부분을 파악한다
  • 리팩터링과 마찬가지로 이 부분의 최적화를 단계별로 쪼개서 진행한다

리팩터링이 최적화에 도움이 되는 점
1. 성능 튜닝에 투입할 시간을 벌 수 있다
2. 세밀하게 분석이 가능하다 => 프로파일러가 지적하는 코드의 범위가 좁아진다

2.9~10 리팩터링의 유래, 리팩터링 자동화

리팩터링은 스몰토크 커뮤니티에서 유래 되었다, 최초의 연구는 빌 옵다이크 라는 박사과정 학생이 자신의 프로그램을 개발하기 위해 리팩터링 기법을 연구, 최신 ide에는 리팩터링 자동화 기능이 있기 때문에 활용하면 테스트 작성의 시간을 줄여 줄 수 있다 그러나 완전한 신뢰보단 자동화된 리팩터링과 수동화 리팩터링을 함께 사용하는 것이 바람직하다

profile
데이터에 소외된 계층을 위해 일을 하는 개발자를 꿈꾸는 학생입니다

0개의 댓글