본문 바로가기
Refactoring

리팩터링 방법

by gf0308 2022. 2. 23.

『자바 웹 프로그래밍 next step』(박재성 저) 을 공부하면서 알게 된 리팩터링에 대해 정리

리팩터링(Refactoring)

리팩터링이란 소스의 가독성을 높이고 유지보수를 편하게 하기 위해 소스의 구조를 변경하는 것

- 리팩터링을 하더라도 기능상의 결과가 변경되는 것은 아님

- 기능 자체는 리팩터링 이전과 똑같이 기능해야 함

리팩터링 할 때의 3가지 기본적인 원칙

1) 한 가지 메서드는 한 가지 일(책임)만

2) 코드 전체의 인덴트(indent: 깊이)는 1단계를 유지

: 인덴트의 깊이(depth)가 2단계 이상으로 가지 않도록 가급적 유지

3) else 문은 (가급적) 사용하지 않기

: else 문을 사용하면 인덴트가 깊어지기 쉽다. 어쩔수 없을 경우도 있기에 그럴 땐 사용할 수도 있지만 가급적이면 else문 없이 if문 까지로만 코드가 작성되는 것이 가독성 관점에선 더 좋다.

모든 단계의 끝은 리팩터링

소스코드의 복잡도가 쉽게 증가하는 이유는 하나의 요구사항을 구현한 후,

리팩터링을 하지 않은 채 다음 단계로 넘어가기 때문이다.

이게 반복되고 시간이 지날수록 소스코드의 복잡도는 기하급수적으로 증가한다.

깔끔하고 유지보수가 용이한 코드를 지향하는 관점에선,

각 단계에서 다음 단계로 넘어가기 위한 작업의 끝은 '리팩터링까지 완료했을 때' 이다.

(내가 기대하는 결과를 확인했을 때가 아닌, 즉 구현했으니 땡이 아닌)

"구현" => "테스트를 통한 결과 확인" => "리팩터링"

리팩터링을 하고 있을 때 유의점

1. 나중에 한꺼번에가 아닌 중간 중간마다 리팩터링 해주기

: 모든 요구사항의 구현을 다 끝낸 다음에 리팩토링을 수행하겠다 하는게 아니라, 중간 중간 마다 한 구현이 끝나면 다시 살펴보고서 리팩터링을 해주고, 깔끔하게 정리되면 다시 이어서 구현을 해주는 프로세스를 반복하는 방식이 더 좋은 방법이다.

2. 분해하고 나눠줄게 별로 많지 않아보이는 작은 코드더라도 최대한 리팩터링

: 아무리 작고 더 쪼개고 분리할 것이 없어보이는 코드더라도, 최대한 할 때 까지 해서 어떻게 보면 극단적으로까지 리팩토링을 해주는 것이 좋다(철저하게 리팩토링하는 것)

이렇게 극단적으로 리팩토링을 하다 보면, 실제 프로덕션 코드에서 개선해야 할 부분을 문득 발견하기도 하는 부수적효과도 얻을 수 있다.

3. 리팩터링을 하다가 어떤 API나 기능 등이 작동하는 방식에 대해 확신이 없을 때, 해당 메서드에 대한 '테스트 클래스'를 작성해서 확인해볼 수도 있음

: 어떤메서드가 정확히 어떻게 동작하는지 확신이 없을 때, 해당 메서드에 대한 '테스트클래스' 를 작성해볼수도 있다.

4. 테스트 메서드의 이름에 한글을 사용할 수도 있다

: 리팩터링과 뗄 수 없는 존재인 테스트를 수행해보면서 많은 테스트메서드를 작성하게 되는데,

테스트 메서드명은 일반적으로 영어로 작성하는 것이 보통이지만, 만약 의미전달이 영어로는 정 힘들다면 (테스트메서드가 어떤 테스트인지 명확하게 전달하는 것이 영어로는 힘들다면) 한글로 작성해서 사용하는 것도 실제로 사용가능한 한 가지 방법이다.

5. 분리할 수 있는 코드는 적극적으로 메서드로 분리

: 메서드를 잘 분리해놓으면 메인 소스 부분의 가독성도 개선되고, 새로운 요구사항이 발생할 때 해당 메서드를 찾아 해당 메서드만 수정사항을 반영하는 것이 가능하다. (메서드가 원자화 되어 있어 다른 코드들과 결합도가 낮기 때문)

6. 메서드명, 변수명 변경도 중요 리팩터링 소재

: 리팩터링 시 로직 수정만 중요한게 아니라, 메서드 이름, 변수 이름을 (필요하다면) 변경하는 것 또한 중요한 부분임

리팩터링을 한 후 주의깊게 봐야할 점

public으로 공개하고 있는 메서드가 얼마나 읽기 쉽고, 좋은가가 관건이고 핵심이다.

- 객체 내부에서만 쓰게 되기 마련인 세부구현을 담당하는 private 메서드는 포인트가 아님.

- 외부에 공개되는 공용 인터페이스 담당인 public 메서드 부분에서 '객체가 수행할 작업(책임)의 핵심' 이 드러남.

public 메서드는, 세부적인 작업을 구현하는 private 메서드의 기능들을 모두 조합하여 전체의 기능을 짜서 만들어내는 '커맨더룸(지휘관실)' 같은 공간이다.

- public 메서드의 코드는 처음 소스를 접한 개발자가 봐도 논리적인 로직을 쉽게 파악할 수 있고, 유지보수하기 용이하도록 되어 있어야 한다. (그래야 전체 흐름 파악 용이)

- 즉 개발자가 세부구현부에(ex: private 메서드 부분) 집중하지 않고(신경쓰지 않고도) 논리적인 로직이 쉽게 파악이 되는 코드가 '읽기 좋은 코드'라는 것이다.

=> 따라서 public 메서드의 코드가 얼마나 읽기 쉽고 유지보수하기 용이하게 깔끔한지가 핵심이다.

테스트코드의 존재가 더 적극적인 리팩터링 시도를 가능하게 함

- 리팩터링을 통해 프로덕션 코드를 변경하더라도 테스트 코드를 통해 바로 검증 쉽게 가능

→ 이로 인하여 부담없이 리팩터링을 얼마든지 진행할 수 있는 것

- 만약 테스트를 수동으로 해줘야 하는 상황이면(ex: 메인메서드에서 테스트를 위한 코드들 일일이 작성해주고 실행하는 식..etc) 리팩터링을 하는 것 자체가 부담스러워질 수 있음

- 테스트는 리팩터링을 든든하게 뒷받침해주는 존재, 둘은 동반자적 존재임.