리팩토링 제2장 리팩토링 개론
이 장에서는 이론적인 설명으로 돌아가서 리팩토링의 주요 원리와 리팩토링할 때 고려해야 할 사안에 대해 설명하겠다.
리팩토링은 무엇인가
리팩토링이란
겉으로 드러나는 기능은 그대로 둔 채, 알아보기 쉽고 수정하기 간편하게 소프트웨어 내부를 수정하는 작업
또는
리팩토링 기법을 연달아 적용해서 겉으로 드러나는 기능은 그대로 둔 채 소프트웨어 구조를 변경하는 작업
리팩토링은 단순한 코드 정리가 아니다. 리팩토링 과정을 통해 코드 효울성도 높일 수 있고 코드 구조도 체계화할 수 있다. 상황에 따라 어느 리팩토링 기법을 적용하는 것이 적절한지 파악할 줄 알아야 한다. 또한 리팩토링으로 인한 버그를 최소화하는 방식을 따르는 것이 중요하다.
리팩토링의 정의로부터 강조할 사항은 다음 두가지다.
- 리팩토링의 목적은 소프트웨어를 더 이해하기 쉽고 수정하기 쉽게 만드는 것이다.
- 리팩토링은 소프트웨어 기능에 영향을 주지 않는다.
모자 두 개
소프트웨어 개발에 리팩토링을 적용할 때 기능 추가와 리팩토링이라는 별개의 두 작업에 시간을 분배해야 한다. 마치 기능 추가 모자와 리팩토링 모자를 바꿔 쓰는 것과 같다. 코드 구조를 바꾸면 작업이 훨씬 쉬워질 때와 기능이 이해하기 이려운 구조로 작성되었을 때 리팩토링 모자로 바꿔 쓴다. 기능을 추가할 땐 코드를 수정하지 말고 기능만 추가해야 한다. 진행상태를 파악하려면 테스트를 추가하고 그 테스트들이 제대로 되는지 알아내면 된다. 리팩토링할 때는 코드를 추가하지 말고 코드 구조 개선만 해야 한다. 각 작업이 완료될 때까지는 반드시 본인이 현재하고 있는 작업의 일관성을 유지해야 버그와 실수를 최소화할 수 있다.
리팩토링을 왜 해야 하나
소프트웨어 설계가 개선되니까
리팩토링을 실시하지 않으면 프로그램 설계는 점점 노후된다. 단기적인 목적 때문에 코드를 수정하거나 코드의 설계를 완벽히 이해하지 않고 코드를 수정하면, 코드 구조가 뒤죽박죽되어 그 코드를 보고 설계를 파악하기 어려워진다. 리팩토링은 그렇게 구조가 산만한 코드를 정리하는 작업이다. 즉 부적절한 위치에 있는 코드를 제거하는 것이다. 코드의 설계를 파악하기 힘들어질수록 설계를 보수하기도 힘들어지니 결국 설계가 더 엉망이 되는 악순환이 되버린다. 그러므로 코드의 처음 설계 구조를 유지하려면 정기적으로 리팩토링을 실시해야 한다.
설계를 개선하는 주요 비법 중 하나는 중복 코드를 없애는 것이다. 중복 코드를 제거하면 나중에 코드를 수정할 때 중복하여 수정할 필요가 없어진다. 또한 코드가 길수록 이해할 분량이 많으니 정확한 수정이 어렵다. 중복 코드 제거는 깔끔한 설계의 필수 요건이다.
소프트웨어를 이해하기가 더 쉬워지니까
프로그래밍에서 개발자가 원하는 바를 정확히 컴퓨터에게 명령하는 것이 중요하다. 하지만 공동 프로젝트라면 다른 팀원과 같이 협력해야 하고 개발자는 다른 사람이 코드를 수정할 경우까지 고려하지 못하는 실수를 하기 쉽다. 그러므로 코드를 이해할 대상을 컴퓨터가 아니라 동료 개발자, 더 나아가 디자이너까지 두루 고려하는 일이 중요하다.
개발자가 프로그램을 제대로 실행되게 만드는 일에만 집중한 나머지, 코드를 나중에 수정하게 될 다른 개발자에 대해 고려하지 않는 점이 문제의 원인이다. 리팩토링을 실시하면 코드는 더 파악하기 쉬워진다. 리팩토링은 제대로 실행되지만 구조가 완전하지 못한 코드에 대해 실시하는 것이다. 리팩토링에 약간만 시간을 투자하면 코드가 본연의 목적에 더 충실히 실행된다. 그런 점에서 볼 때 프로그래밍에서 가장 중요한 것은 의도한 바를 정확히 전달하는 것이다.
기억하지 않아도 나중에 문제없도록 코드를 작성하자.
리팩토링의 또 다른 매력은 낯선 코드를 쉽게 이해할 수 있도록 해준다. 코드를 수정해서 내가 이해한 내용을 더 꼼꼼히 반영한 후, 다시 실행해서 코드가 여전히 제대로 실행되는지 확인하면서 처음에 파악했던 기능을 점검하다보면 코드를 이해하게 된다.
버그를 찾기가 쉬워지니까
코드를 파악하기 쉬우면 버그 발견도 쉬워진다. 코드 리팩토링을 실시하면 코드 기능을 근본적으로 이해할 수 있으며 그 새로운 깨달음을 즉시 코드에 반영한다. 프로그램 구조를 명료하게 만들어두면 버그를 놓치기 어렵다.
프로그래밍 속도가 빨라지니까
리팩토링은 코드를 신속하게 개발할 수 있게 만들어 준다. 깔끔한 설계야말로 소프트웨어 개발 속도를 높이기 위한 핵심이다. 새 기능을 추가하는 시간과 버그를 찾는 시간을 줄일 수 있다. 그러므로 깔끔한 설계는 소프트웨어 개발 속도를 적절히 유지하는데 꼭 필요하다.
리팩토링은 어떨 때 필요한가
리팩토링을 일부러 시간 내서 할 필요는 없다. 리팩토링은 따로 시간을 정해서 하면 안 되고 일상적으로 틈틈히 해야 한다. 리팩토링은 특별한 작업이 있어서 하는게 아니라 리팩토링을 하면 작업이 쉬워지기 때문에 하는 것이다.
TIP 같은 작업을 3번째 반복하게 됐을 때 리팩토링을 실시하자.
기능을 추가할 때
리팩토링이 절실히 필요한 첫번째 상황은 소프트웨어에 새 기능을 추가해야 할 때다. 먼저 코드를 이해하기 쉽도록 만든다. 설계가 지저분해서 기능을 추가하기 힘들 때 리팩토링을 하면 코드를 이해하기 쉽고 깔끔하게 만들 수 있고 코드를 더 깊이 이해할 있게 된다. 그래야 기존 코드에 새 기능을 추가하기 편리해진다.
버그를 수정할 때
보그를 수정할 땐 주로 코드를 이해하기 쉽게 만들려고 리팩토링을 한다. 코드의 기능을 파악하려다 이해하기 힘들면 이해하기 쉽게 만들려고 리팩토링을 실시한다. 이렇게 적극적으로 리팩토링하고 나면 버그를 찾아서 수정할 만큼 코드를 이해할 수 있다.
코드를 검수할 때
코드 검수를 통해 개발 팀원 모두가 코드를 파악하게 되며, 코드 작성에 관한 경험이 전수되는 효과도 나타난다. 그리고 시스템의 더 많은 부분을 더 많은 팀원이 이해할 수 있다. 코드 검수는 명료한 코드를 작성하기 위해서도 꼭 필요하다. 또 코드를 검수하는 동안 기발한 아이디어를 제안받을 기회도 생긴다.
아이디어 검토할 때
아이디어가 떠오르면 리팩토링을 통해, 그 아이디어를 어디에 어떻게 구현할지에 대해 구체적으로 검토할 수 있게 된다. 리팩토링을 몇 차례 실시하면 아이디어를 구현했을 때 코드가 어떤 구조로 변할지 상상할 수 있다. 따라서 리팩토링은 새로운 아이디어를 적극적으로 반영하는데 도움이 된다.
리팩토링의 효용성
프로그램이 지닌 가치는 두 종류다. 하나는 현재의 기능이라는 가치이고, 또 하나는 미래의 기능이라는 가치다. 프로그램의 현재 기능은 그저 일부에 불과하다는 사실을 깨우치지 않으면 개발자로서 오래가지 못한다. 과거의 판단이 현재를 기준으로 불합리하다는 사실을 발견했다면 그 판단을 수정해야 한다. 그래야 현재의 작업을 할 수 있다.
프로그램은 다음 4가지 상황일 때 수정하기 힘들어진다.
- 코드를 알아보기 힘들 때
- 중복된 로직이 들어 있을 때
- 추가 기능을 넣어야 해서 실행 중인 코드를 변경해야 할 때
- 조건문 구조가 복잡할 때
프로그램은 코드를 알아보기 쉽고, 모든 로직이 한 곳에 있으며, 기존 기능을 건드릴 필요 없이 조건문 구조가 최대한 간결하게끔 작성해야 한다. 리팩토링은 신속한 개발 공정을 가능하게 하는 성질을 가중하면서 프로그램의 가치를 높이는 작업이다.
리팩토링 관련 문제들
데이터베이스
비지니스 애플리케이션은 바탕이 되는 데이터베이스 스키마와 강력히 결합되어 있다. 결합 정도를 낮추기 위해 객체 모델과 데이터베이스 모델 사이에 별도의 소프트웨어 계층을 두는 방법도 있지만, 중개 계층을 만들어서 관리해야 하는 부담도 생긴다. 그러므로 별도의 계층을 처음부터 사용할 필요는 없다. 필요에 따라 적절히 적용해야 한다.
인터페이스 변경
리팩토링에서 불안한 점은 인터페이스를 수정할 때도 있다는 점이다. 어떤 리팩토링 기법이 이미 배포된 인터페이스를 건드릴 경우 개발자는 적어도 그 인터페이스를 사용하는 부분이 그 인터페이스 변경에 맞춰 수정되기 전까지는 기존 인터페이스와 새 인터페이스를 모두 그대로 유지시켜야 한다. 그리고 기존 인터페이스는 새 인터페이스를 호출하도록 변경해야 한다. 메서드의 내용 자체를 복사해서 사용하면, 중복 코드가 생겨서 오히려 문제를 만든 꼴이 된다. 마지막으로 인터페이스가 더 이상 유효하지 않다는 사실을 알려야 한다.
리팩토링하면 안되는 상황
코드가 기능하지 않는다면 그건 완전히 새로 작성하라는 신호다. 테스트만 하려다 코드가 버그가 너무 많아 안정화할 수 없음을 알게 될 경우가 바로 리팩토링이 아니라 새로 작성해야 하는 순간이다. 코드는 반드시 대부분 제대로 돌아가는 것이 우선이고, 리팩토링은 나중 일임을 명심하자.
프로젝트 납기가 임박했을 때도 리팩토링은 삼가야 한다. 납기가 임박한 경우 리팩토링을 해봤자 생산성 향상 효과를 보기 힘들다. 반면 납기가 임박한 경우가 아니면 시간이 없다는 핑계로 리팩토링을 미루면 안된다. 언제나 시간에 쫓긴다면 그건 리팩토링해야 한다.
리팩토링과 설계
리팩토링은 설계를 보완하는 특수한 역할을 한다. 설계만 하면 생각이 아주 빨라지지만 그 생각엔 구체성이 없어 빈틈이 많다. 일단 머릿속 아이디어를 코딩하고 잘 돌아가게 만든 후 그것을 리팩토링으로 세밀히 다듬어야 한다. 사전 설계 과정에서 완벽한 설계를 찾을 필요없이 적당한 솔루션을 구현하고 리팩토링을 통해 세밀히 다듬으면 된다. 시스템에 유연성이 필요한 곳은 일부이고, 그나마 그런 부분이 어딘지 예측하는 건 불가능하다. 따라서 유연성을 높이려면 실제 필요한 것보다 훨씬 많은 유연성을 넣게 된다. 하지만 리팩토링을 실시하면 유연성을 낮추지 않고도 더 간결한 설계가 가능해진다. 덤으로 설계 과정이 쉬워지고 스트레스도 줄어든다.
'Develop > 소프트웨어 설계' 카테고리의 다른 글
[SOLID] Single Responsibility 원칙 (0) | 2019.08.16 |
---|---|
[SOLID] SOLID 원칙이란 (2) | 2019.08.15 |
[리팩토링] 제6장 메서드 정리 (0) | 2018.02.19 |
[리팩토링] 제3장 코드의 구린내 (0) | 2018.02.18 |
[리팩토링] 제1장 맛보기 예제 (0) | 2018.01.05 |
꾸준히 노력하는 개발자 "김예건" 입니다.