jblog
Factory Method 패턴
ArchitectureGuru 디자인 패턴 #1

Factory Method 패턴

객체 생성을 서브클래스에게 맡기는 Factory Method 패턴을 알아봅니다.

2026-01-237 min readdesign-pattern, creational, architecture

#왜 내가 직접 만들어야 해?

개발하다 보면 이런 코드를 꽤 자주 만나게 된다.

function createNotification(type: string) {
  if (type === "email") return new EmailNotification();
  if (type === "sms") return new SMSNotification();
  if (type === "push") return new PushNotification();
  // 새로운 타입이 추가될 때마다 여기를 수정해야 한다...
}

처음에는 괜찮다. 3개 정도면 충분히 관리할 수 있다.

그런데 Slack 알림이 추가되고, Discord 알림이 추가되고, 카카오톡 알림이 추가되면?

if-else 지옥

if-else 지옥이 시작된다. 그리고 이 함수를 쓰는 곳이 10군데라면? 10군데를 다 수정해야 한다.

이 문제를 해결하는 패턴이 바로 Factory Method다.

visible: false

Factory Method란?

객체를 생성하는 인터페이스를 정의하되, 어떤 클래스의 인스턴스를 만들지는 서브클래스가 결정하는 패턴

쉽게 말하면 식당과 같다.

손님(클라이언트)은 "파스타 주세요"라고만 하면 된다. 어떤 재료를 쓰고, 어떻게 조리하는지는 셰프(서브클래스)가 알아서 한다.

핵심은 "뭘 만들지는 니가 알아서 해" 라는 것이다.

visible: false

구조

Creator (abstract)
  └── createProduct(): Product    ← 서브클래스가 구현
  └── someOperation()             ← createProduct()를 사용

ConcreteCreatorA
  └── createProduct(): ConcreteProductA

ConcreteCreatorB
  └── createProduct(): ConcreteProductB

Creator는 "만들어라"라는 메서드만 정의하고, 실제로 뭘 만들지는 ConcreteCreator가 결정한다.

visible: false

코드로 보기

Before: 직접 생성

class NotificationService {
  send(type: string, message: string) {
    let notification;
 
    if (type === "email") {
      notification = new EmailNotification();
    } else if (type === "sms") {
      notification = new SMSNotification();
    } else if (type === "push") {
      notification = new PushNotification();
    }
    // 🔥 Slack 추가하려면? 또 else if...
 
    notification?.send(message);
  }
}

문제점이 뭘까?

  1. 새로운 알림 타입 추가 시 기존 코드를 수정해야 한다 (OCP 위반)
  2. NotificationService모든 알림 타입을 알고 있어야 한다
  3. 이 로직이 여러 곳에 퍼져있다면? 전부 수정해야 한다

After: Factory Method 적용

// 1. Product 인터페이스
interface Notification {
  send(message: string): void;
}
 
// 2. Concrete Products
class EmailNotification implements Notification {
  send(message: string) {
    console.log(`📧 이메일 발송: ${message}`);
  }
}
 
class SMSNotification implements Notification {
  send(message: string) {
    console.log(`📱 SMS 발송: ${message}`);
  }
}
 
// 3. Creator (추상 클래스)
abstract class NotificationCreator {
  // Factory Method — 서브클래스가 구현한다
  abstract createNotification(): Notification;
 
  // 비즈니스 로직 — Factory Method를 사용한다
  notify(message: string) {
    const notification = this.createNotification();
    console.log("알림을 준비합니다...");
    notification.send(message);
    console.log("알림 발송 완료!");
  }
}
 
// 4. Concrete Creators
class EmailNotificationCreator extends NotificationCreator {
  createNotification(): Notification {
    return new EmailNotification();
  }
}
 
class SMSNotificationCreator extends NotificationCreator {
  createNotification(): Notification {
    return new SMSNotification();
  }
}

이제 Slack 알림을 추가하고 싶다면?

// 기존 코드 수정 없이, 새로운 클래스만 추가하면 된다!
class SlackNotification implements Notification {
  send(message: string) {
    console.log(`💬 Slack 발송: ${message}`);
  }
}
 
class SlackNotificationCreator extends NotificationCreator {
  createNotification(): Notification {
    return new SlackNotification();
  }
}

기존 코드를 한 줄도 건드리지 않았다. 이것이 Factory Method의 힘이다.

nice

visible: false

사용하는 쪽 코드

// 클라이언트 코드
function sendAlert(creator: NotificationCreator, message: string) {
  creator.notify(message);
}
 
// 어떤 알림을 보낼지는 여기서 결정
sendAlert(new EmailNotificationCreator(), "서버가 다운되었습니다!");
sendAlert(new SlackNotificationCreator(), "배포가 완료되었습니다!");

클라이언트 코드(sendAlert)는 NotificationCreator라는 추상 타입만 알고 있다.

이메일인지, Slack인지, SMS인지 전혀 몰라도 된다.

visible: false

언제 사용하면 좋을까?

  1. 생성할 객체의 타입을 미리 알 수 없을 때

    • 런타임에 어떤 객체를 생성해야 할지 결정되는 경우
  2. 라이브러리나 프레임워크를 만들 때

    • 사용자가 내부 컴포넌트를 확장할 수 있도록 하고 싶을 때
  3. 기존 객체를 재사용하고 싶을 때

    • Factory Method 안에서 매번 새로 만들지 않고 풀에서 꺼내올 수도 있다

실무에서 흔히 보는 예시

  • React의 createElement() — 태그 이름에 따라 다른 Element를 생성
  • Express의 미들웨어 — 요청 타입에 따라 다른 핸들러를 생성
  • DB 커넥션 — MySQL, PostgreSQL 등 드라이버에 따라 다른 커넥션 객체 생성

visible: false

장단점

장점단점
OCP 준수 — 새로운 타입 추가 시 기존 코드 수정 없음클래스가 많아질 수 있음
SRP 준수 — 객체 생성 로직을 한 곳에서 관리간단한 경우 오버엔지니어링이 될 수 있음
클라이언트와 구체 클래스의 결합도를 낮춤상속 구조가 깊어질 수 있음

visible: false

정리하며

Factory Method는 "객체 생성"이라는 행위를 추상화하는 패턴이다.

핵심을 한 줄로 요약하면,

"new를 직접 호출하지 말고, 만드는 방법을 아는 녀석한테 시켜라"

사실 패턴의 이름이 거창해서 어렵게 느껴지지만, 본질은 단순하다.

if-else로 객체를 생성하는 코드가 여기저기 퍼져있다면, Factory Method를 고려해보자.

다음 글에서는 Factory Method를 한 단계 더 확장한 Abstract Factory 패턴을 알아보겠다.

visible: false

#Reference

Refactoring Guru - Factory Method

refactoring.guru

댓글

댓글을 불러오는 중...