액션에서 계산 빼내기
액션 코드에는 종종 암묵적인 입력과 출력이 숨어 있습니다. 이를 명시적으로 바꾸면 테스트하기 쉽고 재사용 가능한 코드를 만들 수 있습니다.
스터디 회차: 3회차 (2025년 8월 19일)
문제 상황 살펴보기
예제: 구매합계가 20달러 이상이면 무료배송 아이콘 표시
tsx
var shopping_cart = [];
var shopping_cart_total = 0;
function calc_cart_total() {
shopping_cart_total = 0;
for (var i = 0; i < shopping_cart.length; i++) {
var item = shopping_cart[i];
shopping_cart_total += item.price;
}
set_cart_total_dom();
update_shipping_icons();
update_tax_dom();
}
이 코드는 절차적으로 이해하기는 쉽지만 몇 가지 문제가 있습니다.
문제점
- 장바구니 정보를 전역변수에서 직접 가져오고 있습니다. (DB에서 가져와야 한다면 변경해야 합니다.)
- 계산 결과를 DOM에 바로 반영합니다. (꼭 DOM을 변경해야 하는 건 아닐 수 있습니다.)
- 즉, 입력과 출력이 고정되어 있어서 재사용성이 낮습니다.
따라서, 계산 로직을 함수로 추출해 입력과 출력을 명시적으로 다루면, 다양한 상황에서 더 유연하게 활용할 수 있습니다.
개선하기
1. 암묵적 입력과 출력 찾기
tsx
function calc_cart_total() {
shopping_cart_total = 0; // 암묵적 출력
for (var i = 0; i < shopping_cart.length; i++) {
var item = shopping_cart[i]; // 암묵적 입력
shopping_cart_total += item.price; // 암묵적 출력
}
set_cart_total_dom(); // DOM 업데이트
update_shipping_icons();
update_tax_dom(); // DOM 업데이트
}
shopping_cart
와shopping_cart_total
은 전역변수라서 함수 안팎으로 암묵적으로 드나듭니다.- DOM 업데이트 코드도 섞여 있어 테스트가 어렵습니다.
암묵적 입력과 출력이란?
인자는 명시적 입력이고 리턴값은 명시적 출력입니다. 이 두가지를 제외하고 발생하는 모든 입출력은 암묵적으로 이루어지며 함수형 프로그래밍에서는 "부수효과"라고 부릅니다.
전역변수를 읽는 것은 데이터가 함수 안으로 들어오는 일이므로 "암묵적 입력"이고,
전역변수를 변경하는 것은 함수에서 데이터가 나가는 일이므로 "암묵적 출력"입니다.
2. 계산 부분만 따로 추출하기
tsx
function calc_cart_total() {
calc_total();
set_cart_total_dom();
update_shipping_icons();
update_tax_dom();
}
function calc_total() {
shopping_cart_total = 0;
for (var i = 0; i < shopping_cart.length; i++) {
var item = shopping_cart[i];
shopping_cart_total += item.price;
}
}
- 계산 로직을
calc_total
로 분리합니다. - 하지만 여전히 전역변수에 의존하고 있습니다.
3. 전역변수를 지역변수와 리턴값으로 교체하기
tsx
function calc_cart_total() {
shopping_cart_total = calc_total();
set_cart_total_dom();
update_shipping_icons();
update_tax_dom();
}
function calc_total() {
var total = 0; // <- 지역변수로 변경
for (var i = 0; i < shopping_cart.length; i++) {
var item = shopping_cart[i];
total += item.price;
}
return total; // <- 지역변수 리턴
}
- 전역변수
shopping_cart_total
에 직접 더하지 않고, 지역변수total
을 사용한 뒤 리턴하도록 수정합니다. - 하지만 여전히 입력(
shopping_cart
)은 전역변수에 의존합니다.
4. 입력까지 명시적으로 받기
tsx
function calc_cart_total() {
shopping_cart_total = calc_total(shopping_cart); // 계산
set_cart_total_dom();
update_shipping_icons();
update_tax_dom();
}
function calc_total(cart) {
var total = 0;
for (var i = 0; i < cart.length; i++) {
var item = cart[i]; // 인자를 활용
total += item.price;
}
return total;
}
- 이제
calc_total
은cart
배열을 인자로 받아 계산합니다. calc_total
는 암묵적 입력/출력이 모두 제거되어, 부수효과 없는 순수함수가 되었습니다.calc_cart_total
은 DOM 업데이트를 담당하고,calc_total
은 계산만 담당합니다.
정리하기
- 액션 코드에는 암묵적인 입력과 출력이 숨어 있습니다.
- 전역변수 읽기 = 암묵적 입력, 전역변수 수정 = 암묵적 출력
- 암묵적 입력은 함수 인자로, 암묵적 출력은 리턴값으로 바꾸어야 합니다.
- 이렇게 하면 계산 로직은 순수 함수로 만들어져 테스트와 재사용이 쉬워집니다.