템플릿 메서드 패턴 (Template Method Pattern)

한눈에 보기

알고리즘의 골격을 상위 클래스에 고정하고 일부 단계만 하위 클래스가 구현하는 행위 패턴이다. 훅 메서드, 할리우드 원칙, 전략 패턴과의 상속 대 합성 비교를 정리한다.

최종 업데이트 2026.09.17

템플릿 메서드 패턴(Template Method Pattern)은 알고리즘의 전체 골격을 상위 클래스의 한 메서드에 정의해 두고, 골격을 이루는 개별 단계 중 일부를 하위 클래스가 오버라이드하여 구체화하도록 하는 행위 디자인 패턴이다. 템플릿 메서드 패턴을 적용하면 알고리즘의 순서와 구조는 상위 클래스가 통제하면서, 단계별 세부 구현만 하위 클래스마다 다르게 가져갈 수 있다. 상속을 이용하는 대표적인 코드 재사용 패턴이다.

패턴의 의도

비슷한 절차를 따르는 코드가 여러 곳에 있으면 중복이 생긴다. 예를 들어 CSV 파일 처리와 JSON 파일 처리는 "파일 열기, 파싱, 검증, 저장, 파일 닫기"라는 순서가 같고 파싱 단계만 다르다. 이를 각각 별도 클래스에 통째로 구현하면 열기와 닫기 같은 공통 절차가 복사되고, 절차가 바뀔 때 모든 사본을 고쳐야 한다.

템플릿 메서드 패턴의 의도는 변하지 않는 절차(골격)와 변하는 단계(세부 구현)를 분리하는 것이다. 상위 클래스는 단계들을 순서대로 호출하는 템플릿 메서드를 제공하고, 변하는 단계는 추상 메서드로 선언해 하위 클래스에 구현을 맡긴다. 이 구조는 "우리가 너를 호출할 테니 너는 우리를 호출하지 마라"라는 할리우드 원칙(Hollywood Principle)으로 요약된다. 제어의 흐름을 하위 클래스가 아니라 상위 클래스(프레임워크)가 쥐는 제어의 역전이 일어나는 것이다.

구조와 참여 객체

  • 추상 클래스(Abstract Class): 템플릿 메서드와 단계 메서드들을 정의한다. 템플릿 메서드는 단계들의 호출 순서를 고정하며, 하위 클래스가 순서를 바꾸지 못하도록 보통 final로 선언한다.
  • 추상 단계(Primitive Operation): 하위 클래스가 반드시 구현해야 하는 가변 단계다. 추상 메서드로 선언된다.
  • 훅 메서드(Hook Method): 기본 구현(대개 빈 구현)을 가진 선택적 확장 지점이다. 하위 클래스는 필요할 때만 오버라이드한다.
  • 구체 클래스(Concrete Class): 추상 단계를 구현하여 알고리즘을 완성한다. 템플릿 메서드 자체는 건드리지 않는다.

Java 코드 예시

// 추상 클래스: 절차의 골격을 고정한다
public abstract class DataProcessor {

    // 템플릿 메서드: 순서 변경을 막기 위해 final
    public final void process(String path) {
        open(path);
        String data = read();
        Object parsed = parse(data);   // 가변 단계
        if (needValidation()) {        // 훅 메서드
            validate(parsed);
        }
        save(parsed);
        close();
    }

    private void open(String path) { System.out.println(path + " 열기"); }
    private String read() { return "raw-data"; }
    private void save(Object parsed) { System.out.println("저장"); }
    private void close() { System.out.println("닫기"); }

    // 하위 클래스가 반드시 구현하는 추상 단계
    protected abstract Object parse(String data);
    protected abstract void validate(Object parsed);

    // 훅: 기본값을 제공하고 선택적으로 오버라이드
    protected boolean needValidation() { return true; }
}

// 구체 클래스: 가변 단계만 채운다
public class CsvProcessor extends DataProcessor {
    @Override
    protected Object parse(String data) {
        return data.split(",");
    }

    @Override
    protected void validate(Object parsed) {
        System.out.println("CSV 형식 검증");
    }
}

// 사용
DataProcessor processor = new CsvProcessor();
processor.process("report.csv");

JSON 처리가 필요하면 JsonProcessor를 추가로 상속하면 되고, 절차에 압축 해제 단계가 추가되어도 템플릿 메서드 한 곳만 고치면 모든 하위 클래스에 반영된다. 예시에서 접근 제어자의 역할 분담에도 주목할 필요가 있다. 골격인 process는 public, 하위 클래스의 확장 지점은 protected, 하위 클래스가 몰라도 되는 공통 단계는 private으로 나뉘어 있어, 컴파일러가 설계 의도를 강제하도록 만들어져 있다.

장단점과 사용 시점

장점은 공통 절차의 중복 제거와 절차에 대한 단일한 통제 지점 확보다. 알고리즘의 순서가 상위 클래스에 고정되어 있으므로 하위 클래스가 실수로 순서를 어길 수 없고, 하위 클래스는 자신이 책임질 단계에만 집중하면 된다. 프레임워크 설계에서 특히 강력해서, 프레임워크가 큰 흐름을 정의하고 사용자가 특정 지점만 오버라이드하는 구조의 근간이 된다.

단점은 상속에 기반한다는 데서 나온다. 하위 클래스는 컴파일 타임에 상위 클래스에 묶이므로 런타임에 동작을 교체할 수 없고, Java는 단일 상속만 지원하므로 상속 자원을 하나 소모한다. 상위 클래스의 변경이 모든 하위 클래스에 파급되는 취약 기반 클래스 문제도 있으며, 단계가 많아지면 어떤 메서드를 오버라이드해야 하는지 파악하기 어려워진다. 절차는 같고 일부 단계만 다른 클래스가 둘 이상 반복될 때, 그리고 절차의 순서를 강제하고 싶을 때가 적절한 사용 시점이다. 실제 사례로는 서블릿의 HttpServlet이 요청 처리 골격을 제공하고 개발자가 doGet만 오버라이드하는 구조, JUnit이 테스트 전후의 실행 순서를 프레임워크가 통제하는 구조가 있다.

유사 패턴과 비교

구분템플릿 메서드전략(Strategy)팩토리 메서드(Factory Method)
재사용 메커니즘상속합성(주입)상속
가변 지점의 크기알고리즘의 일부 단계알고리즘 전체객체 생성 단계
교체 시점컴파일 타임런타임컴파일 타임
제어 주체상위 클래스컨텍스트와 클라이언트상위 클래스

전략 패턴과의 비교가 핵심이다. 템플릿 메서드는 절차의 뼈대를 공유하며 단계 수준에서 변화를 허용하고, 전략은 알고리즘 전체를 객체로 갈아 끼운다. 팩토리 메서드는 템플릿 메서드의 가변 단계가 하필 "객체 생성"인 특수한 경우로 이해할 수 있다. 두 패턴 중 무엇을 쓸지 고민된다면, 절차의 순서 통제가 중요하면 템플릿 메서드, 런타임 교체가 중요하면 전략이라는 기준으로 판단하면 된다.

면접에서 이렇게 물어본다

  • 템플릿 메서드 패턴에서 템플릿 메서드를 final로 선언하는 이유는 무엇인가.
  • 훅 메서드는 추상 메서드와 어떻게 다르고 언제 사용하는가.
  • 템플릿 메서드 패턴과 전략 패턴을 상속과 합성의 관점에서 비교해 보라.
  • 할리우드 원칙과 제어의 역전(IoC)이 이 패턴과 어떻게 연결되는지 설명해 보라.
  • 템플릿 메서드 패턴이 상속 기반이라서 생기는 한계와 그 대안을 말해 보라.
디자인 패턴 문서 전체 보기

이 개념, 내 코드에서는 어떻게 물어볼까요

데브핏(DevFit)에 채용공고 URL을 붙여 넣고 레포지토리를 연결하면, 내가 쓴 커밋에서 예상 질문과 어필 포인트를 만듭니다. 하루 10회까지 무료입니다. 합불 판정이나 지원자 랭킹은 만들지 않고, 최종 판단은 사람이 합니다.

공고 넣고 시작하기