13-5. 템플릿 메서드 패턴 (Template Method Pattern)

박은서's avatar
Feb 24, 2026
13-5. 템플릿 메서드 패턴 (Template Method Pattern)

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

1️⃣ 템플릿 메서드 패턴이란?

1) 개념

  • 알고리즘의 뼈대는 고정하고, 일부 단계만 바꿀 수 있게 하는 패턴
전체 작업 흐름은 부모 클래스가 정해두고, 세부 동작은 자식 클래스가 결정하는 구조

2️⃣ 비유로 이해하기

1) 요리 레시피

  • 라면 끓이기 과정
    • 1️⃣ 물 끓이기
      2️⃣ 면 넣기
      3️⃣ 스프 넣기
      4️⃣ 마무리
  • 스프 종류는 다를 수 있음
  • 토핑은 다를 수 있음
  • 전체 순서는 고정, 세부 내용만 변경
➡️ 이게 템플릿 메서드 패턴

3️⃣ 템플릿 메서드 패턴이 필요한 이유

  • 비슷한 작업들 존재
    • 전체 과정은 거의 동일
    • 일부 단계만 다름
➡️ 매번 코드를 복붙하면 유지보수 지옥 😱
⬇️
  • 공통 흐름은 한 번만 작성
  • 다른 부분만 교체 가능

4️⃣ 핵심 특징 ⭐

  • 알고리즘 구조 고정
  • 세부 구현 유연
  • 코드 재사용 극대화
  • 변경 영향 최소화

5️⃣ 템플릿 메서드 패턴의 장단점

1) 장점 👍

  • 코드 중복 제거
  • 유지보수 쉬움
  • 구조 안정적
  • 확장 용이

2) 단점 👎

  • 클래스 수 증가
  • 설계 이해 필요
  • 과도하게 쓰면 복잡

6️⃣ 언제 쓰면 좋을까?

  • 작업 순서는 동일한데
  • 일부 단계만 달라질 때
    • 파일 처리 (CSV / Excel / JSON)
    • 게임 캐릭터 행동 로직
    • 로그인 절차 (SNS / 이메일 등)

7️⃣ 구성 요소

1) 부모 클래스 – 작업 순서 정의

  • 역할
    • 알고리즘의 뼈대 제공
public abstract class Parent { // ✅ 템플릿 메서드 (작업 순서 고정) public final void process() { stepA(); stepB(); // 자식이 변경 가능 stepC(); stepD(); } protected void stepA() { System.out.println("Step A 실행"); } // ✅ 자식에게 위임 protected abstract void stepB(); protected void stepC() { System.out.println("Step C 실행"); } protected void stepD() { System.out.println("Step D 실행"); } }

💡 핵심 포인트 💡

  • abstract class → 직접 생성 불가
  • final process() → 순서 변경 방지 🚫
  • abstract stepB() → 변경 지점

2) 자식 클래스 – 특정 단계만 변경

  • 역할
    • 일부 단계만 구현
public class Child extends Parent { @Override protected void stepB() { System.out.println("Step B 특별 처리 ✨"); } }

3) 실행 코드

public class Main { public static void main(String[] args) { Parent obj = new Child(); obj.process(); } }

🖥 실행 결과

Step A 실행 Step B 특별 처리 ✨ Step C 실행 Step D 실행
➡️ 전체 흐름은 부모가 제어
➡️ 변경은 특정 단계만

8️⃣ 코드 예시

1) 부모 클래스 (Template)

public abstract class DataProcessor { // ✅ 템플릿 메서드 (알고리즘 뼈대) public final void process() { readData(); processData(); // 변경 가능한 부분 saveData(); } // ✅ 공통 로직 private void readData() { System.out.println("데이터를 읽습니다."); } // ✅ 자식이 구현해야 하는 부분 protected abstract void processData(); // ✅ 공통 로직 private void saveData() { System.out.println("데이터를 저장합니다."); } }

💡 핵심 포인트

  • abstract class → 객체 직접 생성 불가
  • final process() → 순서 변경 방지 🚫
  • abstract method → 자식에게 위임

2) 자식 클래스 – Excel 처리

public class ExcelProcessor extends DataProcessor { @Override protected void processData() { System.out.println("Excel 데이터 가공 중..."); } }

3) 자식 클래스 – CSV 처리

public class CsvProcessor extends DataProcessor { @Override protected void processData() { System.out.println("CSV 데이터 가공 중..."); } }

4) 실행 코드 (Client)

public class Main { public static void main(String[] args) { DataProcessor excel = new ExcelProcessor(); excel.process(); System.out.println("----------------"); DataProcessor csv = new CsvProcessor(); csv.process(); } }

🖥 실행 결과

데이터를 읽습니다. Excel 데이터 가공 중... 데이터를 저장합니다. ---------------- 데이터를 읽습니다. CSV 데이터 가공 중... 데이터를 저장합니다.
➡️ 흐름은 동일, 세부 동작만 다름

9️⃣ 다른 패턴과 차이

패턴
차이점
전략 패턴
알고리즘 자체 교체
템플릿 메서드
알고리즘 구조는 고정
➡️ 전략 = 전체 교체
➡️ 템플릿 = 일부 교체

🔟 그림으로 이해하기

notion image

2. 실습 (ex05)

1️⃣ 기본

1) Teacher.java

C:\workspace\java_lab\designapp\src\ex05\teacher\TeacherTemplate.java
package ex05; import ex05.teacher.Teacher; public class App { public static void main(String[] args) { Teacher tt = new Teacher(); tt.입장하기(); tt.출석부르기(); tt.강의하기(); tt.퇴장하기(); } }

2) App.java

C:\workspace\java_lab\designapp\src\ex05\App.java
package ex05; import ex05.teacher.TeacherTemplate; public class App { public static void main(String[] args) { TeacherTemplate tt = new TeacherTemplate(); tt.입장하기(); tt.출석부르기(); tt.강의하기(); tt.퇴장하기(); } }

3) 결과

notion image

2️⃣ 강의하기() 메서드만 다르게

1) Teacher.java

C:\workspace\java_lab\designapp\src\ex05\teacher\Teacher.java
package ex05.teacher; public abstract class Teacher { public void 입장하기() { System.out.println("입장하기"); } public void 출석부르기() { System.out.println("출석부르기"); } // 구현체에게 구체적인 행위를 미루기 public abstract void 강의하기(); public void 퇴장하기() { System.out.println("퇴장하기"); } }

2) HtmlTeacher.java

C:\workspace\java_lab\designapp\src\ex05\teacher\HtmlTeacher.java
package ex05.teacher; public class HtmlTeacher extends Teacher { @Override public void 강의하기() { System.out.println("html 강의하기"); } }

3) App.java

C:\workspace\java_lab\designapp\src\ex05\App.java
package ex05; import ex05.teacher.HtmlTeacher; import ex05.teacher.Teacher; public class App { public static void main(String[] args) { Teacher tt = new HtmlTeacher(); tt.입장하기(); tt.출석부르기(); tt.강의하기(); tt.퇴장하기(); } }

4) 결과

notion image

3️⃣ PythonTeacher 클래스 추가

1) PythonTeacher.java

C:\workspace\java_lab\designapp\src\ex05\teacher\PythonTeacher.java
package ex05.teacher; public class PythonTeacher extends Teacher{ @Override public void 강의하기() { System.out.println("Python 강의하기"); } }

2) App.java

C:\workspace\java_lab\designapp\src\ex05\App.java
package ex05; import ex05.teacher.HtmlTeacher; import ex05.teacher.PythonTeacher; import ex05.teacher.Teacher; public class App { public static void main(String[] args) { Teacher tt = new PythonTeacher(); tt.입장하기(); tt.출석부르기(); tt.강의하기(); tt.퇴장하기(); } }

3) 결과

notion image

4️⃣ 수업하기() 메서드 만들기

1) Teacher.java

C:\workspace\java_lab\designapp\src\ex05\teacher\Teacher.java
package ex05.teacher; public abstract class Teacher { // 순서 보장 public void 수업하기() { 입장하기(); 출석부르기(); 강의하기(); 퇴장하기(); } private void 입장하기() { System.out.println("입장하기"); } private void 출석부르기() { System.out.println("출석부르기"); } // 구현체에게 구체적인 행위를 미루기 protected abstract void 강의하기(); // private하면 자식이 상속을 못하기 때문에 protected! private void 퇴장하기() { System.out.println("퇴장하기"); } }
💡
순서를 실수할 수 있기 때문에 수업하기() 메서드로 순서 보장해주고, 그 안의 메서드 접근 못하도록 private으로 접근 제한

2) App.java

C:\workspace\java_lab\designapp\src\ex05\App.java
package ex05; import ex05.teacher.HtmlTeacher; import ex05.teacher.PythonTeacher; import ex05.teacher.Teacher; public class App { public static void main(String[] args) { Teacher tt = new PythonTeacher(); tt.수업하기(); } }

3) JavaTeacher.java

C:\workspace\java_lab\designapp\src\ex05\teacher\JavaTeacher.java
package ex05.teacher; public class JavaTeacher extends Teacher{ @Override protected void 강의하기() { System.out.println("JAVA 강의하기"); } }

4) App.java

C:\workspace\java_lab\designapp\src\ex05\App.java
package ex05; import ex05.teacher.JavaTeacher; import ex05.teacher.Teacher; public class App { public static void main(String[] args) { Teacher tt = new JavaTeacher(); tt.수업하기(); } }

5) 결과

notion image
Share article