Spring에서 AOP, 트랜잭션 처리, 템플릿 메서드 등 다양한 기능을 학습하던 중, 익숙한 전략 패턴과 매우 닮은 구조의 템플릿 콜백 패턴을 마주하게 되었습니다. 처음엔 전략 패턴을 조금 더 간단하게 쓴 방식 정도로만 느껴졌지만, 실제로 자주 사용되는 중요한 패턴 중 하나입니다. 이번 글에서는 전략 패턴과의 차이점, 그리고 실무에서 어떻게 활용되는지를 중심으로 정리해보려 합니다.
변하는 알고리즘을 분리하는 디자인 패턴: 전략 패턴
최근에 Spring AOP에대해 공부하면서 Spring에서 Bean 주입을 다루거나, 조건에 따라 다른 구현체를 선택해 사용하는 상황을 자주 마주치면서, 그동안 이름만 알고 있던 전략(Strategy) 패턴의 필요성과
dev-code.tistory.com
템플릿 콜백 패턴 ( Template Callback Pattern )
전략 패턴의 일종으로 전략 패턴의 기본적인 구조에 변화되는 부분을 매번 클래스로 만들지 않고, 익명 내부 클래스를 이용해 바로 생성해서 이용 하는 식으로 전략패턴과 매우 흡사합니다.
알고리즘의 전체적인 흐름(템플릿)은 고정되어 있지만, 특정 단계의 구체적인 동작(콜백)은 변경할 수 있도록 설계하는 것입니다. 핵심은 템플릿이 알고리즘의 구조를 정의하고, 변하는 부분의 실행을 외부로 위임한다는 점입니다.
전략 패턴 VS 템플릿 콜백 패턴
템플릿 콜백 패턴과 전략 패턴 모두 행위를 캡슐화 하고 위임 한다는 점에선 동일 하지만, 사용 방식과 목적에 있어 뚜렷한 차이를 보입니다.
| 전략 패턴(Strategy Partten) | 템플릿 콜백 패턴(Template Callback Pattern) | |
| 목적 | 알고리즘 자체를 캡슐화화여 동적으로 선택/교체 가능하게 함 | 알고리즘 구조는 고정하고 특정 단계에 동작만 변경 가능하게 함 |
| 결정 주체 | 클라이언트가 사용할 알고리즘을 선택하고 Context에 제공 | 템플릿이 알고리즘 흐름을 주도하고, 변하는 동작(콜백)을 외부에서 제공 받아 실행 |
| 구조 | Context가 전략 인터페이스를 필드로 가짐 | Template이 콜백 인터페이스의 메서드를 호출하는 템플릿 메서드를 가짐 |
| 초점 | 알고리즘의 변경 및 확장에 초점 | 알고리즘의 특정 부분에 동작 변경에 초점 |
템플릿 콜백 패턴으로의 전환
기존 전략 패턴에서는 할인 전략 클래스를 명확하게 나눠서 작성했지만, 아래와 같이 익명 클래스나 람다식을 활용하면 외부에서 직접 전략(콜백)을 주입하는 방식으로 구현이 가능합니다.
// 할인 정책 - 인터페이스
public interface DiscountStrategy {
int applyDiscount(int price);
}
// 할인 정책을 사용하는 결제 서비스 - Context
public class PaymentService {
public void pay(DiscountStrategy strategy, int price) {
int discounted = strategy.applyDiscount(price);
System.out.println("기존 금액 : " + price + " | 최종 금액 : " + discounted);
}
}
이전 예제에 사용한 코드의 설명은 생략하도록 하겠습니다.
PaymentService paymentService = new PaymentService();
// DiscountStrategy를 여기서 주입
paymentService.pay(new DiscountStrategy() {
@Override
public int applyDiscount(int price) {
return price - 2000;
}
}, 20000);
// 람다 식으로 변경 가능
paymentService.pay(price -> price - 2000, 20000);
이 방식은 템플릿 콜백 패턴(Template Callback Pattern)이라고 불리며,
- 템플릿 메서드는 고정된 흐름을 가지고
- 콜백(전략)은 동작의 일부를 외부에서 주입받습니다.
왜 템플릿 "콜백" 패턴인가?
- pay() 메서드는 템플릿 메서드처럼 전체 흐름(지불 처리)을 고정하고,
- 전략(=콜백 객체 혹은 람다)은 그 흐름 안에서 할인 로직만 유연하게 교체할 수 있도록 해 줍니다.
즉, 전략 패턴의 유연함은 유지하면서도, 코드를 더 간결하게 만들고 싶을 때 유용한 패턴입니다.
템플릿 콜백 패턴의 특징, 장단점
🌟 장점
- 중복 제거 및 재사용성 증가
고정된 템플릿 흐름을 공통화하고, 유동적인 부분(콜백)만 분리함으로써 중복을 제거할 수 있습니다.
다양한 동작을 하나의 공통 흐름에서 재사용할 수 있습니다. - 코드 간결화
전략 클래스를 따로 만들지 않고, 익명 클래스나 람다식으로 즉석에서 동작 정의가 가능하므로 코드가 짧고 직관적입니다. - 유연한 확장성
새로운 동작이 필요할 때 기존 구조를 변경하지 않고도 쉽게 확장할 수 있습니다
⚠️ 단점
- 복잡한 콜백 로직에는 부적합
콜백 안의 로직이 복잡해지면, 익명 클래스나 람다식 내부가 너무 길어져 오히려 가독성이 떨어질 수 있습니다. - 디버깅과 추적이 어려움
람다식은 익명 객체이기 때문에 디버깅 시 위치 파악이 어렵고, 로그에서 어떤 전략이 사용됐는지 명확하지 않을 수 있습니다. - 과도한 추상화로 인한 혼란
템플릿과 콜백 개념이 뒤섞이면, 패턴 구조를 명확히 이해하지 못한 개발자에겐 추상적으로 느껴질 수 있습니다.
📌 정리
템플릿 콜백 패턴은 전략 패턴과 매우 유사하지만, 전략을 익명 클래스나 람다로 넘겨 더 간결하게 사용할 수 있다는 점이 특징입니다. Spring에서 AOP, 트랜잭션, JdbcTemplate 등을 공부하다 보면 자연스럽게 마주하게 되는 패턴이며, 전체 흐름은 고정하고 핵심 로직만 유연하게 바꿔야 할 때 유용합니다. 패턴 자체가 복잡하지 않기 때문에 "이런 구조도 있구나" 정도로 가볍게 익혀두면 될꺼같습니다.
'개발' 카테고리의 다른 글
| Spring AOP를 이해하기 전 : 프록시 패턴 (0) | 2025.05.20 |
|---|---|
| 변하는 알고리즘을 분리하는 디자인 패턴: 전략 패턴 (0) | 2025.05.18 |
| 반복되는 흐름을 정리하는 디자인 패턴: 템플릿 메서드 패턴 (0) | 2025.05.17 |