코드 리팩토링이란 코드의 중복을 지우고, 로직을 깨끗하고 이해하기 쉽게 재구성하는 것을 말한다. 리팩토링의 판단 기준은 확장성, 가동성, 유지보수성이 있으며, 이는 종종 코드 최적화, 디버깅, 방어 코드 추가와 같은 행위와 혼동될 수 있다.
리팩토링은 당연하게도 중간에 하는 작업이 아니라 코드 작성을 마친 후에 진행되어야 한다. 기능 구현이 우선이고, 정상 작동되는지 확인한 후에 리팩토링을 진행한다. 리팩토링을 할 때에는 한 번에 하나의 작업에만 집중하고, 동시에 여러 작업을 진행하지 않는다. 물론 리팩토링을 하면서 지속적으로 코드가 정상적으로 동작하는지 확인해야 하고, 리팩토링 작업이 동작에 영향을 주어서는 안된다.
리팩토링은 크게 두 가지로 나뉜다. 하나는 신규 기능 추가를 대비한 "준비를 위한 리팩토링", 또 하나는 높은 가독성을 고려한 "이해를 위한 리팩토링"이다. 각각에 대한 자세한 내용은 아래에서 예제와 함께 살펴보도록 하자.
우선 준비를 위한 리팩토링은 신규 기능을 추가하기 전에 코드를 쉽게 추가할 수 있도록 대비하는 것이 목적이다.
예제1) 파편화된 코드 리팩토링: 동일 코드의 반복을 별도의 Function으로 만들어 이를 호출하는 방식으로 분리
// 리팩토링 전
function printOwing(invoice) {
printBanner();
let outstanding = calculateOutstanding();
// print details
console.log(`name: ${invoice.customer}`);
console.log(`amount: ${outstanding}`);
}
// 리팩토링 후
function printOwing(invoice) {
printBanner();
let outstanding = calculateOutstanding();
printDetails(outstanding);
function printDetails(outstanding) {
console.log(`name: ${invoice.customer}`);
console.log(`amount: ${outstanding}`);
}
}
예제2) 중복된 유사 로직: 의미가 유사한 function을 매개 변수를 이용하여 통합(추가적인 소스 수정 및 배포 불필요)
// 리팩토링 전
function tenPercnetRaise(aPerson) {
aPerson.salary = aPerson.salary.multiply(1.1);
}
function fivePercentRaise(aPerson) {
aPerson.salary = aPerson.salary.multiply(1.05);
}
// 리팩토링 후
function raise(aPerson, factor) {
aPerson.salary = aPerson.salary.multiply(1 + factor);
}
예제3) 모든 분기마다 동일 로직: 모든 분기마다 동일 로직이 있다면 이를 분기문 밖으로 이동시켜 한 번만 작성
// 리팩토링 전
if (isSpecialDeal()) {
total = price * 0.95;
send();
}
else {
total = price * 0.98;
send();
}
// 리팩토링 후
if (isSpecialDeal()) {
total = price * 0.95;
}
else {
total = price * 0.98;
}
send();
다음으로 이해를 위한 리팩토링은 코드의 의도를 쉽고 명확하게 이해할 수 있도록 가독성을 높이는 것이 목적이다.
예제1) 모호한 변수명: 의도를 알 수 없는 모호한 변수명을 직관적으로 선언
// 리팩토링 전
let a = height * width;
// 리팩토링 후
let area = height * width;
예제2) 길어지는 표현식: 표현식이 너무 길어지면, 이를 의도 파악이 가능한 개별 변수로 선언
(소스코드가 길어졌으나 가독성이 눈에 띄게 향상되었다. 코드의 길이와 가독성이 항상 반비례하지는 않는다.)
// 리팩토링 전
return order.quantity * order.itemPrice -
Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +
Math.min(order.quantity * order.itemPrice * 0.1, 100);
// 리팩토링 후
const basePrice = order.quantity * order.itemPrice;
const quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;
const shipping = Math.min(order.quantity * order.itemPrice * 0.1, 100);
return basePrice - quantityDiscount - shipping;
예제3) 변수가 한 번만 변경: 변경되는 변수가 하나이고, 변경이 한 번 뿐이라면 변수 선언 대신 Inline으로 처리
// 리팩토링 전
let basePrice = anOrder.basePrice;
return (basePrice > 1000);
// 리팩토링 후
return anOrder.basePrice > 1000;
여기까지 코드 리팩토링에 대해 알아보았다. 코드 판독 자체가 불가하거나 정상 작동 하지 않는 코드라면 리팩토링 할바에 그냥 새로 짜는 것이 낫다. 그럼 20000
[개발 방법론] 폭포수(Waterfall) 방법론 vs 애자일(Agile) 방법론 (0) | 2024.05.09 |
---|---|
[개발 기법] TDD(Test-Driven Development, 테스트 주도 개발) (0) | 2024.05.06 |
프레임워크(Framework) vs 라이브러리(Library) (0) | 2024.05.05 |
재귀 함수/재귀적 호출(Recursion Function/Recursion Call) (0) | 2024.05.05 |
객체 지향 프로그래밍(Object-Oriented Programming, OOP) (0) | 2024.05.02 |