조건문 나열 + 함수 호출 방식
function calculateMembershipDiscount(tier) {
if (tier === 'BRONZE') return 0.01;
if (tier === 'SILVER') return 0.02;
if (tier === 'GOLD') return 0.03;
if (tier === 'PLATINUM') return 0.05;
if (tier === 'DIAMOND') return 0.1;
return 0;
}
function calculateSeasonDiscount(date) {
const month = date.getMonth();
if (month >= 2 && month <= 4) return 0.02; // 봄
if (month >= 5 && month <= 7) return 0.03; // 여름
if (month >= 8 && month <= 10) return 0.02; // 가을
return 0.04; // 겨울
}
// 나머지 할인 함수들...
function calculateDiscount(user, product, date, paymentMethod) {
let discount = 0;
discount += calculateMembershipDiscount(user.tier);
discount += calculateSeasonDiscount(date);
discount += calculateDayOfWeekDiscount(date.getDay());
discount += calculateCategoryDiscount(product.category);
discount += calculatePaymentMethodDiscount(paymentMethod);
return discount;
}
✔️장점:
간단하고 직관적임.
소규모 프로젝트에서는 빠르다.
❌ 단점:
할인 항목이 늘어난다면 로직이 길어진다.
각 할인함수가 calculateDiscount에 강하게 의존 (결합도가 높다)
새로운 할인 정책을 넣으려면 calculateDiscount에 또 추가 하는데 OCP 위반.
단위 테스트는 calculateHolidayDiscount()도, calculateDiscount()도 모두 테스트해야 함
확장(Extension)에는 열려 있어야 함
수정(Modification)에는 닫혀 있어야 함
전략 패턴
// 할인 전략 함수들
const membershipDiscount = (user, product, date, paymentMethod) => {
const rates = {
'BRONZE': 0.01,
'SILVER': 0.02,
'GOLD': 0.03,
'PLATINUM': 0.05,
'DIAMOND': 0.1,
};
return rates[user.tier] || 0;
};
const seasonDiscount = (_, __, date) => {
const month = date.getMonth();
if (month >= 2 && month <= 4) return 0.02; // 봄
if (month >= 5 && month <= 7) return 0.03; // 여름
if (month >= 8 && month <= 10) return 0.02; // 가을
return 0.04; // 겨울
};
const holidayDiscount = (_, __, date) => {
const holidays = ['2025-01-01', '2024-12-25'];
const today = date.toISOString().slice(0, 10);
return holidays.includes(today) ? 0.05 : 0;
};
위 코드는 할인 방법, 아래 코드는 계산함수
// 전략들을 배열로 관리
const discountStrategies = [
membershipDiscount,
seasonDiscount,
holidayDiscount,
// 필요한 전략 함수들 추가
];
// 총 할인율 계산
function calculateDiscount(user, product, date, paymentMethod) {
return discountStrategies.reduce((total, strategy) => {
return total + strategy(user, product, date, paymentMethod);
}, 0);
}
✔️ 장점:
전략을 객체화함으로써 할인 정책을 각각 캡슐화
새로운 할인 정책 추가 시 기존 코드를 수정할 필요가 없음 (OCP 충족)
테스트와 재사용성 극대화 (전략 하나만 독립적으로 테스트 가능)
동적으로 전략을 추가/제외 가능 (사용자나 상품에 따라 전략 조정 가능)
유지보수가 쉬움: 한 전략의 로직 수정이 다른 전략에 영향을 주지 않음
❌ 단점:
초기에 설계와 클래스 구조가 약간 복잡해짐
간단한 할인 정책이라면 오히려 과설계(overengineering)일 수 있음
요즘 설계에 대한 생각이 많아지면서 이런부분을 기록으로 남기는게 좋다고 생각했다.