기초단계

대규모 시스템에서 리팩토링은 매우 중요하다.

프로그램은 주어진 상황과 정보를 코드를 통해서 자동화한다.

코드가 지저분 하든 그렇지 않든 컴파일러는 개이치 않지만 사람은 코드의 미적 상태에 민감하다.

설계가 나쁜 시스템은 수정하기 어렵다.

무엇을 수정할지 찾기 어렵다면 실수를 저지르기 쉽다.

리팩토링 기초 단계

복잡하게 얽힌 덩어리를 잘게 쪼개는 작업이다. 이 작업은 이름을 얼마나 잘 짓는 지가 관건이다.

수백줄 짜리 코드를 리팩토링하는 과정

먼저 프로그램의 작동 방식을 더 쉽게 파악 할 수 있도록 코드를 여러 함수와 프로그램 요소(변수, 함수, 클래스)로 재구성한다.

기능을 추가하기 어려운 프로그램을 리팩토링하는 과정

먼저 기능을 추가하기 쉬운 형태로 리팩토링하고 나서 원하는 기능을 추가한다.

리팩토링의 냄새가 나는 곳

  • 자주 수정하게 되는 코드
  • 수정한 부분이 다른 코드에 영향을 많이 끼치는 코드
  • 자주 반복이 일어나는 코드
  • 새로운 요구사항을 받아들이기 어려운 코드

변경에서 자유로운 설계를 갖추기 위해 우리는 리팩토링하게 될 것이다.

 

잘 작동하고 변경 할 일이 절대 없다면 현재 상태로 놔두어도 문제 없다. 누군가 읽을 일이 없다면 말이다. 이때는 대책이 필요하다.

리팩토링의 첫 단계

리팩토링 전에 제대로 된 테스트 부터 마련한다. 테스트는 반드시 자가진단하도록 만든다.

리팩토링 기법은 버그를 최소화하도록 구성됐지만 사람이 수행하는 만큼 언제든 실수가 발생할 수 있다.

리팩토링 시에 테스트에 의지한다. 테스트는 내 실수를 검출하는 역할을 한다.

긴 함수를 리팩토링

전체 동작을 각각의 부분으로 나눌 수 있는 지점을 찾는다.

작은 리팩토링 부분은 분석이 끝나는 데로 재빨리 코드에 반영한다.

분석한 부분을 별도의 함수로 추출하고 이 코드가 하는 일을 이름으로 지어준다. - "함수 추출하기" 라고 부른다.

함수 추출하기

추출 될 함수의 유효범위를 벗어나는 변수가 있는 지 확인한다.

값이 변경되지 않는 변수는 매개변수로 사용하는 게 좋다.

코드 수정하고 곧바로 테스트 한다.

곧 바로 테스트해야 문제를 찾고 해결하기 쉽다.

리팩토링 진행

리팩토링은 프로그램 수정을 작은 단계로 나눠 진행한다. 그래서 중간에 실수하더라도 버그를 쉽게 찾을 수 있다. 그러므로 리팩토링에 대한 심적인 부담을 줄이자. 결국 우리가 할 일은 작은 부분을 고치는 것의 연속이다.

중첩 함수

JS에는 중첩함수가 많다. 리팩토링 관점에서 보면 변수 스코프를 변경하는 일을 줄이는 장점이 있다.

작은 리팩토링이 끝나면

변경 및 테스트 후 로컬 버전 관리 시스템에 커밋한다. 이러한 커밋이 모여 의미 있는 단위로 뭉쳐지면 공유 저장소에 푸시한다.

IDE의 리팩토링 기능

현대적인 IDE는 리팩토링 기능을 제공한다. 적극 활용하자.

추출한 함수의 네이밍

변수, 함수 이름을 더욱 명확하게 한다.

단축 이름 보다는 정확한 이름을 사용한다.

 

컴퓨터가 이해하는 코드는 바보도 작성할 수 있다. 사람이 이해하도록 작성하는 프로그래머가 진정한 실력자다.

변수 이름을 명확하게 바꾸는 일을 정말 가치 있는 일이다.

임시 변수 제거

매개변수의 값에 따라서 실행되는 로직이 다르다면, 이 매개변수는 임시 변수라고 한다.

임시 변수는 나중에 문제를 일으킬 수 있다.

자신이 속한 루틴에서만 의미가 있어서 루틴이 길고 복잡해지기 쉬다.

이러한 변수는 추출하여 질의 함수로 바꾸거나 하여 제거한다.

 

더보기

"임시"라는 단어의 뜻을 짚고 넘어갑니다.

미리 정하지 아니하고 그때그때 필요에 따라 정한 것 - 네이버 사전

 

임시 변수는 추출 작업을 복잡하게 만드므로 바로바로 함수로 바꿉니다. 이를 "임의 변수를 질의 함수로 바꾸기"라고 합니다.

더보기

"질의"라는 단어의 뜻을 짚고 넘어갑니다.

모르는 것을 물어보는 것 - 네이버 사전

변수 인라인하기

임시 변수는 인라인으로 대체한다.

 

리팩터링한 코드가 기존 코드 보다 미묘한 차이로 성능에 영향을 주는 경우라도 리팩토링 된 코드가 성능을 개선하기에 훨씬 유리한 품질을 가졌다는 것은 사실이다.

 

함수 추출 작업 전에 지역 변수 제거

지역 변수를 제거해서 얻는 가장 큰 장점은 추출 작업이 훨씬 쉬워진다는 것이다. 유효범위를 신경 써야 할 대상이 줄어들기 때문이다. 변수를 인라인으로 변경하여 제거한다.

 

더보기

리팩토링에는 순서가 있다. 어떤 순서로 코드를 리팩토링하냐에 따라 쉽고 어려움이 달라진다.

함수를 사용하는 함수

유틸리티 객체의 메소드를 사용하는 경우, 함수를 직접 선언해 사용한다.

함수 선언 바꾸기

함수 이름이 충분히 설명되지 않거나 장황한 경우, 적절한 이름으로 바꾸자. 이러한 경우, 함수의 핵심을 나타내는 단어를 사용하는 것이 좋다.

이름짓기의 중요성

긴 함수를 작게 쪼개는 리팩터링은 이름을 잘 지어야만 효과가 있다. 그 만큼 이름 짓기는 중요하다.

 

잘 지은 이름 하나는 함수의 본문을 읽지 않고도 무슨 일을 하는 지 알 수 있다.

 

물론 좋은 이름 짓기는 쉽지 않다. 따라서 처음에는 당장 떠오르는 최선의 이름을 사용하다가, 나중에 더 좋은 이름이 떠오를 때 바꾸는 식이 좋다.

반복문 쪼개기

반복문 하나를 하나의 함수로 보자. 이 반복문이 돌 때 마다 여러 값이 변화 된다면, 각각의 값을 변화시키는 반복문으로 쪼갠다. 그리고 이 반복문을 각각의 함수로 바꾸면, 반복문에서 사용했던 임시 변수를 질의 함수로 바꾸기가 수월해진다.

 

더보기

리팩토링 흐름이 조금씩 보이는 가?

리팩토링과 성능

리팩토링이 성능에 영향을 준 경우라도 크게 개의치 않고 리팩토링 한다. 잘 다듬어진 코드가 성능을 더 개선 할 수 있다.

변수 이름과 추출 함수의 중복

이러한 경우 추출 함수를 임의로 변경하여 함수를 만들고 테스트 한 다음, 추출 함수를 변수이름으로 변경 후 인라인으로 처리한다.

 

단계와 분류

잘 리팩토링 된 코드는 여러 버전으로 나누기가 쉽다. 각 단계를 쪼개기가 쉽다는 것이다.

 

긴 함수를 리팩토링하면 여러 함수로 나뉜다. 이 나뉜 함수를 의미 단위로 묶어 놓으면 클래스 처럼 보인다. 이를 파일로 나누면 더 명확해진다.

 

리팩토링의 결과로 코드량은 늘어 날 수 있다. 그렇지만 중복이 없고 각 요소가 더뚜렷해지며, 계산과 출력 부분이 분리됨으로써 코드는 간결해진다.

 

캠핑자들에게는 "도착했을 때보다 깔끔하게 정돈하고 떠난다"는 규칙이 있다. 프로그래밍도 마찬가지다. 항시 코드베이스를 작업 시간 전 보다 건강하게 만들어놓고 떠나야 한다.

 

항상 리팩토링과 기능 추가 사이의 균형을 맞추려고 노력한다고 한다. 더 이상 리팩토링이 필요 없는 코드를 지향하는 것도 나쁘지 않지만 어느 정도 균형점을 잡는 게 좋다.

 

밥 아저씨의 마인드 : 항시 코드베이스를 작업하기 전보다 더 건강하게 고친다. 완벽하지 않더라도, 분명 더 나아지게 한다.

 

다형성

조건부 로직은 코드 수정 횟수가 늘어날수록 골치거리로 전락한다. 이를 방지하려면 프로그래밍 언어가 제공하는 구조적인 요소로 적절히 보완해야 한다. 다양한 보완법이 있지만 여기서는 객체지향의 핵심 특성인 다향성을 활용한다.

 

이 작업의 목표는 상속 계층 구조를 구성하여 서브클래스에서 각자의 구체적인 계산 로직을 정의하는 것이다. 호출 쪽에서는 함수를 호출하기만 하면 된다. 어떤 계산 로직을 연결할 지는 언어 차원에서 처리해준다. - 조건부 로직을 다형성으로 바꾸기

 

이 리팩토링은 조건부 코드 한 덩어리를 다형성을 활용하는 방법으로 바꾼다. 이 리팩토링을 적용하려면 상속 계층부터 정의해야 한다.

 

자바스크립트에서는 생성자가 서브 클래스의 인스턴스를 반환할 수 없기 때문에 생성자를 팩터리 함수로 바꾸어 다형성을 구현한다.

 

다형성을 활용해 계산 코드 재구성하기

...

다형성을 활용하여 데이터 생성하기

...


리팩토링이 무엇인지 감을 잡자.

코드를 보았을 때 어떻게 리팩토링 할 수 있는 지 아는 것은 중요하다.

리팩토링 기법

  • 함수 추출하기
  • 변수 인라인하기
  • 함수 옮기기
  • 조건부 로직을 다형성으로 바꾸기
  • etc

리팩토링 과정

  1. 코드가 하는 일 파악
  2. 개선점 찾기
  3. 리랙토링 작업 수행
  4. 테스트
  5. 커밋

리랙토링 결과

  • 명확해지고 이해하기 더 쉬워진다.
  • 다른 개선점을 더 쉽게 개선 할 수 있다.

 

좋은 코드를 가늠하는 확실한 방법은 '얼마나 수정하기 쉬운가' 다.

 

코드는 명확하게 한다.

코드를 수정해야 할 상황이 되면 고쳐야 할 곳을 쉽게 찾을 수 있고 오류 없이 빠르게 수정할 수 있어야 한다.

건강한 코드베이스는 생산성을 극대화하고, 고객에게 필요한 기능을 더 빠르고 저렴한 비용으로 제공하도록 해준다.

 

코드를 건강하게 관리하려면 프로그래밍 팀의 현재와 이상의 차이에 항상 신경 쓰면서, 이상에 가까워지도록 리팩터링해야 한다.

 


더보기

코드의 흐름이 표면적으로 보이지 않고 계층적으로 잘 나뉘어진 코드는 코드의 흐름을 파악하기 어려운 대신 계층 구조를 이해한 후 부터는 유지보수가 쉬워진다. 그러므로 계층 구조에서 코드의 흐름을 쉽게 파악 할 수 있게 만들 수 있다면 두 마리의 토끼를 둘 다 잡을 수 있을 거라 생각한다. ( 다만, 방법을 모를 뿐... )

 

한 줄, 한 줄 정리하다보니 정말 이래서 밥 아저씨라고 불리는 건가 싶다.

 

리팩토링 2판 - 마틴 파울러

 

밥 아저씨의 조언

  • 리팩터링하는 리듬을 익혀라.
  • 각 단계를 광장히 잘제 나누고
  • 매번 컴파일하고
  • 테스트하여 작동하는 상태로 유지하라
  • 이것이 리팩토링을 효율적으로 하는 핵심이다.
  • 코드는 절대 깨지지 않으며, 이러한 작은 단계들이 모여서 상당히 큰 변화를 이룰 수 있다
블로그 이미지

_김은찬

두번 다시는 꺾이지 않으리

,