자바스크립트 TDD에서의 리팩토링 기법

리팩토링은 코드를 개선하고 유지보수하기 쉽게 만들기 위해 기존 코드를 수정하는 과정입니다. 자바스크립트 Test-driven development(TDD)에서도 리팩토링은 중요한 부분입니다. 이번 블로그 포스트에서는 자바스크립트 TDD에서의 리팩토링 기법에 대해 알아보겠습니다.

1. 중복 제거

TDD를 통해 단위 테스트를 작성하다 보면 코드 내에 중복된 부분이 발견될 수 있습니다. 중복된 코드는 유지보수에 어려움을 줄 수 있으며, 버그 발생의 가능성도 높아집니다. 따라서 중복된 코드를 제거하여 코드의 가독성을 높이고 유지보수성을 향상시킬 수 있습니다.

예를 들어, 다음과 같은 중복된 코드가 있다고 가정해봅시다.

function calculateArea(width, height) {
  const area = width * height;
  console.log(`The area is ${area}`);
}

function calculatePerimeter(width, height) {
  const perimeter = 2 * (width + height);
  console.log(`The perimeter is ${perimeter}`);
}

위의 코드는 calculateArea 함수와 calculatePerimeter 함수에서 중복된 계산을 수행하고 있습니다. 이 중복된 코드를 제거하기 위해 다음과 같이 리팩토링할 수 있습니다.

function calculateArea(width, height) {
  return width * height;
}

function calculatePerimeter(width, height) {
  return 2 * (width + height);
}

위의 리팩토링된 코드에서는 중복된 코드를 제거하고, 각 함수는 계산된 값을 반환하도록 수정되었습니다.

2. 함수 분리

자바스크립트 TDD에서는 각 테스트 케이스마다 함수를 작성하는 것이 일반적입니다. 하지만 테스트 케이스의 수가 많아지면 함수의 길이가 길어지고 가독성이 떨어지는 문제가 발생할 수 있습니다. 이 경우, 함수를 더 작은 단위로 분리하여 가독성을 높이고 유지보수성을 향상시킬 수 있습니다.

예를 들어, 다음과 같은 테스트 케이스가 있다고 가정해봅시다.

it('should calculate the price of a product including tax and discount', () => {
  const price = 1000;
  const taxRate = 0.1;
  const discountRate = 0.2;

  const taxedPrice = price * (1 + taxRate);
  const discountedPrice = taxedPrice * (1 - discountRate);

  expect(calculatePrice(price, taxRate, discountRate)).toBe(discountedPrice);
});

위의 테스트 케이스에서 calculatePrice 함수의 길이가 길어져서 가독성이 떨어집니다. 이를 해결하기 위해 다음과 같이 함수를 분리할 수 있습니다.

function calculateTaxedPrice(price, taxRate) {
  return price * (1 + taxRate);
}

function calculateDiscountedPrice(taxedPrice, discountRate) {
  return taxedPrice * (1 - discountRate);
}

function calculatePrice(price, taxRate, discountRate) {
  const taxedPrice = calculateTaxedPrice(price, taxRate);
  const discountedPrice = calculateDiscountedPrice(taxedPrice, discountRate);
  return discountedPrice;
}

it('should calculate the price of a product including tax and discount', () => {
  const price = 1000;
  const taxRate = 0.1;
  const discountRate = 0.2;
  const expectedPrice = calculatePrice(price, taxRate, discountRate);

  expect(expectedPrice).toBe(800);
});

위의 코드에서는 calculatePrice 함수를 calculateTaxedPricecalculateDiscountedPrice 함수로 분리하여 가독성을 높였습니다.

3. 조건문 단순화

복잡한 조건문은 가독성을 떨어뜨리고 버그 발생 가능성을 높입니다. 자바스크립트 TDD에서는 조건문을 단순화하여 가독성과 테스트 용이성을 높이는 것이 중요합니다.

예를 들어, 다음과 같은 테스트 케이스가 있다고 가정해봅시다.

it('should return the type of a person based on their age', () => {
  const age = 30;

  let type;
  if (age < 18) {
    type = 'Teenager';
  } else if (age >= 18 && age < 60) {
    type = 'Adult';
  } else {
    type = 'Senior';
  }

  expect(getPersonType(age)).toBe(type);
});

위의 테스트 케이스에서는 조건문의 분기가 복잡하게 작성되어 가독성이 떨어집니다. 이를 해결하기 위해 조건문을 단순화할 수 있습니다.

function getPersonType(age) {
  if (age < 18) {
    return 'Teenager';
  } else if (age < 60) {
    return 'Adult';
  } else {
    return 'Senior';
  }
}

it('should return the type of a person based on their age', () => {
  const age = 30;
  const expectedType = getPersonType(age);

  expect(expectedType).toBe('Adult');
});

위의 코드에서는 조건문을 단순화하여 가독성을 높였습니다.

4. 테스트 케이스 추가

자바스크립트 TDD에서 리팩토링을 수행할 때에는 기존 테스트 케이스가 모두 통과하는지 확인해야 합니다. 또한, 리팩토링으로 인한 새로운 버그가 발생하지 않도록 추가적인 테스트 케이스를 작성하는 것도 중요합니다.

it('should calculate the total price of the cart', () => {
  const cart = [
    { price: 1000, quantity: 3 },
    { price: 500, quantity: 2 },
    { price: 2000, quantity: 1 },
  ];
  const expectedTotalPrice = calculateTotalPrice(cart);

  expect(expectedTotalPrice).toBe(5500);
});

위의 테스트 케이스는 장바구니(cart)에 담긴 상품들의 가격과 수량을 기반으로 총 가격을 계산하는 기능을 테스트합니다. 리팩토링을 수행한 후에는 기존의 테스트 케이스가 모두 통과하는지 확인하고, 추가적인 테스트 케이스를 작성하여 새로운 버그가 발생하는지 확인해야 합니다.

마무리

자바스크립트 TDD에서 리팩토링은 코드의 가독성과 유지보수성을 향상시키는 데 중요한 역할을 합니다. 중복을 제거하고, 함수를 분리하며, 조건문을 단순화하고, 테스트 케이스를 추가하는 등의 리팩토링 기법을 활용하여 안정적이고 유지보수하기 쉬운 코드를 작성할 수 있습니다.