본 내용은 마틴 파울러의 Refactoring 2판을 토대로 작성되었습니다.
리팩터링 원칙
리팩터링하는 이유
- 코드를 건강한 상태로 유지
- 다양한 용도로 활용
- 소프트웨어 설계가 좋아짐
- 리팩터링하지 않으면 내부 설계(아키텍처)가 썩기 쉬움
- 아키텍처를 충분히 이해하지 못한 채 단기 목표만을 위해 코드를 수정하다 보면 기반 구조가 무너지기 쉬움
- 설계를 파악하기 어려워질 수록 설계를 유지하기 어려워지고 설계가 부패되는 속도는 더욱 빨라짐
- 설계가 나쁘면 코드가 길어지고 같은 일을 하는 코드가 여러 곳에 나타남
- 중복 코드 제거는 설계 개선 작업의 중요한 한 축을 차지
- 중복코드를 제거하면 모든 코드가 언제나 고유한 일을 수행함을 보장할 수 있음
- 소프트웨어를 이해하기 쉬워 짐
- 컴퓨터에게 시키려는 일과 표현한 코드의 차이를 최대한 줄여야 함
- 프로그래밍에서는 사람이 제일 중요
- 프로그램을 동작시키는데에만 신경 쓰다 보면 나중에 그 코드를 다룰 개발자를 배려하지 못함
- 기억한 필요가 있는 것은 최대한 코드에 담기
- 버그를 쉽게 찾을 수 있음
- 프로그래밍 속도를 높임
- 새로운 기능을 추가할수록 기존 코드베이스에 잘 녹여낼 방법을 찾는 데 드는 시간이 늘어남
- 기능을 추가하면, 버그가 발생하는 일이 잦아지고 해결하는 시간은 한층 더 걸림
- 소프트웨어의 내부 품질이 좋아질 수록 새로운 기능을 추가할 지점과 어떻게 고칠지를 쉽게 찾을 수 있음
- 모듈화가 잘 되어 있으면 전체 코드베이스 중 작은 일부만 이해하면 됨
- 설계 지구력 가설
- 내부설계에 심혈을 기울이면 소프트웨어의 지구력이 높아져서 빠르게 개발할수 있는 상태를 오래 지속
언제 리팩터링해야 할까?
- 처음에는 그냥 한다 -> 비슷한 일을 세 번째 하게 되면 리팩터링 하라
- 삼진 리팩터링
- 준비를 위한 리팩터링: 기능을 쉽게 추가하게 만들기
- 리팩터링하기 좋은 시점은 기능을 새로 추가하기 직전
- 현재 코드를 살펴보며, 구조를 살짝 바꾸면 다른 작업을 하기가 훨씬 쉬어질 만한 부분을 찾음
- 이해를 위한 리팩터링: 코드를 이해하기 쉽게 만들기
- 코드의 의도가 더 명확하게 드러나도록 리팩터링할 여지는 없는지 찾아보기
- 리팩터링하면 머리를 이해한 것을 코드에 옮겨 담을 수 있음
- 쓰레기 줍기 리팩터링
- 간단히 수정할 수 있는 것은 고치고, 시간이 좀 걸리는 것은 짧은 메모만 남긴 다음 하던 일을 끝내고 나서 처리
- 처음 봤을 때보다 깔끔하게 정리하고 떠나기
- 조금씩 개선하다보면 문제가 해결
- 계획된 리팩터링과 수시로 하는 리팩터링
- 리팩터링은 모두 기회가 될 때만 진행
- 리팩터링 일정을 따로 잡아두지 않고, 기능을 추가하거나 버그를 잡는 동안 리팩터링도 함께 진행
- 프로그래밍 과정에 자연스럽게 녹이기
- 잘 작성된 코드 역시 수많은 리팩터링을 거쳐야 함
- 새 기능을 추가하기 쉽도록 코드를 수정하는 것이 그 기능을 가장 빠르게 추가하는 길
- 리팩터링에 소홀했다면, 따로 시간을 내어 코드베이스 개선
- 단, 계획된 리팩터링은 최소한으로 줄이기
- 버전 관리 시스템 리팩터링 커밋과 기능 추가 커밋을 분리? -> 팀에 적합한 방식을 정하기
- 오래 걸리는 리팩터링
- 라이브러리를 새 것으로 교체
- 컴포넌트 추출
- 의존성 정리
- 이런 상황애서도 팀 전체가 리팩터링에 매달리는 것은 회의적임
- 몇 주에 걸쳐 조금씩 해결하는 것이 효과적
- 누군드지 리팩터링해야할 코드와 관련한 작업을 하게 될 때마다 원하는 방향으로 조금씩 개선
- 추상화로 갈아타기(Branch By Abstraction)
- 라이브러리를 교체할 때는 기존 것과 새 것 모두를 포용하는 추상 인터페이스부터 마련
- 기존 코드가 추상 인터페이스를 호추하도록 만들면, 라이브러리르 훨씬 쉽게 교체
- 코드 리뷰에 리팩터링 활용
- 코드 리뷰는 개발팀 전체에 지식을 전파하는데 좋음
- 경험이 더 많은 개발자의 노하우를 전수
- 대규모 소프트웨어 시스템의 다양한 측면을 더 많은 사람들이 이해
- 다른 사람의 아이디어를 얻을 수 있음
- 리팩터링은 다른 이의 코드를 리뷰하는 데도 도움이 됨
- 풀 요청 모델(Pull Request Model)은 효과적이지 않음
- 참석하는 참석하는 방식이 좋음 -> 짝프로그래밍
- 관리자에게는 리팩터링한다고 말하지 말라?
- 리팩터링하지 말아야 할 때
- 굳이 수정할 필요가 없을 경우
- 처음부터 새로 작성하는 게 쉬울 때
- 리팩터링할지 새로 할지를 잘 결정하려면 뛰어나 판단련과 경험이 뒷받침되어야 함
리팩터링 시 고려할 문제
- 리팩토링에 딸려 오는 문제도 엄연히 있으므로 이 문제가 언제 발생하고 어떻게 대처해야 할지 반드시 알고 있어야 함
- 새 기능 개발 속도 저하
- 리팩터링이 필요해 보이지만, 추가하는 기능이 작아서 기능 추가부터 하고 싶은 상황일 경우 경험을 살려 결정
- 새 기능을 구현해넣기 편해지겠다 싶은 리팩터링이라면 주저하지 않고 하기
- 직접 건드릴 일이 없거나 불편한 정도가 그리 심하지 않으면 하지 않아도 됨
- 리팩터링을 클린코드나 바람직한 엔지니어링 습관처럼 정당화하지 않기
- 리팩터링은 오로지 경제적인 이유로 하는 것 -> 개발 시간 단축
- 코드 소유권
- 모듈의 내부뿐아니라 시스템의 다른 부분과 연동하는 방식에도 영향을 줄 수 있음
- 코드 소유권이 나뉘어 있으면 리팩터링에 방해가 됨
- 코드 소유권이 팀에 두는 것이 바람직
- 브랜치
- 기능 브랜치 방식은 작업 기간이 길어질 수록 마스터로 머지하기 어려워 짐
- 기능별 브랜치의 통합 주기를 2~3일 단위로 짧게 관리
- 지속적 통합(CI, Continuos Integration)
- 트렁크 기반 개발(TBD, Trunk-Based Development)
- CI에 따르면 모든 팀원이 하루에 최소 한 번은 마스터와 통합
- 브랜치간 차이가 적어져서 머지의 복잡도를 낮출 수 있음
- 마스터를 건강하게 유지하고 거대한 기능을 잘게 쪼개야하며 각 기능을 끌 수 있는 기능 토글을 적용하여 완료되지 않은 기능이 시스템 전체를 망치지 않도록 해야 함
- CI와 리팩터링은 궁합이 좋음
- CI + 리팩터링 -> 익스트림 프로그래밍(XP, eXtreme Programming)
- 테스팅
- 오류를 재빨리 잡기 위해서는 테스트 스위트(test suite)가 필요
- 자가 테스트 코드를 마련해야 함
- 자가 테스트 코드는 리팩터링과 새 기능 추가를 안전하게 진행할 수 있도록 도움
- 버그를 쉽게 찾을 수 있음
- 뛰어난 자동 리팩터링 기능을 제공하는 환경이라면 테스트 없이도 가능
- 검증된 몇 가지 리팩터링 기법만 조합해서 사용하자는 흐름도 등장
- CI에 통합된 테스트는 XP의 권장 사항이자 지속적 배포(CD, Continous Delivery)의 핵심
- 레거시 코드
- 레거시 코드는 대체로 복잡하고 테스트도 갖춰지지 않음
- 레거시 시스템 파악시, 리팩터링이 굉장히 도움
- 테스트를 추가할 틈새를 찾아 시스템을 테스트해야 함
- 이 틈새를 만들기 위해서 리팩터링 활용
- 캠핑 규칙에 따라 리팩터링
'programming study > Refactoring' 카테고리의 다른 글
Refactoring - 리팩터링 원칙(4) (0) | 2021.12.14 |
---|---|
Refactoring - 리팩터링 원칙(3) (0) | 2021.12.13 |
Refactoring - 리팩터링 원칙(1) (0) | 2021.12.11 |
Refactoring - 첫 번째 예시(2) (0) | 2021.12.05 |
Refactoring - 첫 번째 예시(1) (0) | 2021.12.04 |