[ Programming > Design Pattern ]
[디자인 패턴] 템플릿 메서드 패턴
Template Method 패턴 정복하기
Template Method 패턴은 알고리즘의 구조는 그대로 두면서, 특정 단계만 다르게 구현할 수 있게 해주는 디자인 패턴이에요. 이 튜토리얼을 따라하면 Template Method 패턴의 핵심 개념을 이해하고, 실제 프로젝트에서 활용할 수 있게 됩니다.
학습목표
Template Method 패턴의 동작 원리를 이해한다
간단한 예제를 구현해본다
1. Template Method 패턴 구조
Template Method 패턴은 다음과 같이 추상 클래스와 구현 클래스로 이루어지는 상속을 이용하는 패턴이에요.

Abstract Class (추상 클래스)
템플릿 메서드를 정의하여 알고리즘의 전체 구조를 제공 (메서드 => 알고리즘 실행 뼈대)
각 단계를 나타내는 추상 메서드들을 선언
공통 로직을 구현하는 구체적인 메서드들도 포함 가능
Concrete Class (구현 클래스)
추상 클래스를 상속받아 추상 메서드들을 구현
알고리즘의 특정 단계들을 자신만의 방식으로 정의
위 구조에 후크라 불리는 메서드를 추상 클래스에 선언하여 사용하기도 해요. 후크는 기본적인 내용만 구현되어 있거나, 아무 코드도 들어있지 않은 메소드에요. 보통 서브클래스에서 알고리즘에 끼어드는데 많이 사용되요.
2. Template Method 패턴 예시 - 커피와 차 (음료)

이제 위 구조에 따라 커피와 차를 구현하는데 Template Method를 사용해 보아요. 왜 위 구조로 Coffee와 Tea를 구현했는지 배경을 설명해 볼게요. Coffee와 Tea라는 객체를 만들었는데, 물을 끓이고, 원재료를 넣어 추출하고, 컵에 붓는 과정이 거의 비슷해요. 그래서 이 과정을 공통화 해서 추상화(캡슐화)할 수 있다고 판단할 수 있어요.
공통된 Beverage라는 추상 클래스를 만들고 위 과정을 prepareBeverage라는 메서드에서 순서대로 단계별 함수를 실행하도록 만드는거에요.이렇게 알고리즘 뼈대 역할을 해주는 메서드를 템플릿 메서드라고 해요. 여기서 템플릿 메서드는 prepareBeverage()에요.
prepareBeverage() 메서드에서는 boilWater(), brew(), pourInCup()을 순서대로 실행하는 뼈대가 되요. 여기서 boilWater의 온도와 pourInCup은 Coffee나 Tea가 똑같다고 생각하고 brew()하는 과정만 coffee와 tea에서 다르게 만들고 싶을 거에요. 그래서 brew는 abstract 함수로 선언하여 각각 구현 클래스에서 알고리즘을 구현하도록 만든 거에요.
Abstract Class (추상 클래스)
// 추상 클래스 - 커피와 차를 만드는 과정의 템플릿abstract class Beverage { // 템플릿 메서드 - 전체 알고리즘의 구조를 정의 public final void prepareBeverage() { boilWater(); brew(); pourInCup(); if (customerWantsCondiments()) { // 후크를 사용해 손님이 첨가물 원하는 여부에 따라 함수 실행 결정. addCondiments(); } } // 공통 메서드들 private void boilWater() { System.out.println("물을 끓입니다"); } private void pourInCup() { System.out.println("컵에 따릅니다"); } // 하위 클래스에서 구현해야 하는 추상 메서드들 protected abstract void brew(); protected abstract void addCondiments(); // 훅(hook) 메서드 - 하위 클래스에서 선택적으로 오버라이드 가능 protected boolean customerWantsCondiments() { return true; }}
Concrete Class (구현 클래스)
// 커피 클래스class Coffee extends Beverage { @Override protected void brew() { System.out.println("필터로 커피를 우려냅니다"); } @Override protected void addCondiments() { System.out.println("설탕과 우유를 추가합니다"); }}// 차 클래스class Tea extends Beverage { @Override protected void brew() { System.out.println("찻잎을 우려냅니다"); } @Override protected void addCondiments() { System.out.println("레몬을 추가합니다"); } @Override protected boolean customerWantsCondiments() { return false; // 차에는 기본적으로 첨가물을 넣지 않음 }
3. Template Method와 Factory Method, Strategy 패턴과의 차이
Template Method 패턴은 Factory Method 패턴과 비슷해 보여요. 또한 Strategy 패턴과 역할이 비슷해 보이기도 해요. 그래서 표로 정리해봤어요.
패턴 | 분류 | 목적 | 범위/ 적용 단위 | 핵심 |
---|---|---|---|---|
Template Method | 행위 패턴 | 알고리즘의 골격을 정의하고, 일부 단계를 서브클래스에서 구현하도록 위임 | 클래스: 상위 클래스에서 알고리즘 구조 정의, 하위 클래스에서 구현 | 상위 클래스에서 templateMethod() 정의 → 하위 클래스가 세부 단계 구현 |
Factory Method | 생성 패턴 | 객체 생성을 서브클래스에서 캡슐화하여 클라이언트 코드와 분리 | 클래스: 어떤 클래스의 인스턴스를 만들지 서브클래스가 결정 | 객체 생성 코드를 서브클래스에 위임, 클라이언트는 구체 클래스 몰라도 됨 |
Strategy | 행위 패턴 | 알고리즘을 캡슐화하고 런타임에 교체 가능하도록 하여 행동을 동적으로 결정 | 객체: 객체가 사용할 알고리즘(행동)을 선택/교체 가능 | 알고리즘을 별도 Strategy 객체로 정의 → 컨텍스트 객체가 실행 시 선택 |
그러면 이제 어느 경우에 Template Method를 사용하고, 어느 경우세 Strategy 패턴이나 다른 패턴을 사용할지 정리해 볼게요.
템플릿 메소드를 사용하면 좋은 경우
여러 클래스에서 동일한 알고리즘을 사용하지만 일부만 다를 때
알고리즘 구조를 강제하고 싶을 때 (메서드 순서)
프레임워크나 라이브러리 만들 때 (자바의 Configuration 생각해보면 세부 알고리즘만 정의하면 됌)
템플릿 메소드를 피하는 것이 좋은 경우
런타임에 알고리즘 변경이 필요할 때 => 상속을 이용하기 때문에 불가능
클래스 계층이 이미 복잡할 때
4. 정리 및 마무리
이제 Template Method 패턴에 대해서 아셨나요?
배운 내용
Template Method 패턴의 기본 구조와 동작 원리
Hook 메서드를 활용한 선택적 단계 구현 방법
다른 디자인 패턴과의 차이점
Template Method 적용이 장점이 되는 경우와 나쁜 경우
Template Method 패턴은 알고리즘을 구조화하여 명확히 하고, 세부 구현을 통해 다르게 작동하게 만드는 패턴이에요. 그래서 이 패턴이 사용되는 대표적인 예 중 하나가 Java의 Array가 sort가 템플릿 메서드고 compareTo가 세부 구현이 되는 경우에요. 그리고 Spring의 Configuration도 메서드를 오버라이드 해서 설정하는 것도 프레임워크를 만드는데 사용되는 예시에요. 여러분도 적절히 사용해 보시면 좋을것 같아요.