리팩터링

컴퓨터 프로그래밍 및 소프트웨어 설계에서 **코드 리팩터링**(code refactoring)은 외부 동작을 변경하지 않고 기존 소스 코드의 구조를 재조정(계수화)하는 과정이다. 리팩터링은 소프트웨어의 기능성을 보존하면서 디자인, 구조 및 구현(비기능적 속성)을 개선하는 것을 목적으로 한다. 리팩터링의 잠재적인 장점으로는 코드 가독성 향상 및 복잡성 감소가 있으며, 이는 소스 코드의 유지 보수성을 높이고, 확장 가능성을 개선하기 위해 더 단순하고 깨끗하며 표현력이 풍부한 내부 소프트웨어 아키텍처 또는 객체 모델을 만들 수 있다. 리팩터링의 또 다른 잠재적 목표는 성능 향상으로, 소프트웨어 엔지니어는 더 빠르게 실행되거나 메모리를 적게 사용하는 프로그램을 작성해야 하는 지속적인 과제에 직면해 있다.

일반적으로 리팩터링은 일련의 표준화된 기본 마이크로 리팩터링을 적용하며, 각각은 (보통) 소프트웨어의 동작을 보존하거나 적어도 기능 요구사항에 대한 적합성을 수정하지 않는 컴퓨터 프로그램 소스 코드의 아주 작은 변화이다. 많은 개발 환경은 이러한 기본 리팩터링의 기계적인 측면을 수행하기 위한 자동화된 지원을 제공한다. 코드 리팩터링을 잘 수행하면 기본 로직을 단순화하고 불필요한 수준의 복잡성을 제거함으로써 시스템에 숨겨져 있거나 잠복해 있는 버그 또는 취약점을 발견하고 수정하는 데 도움이 될 수 있다. 제대로 수행되지 않으면 외부 기능이 변경되지 않아야 한다는 요구사항을 충족하지 못해 새로운 버그가 발생할 수 있다.

## 동기
리팩터링은 보통 코드 스멜을 감지함으로써 동기가 부여된다. 예를 들어, 해당 메서드가 매우 길거나 근처에 있는 다른 메서드와 거의 중복될 수 있다. 이러한 문제가 인식되면 소스 코드를 리팩터링하거나, 이전과 동일하게 동작하지만 더 이상 "냄새"가 나지 않는 새로운 형태로 변환하여 문제를 해결할 수 있다.

긴 루틴의 경우 하나 이상의 작은 서브루틴을 추출할 수 있다. 중복된 루틴의 경우 중복을 제거하고 하나의 공유 함수로 교체할 수 있다. 리팩터링을 수행하지 않으면 기술 부채가 축적될 수 있으며, 반면에 리팩터링은 기술 부채를 상환하는 주요 수단 중 하나이다.

## 이점
리팩터링 활동에는 두 가지 일반적인 범주의 이점이 있다.
# 유지 보수성. 소스 코드를 읽기 쉽고 작성자의 의도를 파악하기 쉽기 때문에 버그를 수정하기가 더 쉽다. 이는 거대한 단일 루틴을 간결하고 이름이 잘 명명된 단일 목적의 메서드 집합으로 줄임으로써 달성할 수 있다. 또한 메서드를 더 적절한 클래스로 이동하거나 오해의 소지가 있는 주석을 제거함으로써 달성할 수도 있다.
# 확장 가능성. 인식 가능한 디자인 패턴을 사용하고 이전에는 없었던 유연성을 제공한다면 애플리케이션의 기능을 확장하기가 더 쉽다.
성능 엔지니어링은 실행 시간보다 애플리케이션 개발 시간을 최소화하려는 전통적인 소프트웨어 개발 전략에서 발생하는 소프트웨어 비대화라고 알려진 프로그램의 비효율성을 제거할 수 있다. 성능 엔지니어링은 또한 병렬 프로세서와 벡터 유닛의 이점을 활용하는 등 소프트웨어가 실행되는 하드웨어에 맞게 소프트웨어를 조정할 수 있다.

## 시기와 책임
리팩터링에는 두 가지 가능한 시기가 있다.
# 예방적 리팩터링 – 코드의 원래 개발자가 미래에 냄새가 형성되는 것을 방지하기 위해 코드가 아직 냄새가 없을 때 코드를 더 견고하게 만든다.
# 교정적 리팩터링 – 후속 개발자가 코드 스멜이 발생할 때 이를 수정하기 위해 리팩터링을 수행한다.

예방적 리팩터링과 교정적 리팩터링의 균형을 맞추는 방법은 "리팩터링에 대한 공동 책임"이다.
이 접근 방식은 리팩터링 작업을 두 단계와 두 가지 역할로 나눈다. 코드의 원래 개발자는 리팩터링을 위한 코드 준비만 하고, 코드 스멜이 형성되면 후속 개발자가 실제 리팩터링 작업을 수행한다.

## 과제
리팩터링을 위해서는 기존 소프트웨어 시스템에 대한 지식을 되찾기 위해 소프트웨어 시스템 구조, 데이터 모델 및 애플리케이션 내부 종속성을 추출해야 한다.
팀의 이직은 시스템의 현재 상태와 퇴사한 개발자가 내린 설계 결정에 대한 지식이 누락되거나 부정확함을 의미한다. 추가적인 코드 리팩터링 활동에는 이러한 지식을 다시 얻기 위한 추가 노력이 필요할 수 있다.
리팩터링 활동은 소프트웨어 시스템의 구조적 아키텍처를 저하시키는 아키텍처 수정을 발생시킨다. 이러한 저하는 유지 보수성 및 이해도와 같은 아키텍처 속성에 영향을 미치며, 이는 소프트웨어 시스템의 완전한 재개발로 이어질 수 있다.

코드 리팩터링 활동은 알고리즘 및 코드 실행 시퀀스에 대한 데이터를 제공하는 도구와 기술을 사용할 때 소프트웨어 인텔리전스로 보호된다. 소프트웨어 시스템 구조, 데이터 모델 및 구성 요소 간 종속성의 내부 상태에 대해 이해하기 쉬운 형식을 제공하는 것은 높은 수준의 이해를 형성한 다음 수정해야 할 사항과 방법에 대한 세련된 관점을 형성하는 데 중요한 요소이다.

## 테스트
루틴이 여전히 예상대로 동작하는지 확인하기 위해 리팩터링 전에 자동화된 단위 테스트를 설정해야 한다. 단위 테스트는 단일 원자적 커밋으로 수행될 때 대규모 리팩터링에도 안정성을 가져다줄 수 있다. 여러 프로젝트에 걸친 안전하고 원자적인 리팩터링을 허용하는 일반적인 전략은 모노레포라고 알려진 단일 저장소에 모든 프로젝트를 저장하는 것이다.

단위 테스트가 마련되면 리팩터링은 작은 프로그램 변환을 수행하고, 정확성을 보장하기 위해 테스트한 다음, 또 다른 작은 변환을 수행하는 반복적인 주기가 된다. 어느 시점에서든 테스트가 실패하면 마지막 작은 변경 사항을 취소하고 다른 방식으로 반복한다. 많은 작은 단계를 통해 프로그램은 원래 있던 곳에서 원하는 곳으로 이동한다. 이러한 매우 반복적인 프로세스가 실용적이려면 테스트가 매우 빠르게 실행되어야 하며, 그렇지 않으면 프로그래머는 테스트가 끝나기를 기다리는 데 많은 시간을 소비해야 할 것이다. 익스트림 프로그래밍 및 기타 애자일 소프트웨어 개발의 지지자들은 이 활동을 소프트웨어 개발 주기의 필수적인 부분으로 설명한다.

## 기법
다음은 마이크로 리팩터링의 몇 가지 예이다. 이들 중 일부는 특정 언어 또는 언어 유형에만 적용될 수 있다. 더 긴 목록은 마틴 파울러의 리팩터링 책과 웹사이트에서 찾을 수 있다. 많은 개발 환경은 이러한 마이크로 리팩터링에 대한 자동화된 지원을 제공한다. 예를 들어, 프로그래머는 변수 이름을 클릭한 다음 콘텍스트 메뉴에서 "필드 캡슐화" 리팩터링을 선택할 수 있다. 그러면 IDE는 일반적으로 적절한 기본값과 코드 변경 미리보기와 함께 추가 세부 정보를 요청한다. 프로그래머가 확인하면 코드 전체에 걸쳐 필요한 변경을 수행한다.
### 정적 분석
정적 프로그램 분석(덜 엄격한 인터프리터 언어에서 수행될 때는 "린팅"이라고 함)은 유효하지만 수준 이하인 프로그램의 문제를 감지한다.

* 프로그램 의존성 그래프 - 데이터 및 제어 종속성의 명시적 표현
* 시스템 의존성 그래프 - PDG 간의 프로시저 호출 표현
* 순환 복잡도 분석.
* 소프트웨어 인텔리전스 - 기존 애플리케이션 내부 종속성을 이해하기 위해 초기 상태를 역공학함

### 변환
변환은 프로그램의 구문 표현을 수정한다. 일부 수정은 프로그램의 유연성이나 견고성을 향상시키는 방식으로 프로그램의 의미나 구조를 변경한다. 이러한 수정에는 문제 도메인 및 의도된 로직에 대한 지식이 필요하므로 자동화가 불가능하다. 프로그램을 더 읽기 쉽고 수정하기 쉽게 만들지만 프로그램의 기본 로직을 변경하지 않는 수정 사항이 존재하며, 이러한 변환은 자동화될 수 있다.

* 더 많은 추상화를 허용하는 기법
** 필드 캡슐화 – 코드가 게터 및 세터 메서드를 통해서만 필드에 접근하도록 강제함
** 유형 일반화 – 더 많은 코드 공유를 허용하기 위해 더 일반적인 유형을 생성함
** 타입 체크 코드를 상태/전략(state/strategy)으로 교체
** 조건문을 다형성으로 교체
* 코드를 더 논리적인 조각으로 나누는 기법
** 컴포넌트화는 코드를 명확하고 잘 정의되었으며 사용하기 쉬운 인터페이스를 제공하는 재사용 가능한 의미 단위로 분해함.
** 클래스 추출(Extract class)은 기존 클래스의 코드 일부를 새로운 클래스로 이동함.
** 메서드 추출(Extract method)은 큰 메서드의 일부를 새로운 메서드로 전환함. 코드를 더 작은 조각으로 나눔으로써 더 쉽게 이해할 수 있다. 이는 함수에도 적용 가능하다.
* 코드의 이름과 위치를 개선하는 기법
** 메서드 이동 또는 필드 이동 – 더 적절한 클래스 또는 소스 파일로 이동함
** 메서드 이름 변경 또는 필드 이름 변경 – 그 목적을 더 잘 드러내는 새로운 이름으로 변경함
** 풀 업(Pull up) – 객체 지향 프로그래밍(OOP)에서 상위 클래스로 이동함
** 푸시 다운(Push down) – OOP에서 하위 클래스로 이동함
* 자동 복제 탐지

## 하드웨어 리팩터링
리팩터링이라는 용어는 원래 소프트웨어 코드의 리팩터링만을 의미했지만, 최근 몇 년 동안 하드웨어 기술 언어로 작성된 코드도 리팩터링되고 있다. 하드웨어 리팩터링이라는 용어는 하드웨어 기술 언어의 코드 리팩터링을 위한 약칭으로 사용된다. 하드웨어 기술 언어는 대부분의 하드웨어 엔지니어에 의해 프로그래밍 언어로 간주되지 않으므로, 하드웨어 리팩터링은 전통적인 코드 리팩터링과는 별개의 분야로 간주되어야 한다.

아날로그 하드웨어 기술(VHDL-AMS)의 자동 리팩터링은 Zeng과 Huss에 의해 제안되었다. 그들의 접근 방식에서 리팩터링은 하드웨어 설계의 시뮬레이션된 동작을 보존한다. 개선되는 비기능적 측정 요소는 리팩터링된 코드는 표준 합성 도구로 처리할 수 있는 반면, 원래 코드는 처리할 수 없다는 점이다. 디지털 하드웨어 기술 언어의 리팩터링은 비록 수동 리팩터링이기는 하지만 시놉시스 석학회원인 마이크 키팅(Mike Keating)에 의해 조사되기도 했다. 그의 목표는 복잡한 시스템을 이해하기 쉽게 만들어 설계자의 생산성을 높이는 것이다.

## 역사
출판된 문헌에서 "리팩터링"이라는 용어가 처음 사용된 것은 1990년 9월 윌리엄 옵다이크(William Opdyke)와 랄프 존슨의 논문에서였다.
코드 리팩터링은 수십 년 동안 비공식적으로 수행되어 왔지만, 윌리엄 그리스월드의 1991년 박사 학위 논문은 함수형 및 절차형 프로그램의 리팩터링에 관한 최초의 주요 학술 연구 중 하나이며, 그 뒤를 이어 객체 지향 프로그램의 리팩터링에 관한 윌리엄 옵다이크의 1992년 논문이 뒤를 이었다. 모든 이론과 기제는 오랫동안 프로그램 변환 시스템으로 사용 가능했다. 이러한 모든 리소스는 리팩터링을 위한 일반적인 방법의 카탈로그를 제공한다. 리팩터링 방법에는 해당 방법을 적용하는 방법과 방법을 적용해야 하는(또는 적용하지 말아야 하는) 시기에 대한 지표가 설명되어 있다.

마틴 파울러의 저서 《리팩토링: 기존 코드의 설계를 개선하는 방법》은 정석적인 참고서이다.

"팩터링" 및 "팩터링 아웃"이라는 용어는 적어도 1980년대 초반부터 포스 커뮤니티에서 이러한 방식으로 사용되어 왔다. 레오 브로디(Leo Brodie)의 저서 《Thinking Forth》(1984) 제6장은 이 주제에 할애되어 있다.

익스트림 프로그래밍에서 메서드 추출 리팩터링 기법은 기본적으로 포스에서의 팩터링과 동일한 의미를 갖는다. 즉, "단어"(또는 함수)를 더 작고 유지 관리가 쉬운 함수로 나누는 것이다.

리팩터링은 깃과 같은 소프트웨어 저장소에 기록된 복잡한 소프트웨어 변경 사항에 대한 간결한 설명을 생성하기 위해 사후에 재구성될 수도 있다.

## 도구
많은 소프트웨어 개발 도구에는 리팩터링 기능이 있다. 예시는 다음과 같다.
; 안드로이드 스튜디오: 자바 및 C++ 리팩터링을 지원한다.
; AppCode: 오브젝티브-C, C 및 C++ 리팩터링을 지원한다.
; 델파이: 오브젝트 파스칼 리팩터링을 지원한다.
; DMS Software Reengineering Toolkit: C, C++, C#, 코볼, 자바, PHP 및 기타 언어에 대한 대규모 리팩터링을 지원한다.
; Eclipse: 플러그인을 통해 자바 및 어느 정도의 C++, PHP, 루비, 자바스크립트 리팩터링을 지원한다.
; IntelliJ IDEA: 자바 리팩터링을 지원한다.
; JDeveloper: 자바 리팩터링을 지원한다.
; 넷빈즈: 자바 리팩터링을 지원한다.
; PhpStorm: PHP 리팩터링을 지원한다.
; PyCharm: 파이썬 리팩터링을 지원한다.
; PyDev: 파이썬 리팩터링을 지원한다.
; 스몰토크: 대부분의 방언에 강력한 리팩터링 도구가 포함되어 있다. 많은 도구가 90년대 초반 랄프 존슨이 만든 원본 리팩터링 브라우저를 사용한다.
; Visual Assist: C# 및 C++ 리팩터링을 지원한다.
; 비주얼 스튜디오: 닷넷 및 C++ 리팩터링을 지원한다.
; 비주얼 스튜디오 코드: 플러그인을 통해 많은 언어의 리팩터링을 지원한다.
; WebStorm: 자바스크립트 리팩터링을 지원한다.
; Wing IDE: 파이썬 리팩터링을 지원한다.
; 엑스코드: C, 오브젝티브-C 및 스위프트 리팩터링을 지원한다.
; Qt 크리에이터: C++, 오브젝티브-C 및 QML 리팩터링을 지원한다.

## 같이 보기
* 코드 검토
* 소프트웨어 디자인 패턴
* 난독화
* 테스트 주도 개발
* 모듈성 (프로그래밍)

## 각주

분류:익스트림 프로그래밍