Skip to content

액션의 암묵적 의존성을 최소화하기

이전 장에서는 액션에서 암묵적 입력과 출력을 제거해 계산으로 바꿔보았습니다. 하지만 프로그램에서 액션은 반드시 필요하기 때문에 이런 방식으로 모든 액션을 없앨 수는 없습니다.

대신, 액션에서 암묵적 입력과 출력을 줄여 설계를 개선할 수 있습니다. 이번 장에서는 액션을 완전히 제거하는 것이 아니라, 액션이 가진 암묵적 의존성을 최소화하는 방법을 살펴보겠습니다.

1. 암묵적 입력과 출력을 줄여야 하는 이유

어떤 함수가 암묵적 입력·출력을 가진다면, 그 함수는 다른 컴포넌트와 강하게 연결됩니다. 예를 들어, 장바구니의 총액을 계산하는 아래 함수를 보겠습니다.

tsx
function calculateCartTotal() {
    // 암묵적 입력: 전역 변수 shopping_cart 읽기
    let total = 0;
    for (let item of shopping_cart) {
        total += item.price;
    }

    // 암묵적 출력: DOM 업데이트
    updateTotalDisplay(total);

    return total;
}

이 함수가 실행되는 동안은, 전역 변수 shopping_cart 값이 바뀌어서는 안 됩니다. 또 어떤 경우에는 단순히 총액만 필요할 뿐 DOM 업데이트는 원하지 않을 수도 있습니다.

즉, 암묵적 입력과 출력은 함수의 사용 범위를 좁히고 실행을 제한하는 요인이 됩니다.

2. 엉켜 있는 코드 풀어내기

복잡하게 얽힌 함수를 개선하는 방법은 작은 단위로 나누는 것입니다. 이렇게 분리하면 다음과 같은 장점이 있습니다.

  1. 재사용성: 작을수록 하는 일이 적어 여러 곳에서 다시 쓸 수 있습니다.
  2. 유지보수성: 코드가 단순해져 이해하기 쉽습니다.
  3. 테스트 용이성: 한 가지 일만 담당하기 때문에 테스트가 쉽습니다.

2.1 실제로 분리하기

장바구니에 제품을 추가하는 함수를 보겠습니다.

tsx
function add_item(cart, name, price) {
    var new_cart = cart.slice(); // 1. 배열 복사
    new_cart.push({
        // 2. 아이템 객체 생성 후 추가
        name,
        price,
    });
    return new_cart; // 3. 복사본 반환
}

add_item(shopping_cart, "shoes", 3.45);

겉보기에는 간단하지만, 이 함수는 여러 동작을 한꺼번에 처리하고 있습니다. 이를 더 작은 단위로 나누면 다음과 같이 정리할 수 있습니다.

tsx
// 일반적인 배열 연산으로 분리
function add_element_last(array, elem) {
    var new_array = array.slice();
    new_array.push(elem);
    return new_array;
}

// 장바구니 전용 함수로 분리
function add_item(cart, item) {
    return add_element_last(cart, item);
}

// 아이템 생성 함수도 분리
function make_cart_item(name, price) {
    return { name, price };
}

// 사용할 때
add_item(shopping_cart, make_cart_item("shoes", 3.45));

정리하며

액션에서 암묵적 입력과 출력을 줄이고 계산을 분리하면 코드의 재사용성과 명확성이 높아집니다. 이는 결국 더 단단하고 유지보수하기 쉬운 프로그램 설계로 이어집니다.