| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 |
- 인덱스
- docker
- PHP객체지향
- 매직메서드
- dhgrp
- Laravel
- OOP
- Agent Loop
- mcp client
- SQL문법
- linux 권한
- 라라벨
- 데이터베이스
- ai agent
- docker network
- 데코레이터패턴
- 객체복제
- SQL기초
- 객체지향
- LLM
- SQL
- 디자인패턴
- 소프트웨어설계
- MySQL
- Tool Calling
- ai 에이전트
- PHP
- MCP
- mcp server
- 어댑터패턴
- Today
- Total
개발블로그
[디자인패턴] 팩토리 패턴 본문
개념
필요성
프로그램을 만들다 보면 객체를 생성하는 조건이 복잡해지는 경우가 있음.
ex) 결제 방식에 따라 서로 다른 결제 객체를 만들어야 함
if payment_type == "card":
payment = CardPayment()
elif payment_type == "kakao":
payment = KakaoPayPayment()
elif payment_type == "point":
payment = PointPayment()
처음에는 이 정도 조건문도 크게 문제되지 않음.
하지만 결제 방식이 계속 추가되거나, 객체 생성에 필요한 설정이 많아지면 생성 코드가 점점 복잡해짐
, 문제는 이런 생성 코드가 여러 곳에 흩어질 수 있다.
=> 새로운 결제 방식이 추가될 때 여러 코드를 함께 수정해야 함.
팩토리 패턴은 이런 상황에서 사용 할 수 잇음
" 객체를 사용하는 코드가 객체 생성 조건까지 모두 알아야 할까? "
=> 객체를 생성하는 책임을 별도의 객체나 메서드로 분리해서, 사용하는 쪽이 생성 과정을 직접 알지 않아도 되게 만드는 패턴
의미
객체 생성 책임을 별도의 역할로 분리하는 패턴
=> 객체를 사용하는 코드는 어떤 객체가 필요한지만 요청하고, 실제로 어떤 클래스를 생성할지는 팩토리가 결정
즉, 객체 생성 책임을 한 곳으로 모아, 사용하는 코드가 생성 과정에 덜 의존하게 만드는 것.
사용하는 코드 - 객체를 요청하고 사용
팩토리 - 조건에 맞는 객체를 생성
생성되는 객체 - 실제 기능을 수행
ex)
# 주문 서비스는 결제 객체를 직접 만들지 않고, 팩토리에게 요청할 수 있음
payment = PaymentFactory.create(payment_type)
payment.pay(10000)
# 주문 서비스가 CardPayment, KakaoPayPayment, PointPayment를 직접 생성하지 않는다.
# 어떤 결제 객체를 만들지는 PaymentFactory가 담당
핵심 구조
| 구성 요소 | 역할 | 예시 |
| Product | 생성될 객체의 공통 형태 | 결제 수단 |
| Concrete Product | 실제로 생성되는 구체 객체 | 카드 결제, 카카오페이 결제, 포인트 결제 |
| Factory | 객체 생성 책임을 담당 | 결제 팩토리 |
적합
- 객체 생성 조건이 여러개이다
- 객체 생성 코드가 여러 곳에 반복된다
- 생성 과정이 복잡하거나 자주 바뀐다
- 사용하는 코드가 구체 클래스를 직접 알지 않게 만들고 싶다.
예시
EX]
결제 방식에 따라 다른 결제 객체를 만들어야 할 때
처음에는 필요한 곳에서 직접 객체를 생성할 수 있음
def order(payment_type, amount):
if payment_type == "card":
payment = CardPayment()
elif payment_type == "kakao":
payment = KakaoPayPayment()
elif payment_type == "point":
payment = PointPayment()
else:
raise ValueError("지원하지 않는 결제 방식입니다.")
return payment.pay(amount)
같은 생성 로직이 여러 곳에서 필요해지면 문제가 생김
def refund(payment_type, amount):
if payment_type == "card":
payment = CardPayment()
elif payment_type == "kakao":
payment = KakaoPayPayment()
elif payment_type == "point":
payment = PointPayment()
else:
raise ValueError("지원하지 않는 결제 방식입니다.")
return payment.refund(amount)
order()와 refund()는 목적이 다르지만, 결제 객체를 생성하는 조건문의 거의 같음.
여기에 새로운 결제 방식이 추가된다면
elif payment_type == "naver":
payment = NaverPayPayment()
이 코드를 order(), refund()처럼 결제 객체를 생성하는 모든 위치에 추가해야 함.
아래와 같은 문제들이 생긴다
| 문제 | 설명 |
| 중복 증가 | 같은 생성 조건문이 여러 함수에 반복된다. |
| 수정 범위 증가 | 결제 방식이 추가될 때 여러 위치를 수정해야 한다. |
| 누락 가능성 | 어떤 함수에는 새 결제 방식을 추가하지 않을 수 있다. |
| 책임 혼합 | 주문/환불 로직이 결제 객체 생성 조건까지 알고 있다. |
해결 : 팩토리로 생성 책임 분리하기
=>객체 생성 조건을 한곳으로 모으기
먼저 결제 객체들이 공통으로 제공할 동작을 정한다
class Payment:
def pay(self, amount):
pass
def refund(self, amount):
pass
이제 각 결제 방식을 구현함
class CardPayment(Payment):
def pay(self, amount):
return "카드 결제"
def refund(self, amount):
return "카드 환불"
class KakaoPayPayment(Payment):
def pay(self, amount):
return "카카오페이 결제"
def refund(self, amount):
return "카카오페이 환불"
class PointPayment(Payment):
def pay(self, amount):
return "포인트 결제"
def refund(self, amount):
return "포인트 환불"
그리고 객체 생성 책임을 PaymentFactory로 분리함
class PaymentFactory:
@staticmethod
def create(payment_type):
if payment_type == "card":
return CardPayment()
elif payment_type == "kakao":
return KakaoPayPayment()
elif payment_type == "point":
return PointPayment()
raise ValueError("지원하지 않는 결제 방식입니다.")
이제 주문 로직과 환불 로직은 직접 결제 객체를 생성하지 않는다
def order(payment_type, amount):
payment = PaymentFactory.create(payment_type)
return payment.pay(amount)
def refund(payment_type, amount):
payment = PaymentFactory.create(payment_type)
return payment.refund(amount)
이 구조에서는 결제 객체를 생성하는 조건이 PaymentFactory 안에 모임
새로운 결제 방식이 추가되면 팩토리와 새로운 결제 클래스만 추가하면 됨
class NaverPayPayment(Payment):
def pay(self, amount):
return "네이버페이 결제"
def refund(self, amount):
return "네이버페이 환불"
class PaymentFactory:
@staticmethod
def create(payment_type):
if payment_type == "card":
return CardPayment()
elif payment_type == "kakao":
return KakaoPayPayment()
elif payment_type == "point":
return PointPayment()
elif payment_type == "naver":
return NaverPayPayment()
raise ValueError("지원하지 않는 결제 방식입니다.")
order()와 refund()는 수정하지 않아도 됨.
| 구분 | 역할 |
| order(), refund() | 결제 객체를 사용한다. |
| PaymentFactory | 결제 객체를 생성한다. |
| CardPayment, KakaoPayPayment, PointPayment | 실제 결제/환불 동작을 수행한다. |
장점
장점
| 장점 | 설명 |
| 생성 책임 분리 | 객체를 사용하는 코드와 생성하는 코드를 분리할 수 있다. |
| 중복 감소 | 여러 곳에 반복되던 생성 조건문을 한곳으로 모을 수 있다. |
| 변경 범위 축소 | 생성 방식이 바뀌어도 사용하는 코드의 수정을 줄일 수 있다. |
| 구체 클래스 의존 감소 | 사용하는 코드가 특정 클래스 생성 방식에 덜 의존하게 된다. |
| 생성 과정 캡슐화 | 객체 생성에 필요한 복잡한 설정이나 조건을 팩토리 안에 숨길 수 있다. |
효과적인 상황
| 상황 | 이유 |
| 생성 조건이 여러 개인 경우 | 조건을 팩토리 안에서 관리할 수 있다. |
| 같은 생성 로직이 여러 곳에 반복되는 경우 | 중복된 생성 코드를 줄일 수 있다. |
| 객체 생성 과정이 복잡한 경우 | 필요한 설정, 초기화, 의존성 연결을 팩토리 안에 모을 수 있다. |
| 사용하는 코드가 구체 클래스를 몰라도 되는 경우 | 공통 인터페이스나 역할에 의존하도록 만들 수 있다. |
주의점
단순히 클래스 하나를 생성하는 코드라면 팩토리를 만드는 것이 오히려 불필요할 구조가 될 수 있음.
| 질문 | 의미 |
| 객체 생성 조건이 여러 개인가? | 팩토리로 분리할 이유가 있는지 확인한다. |
| 같은 생성 코드가 여러 곳에 반복되는가? | 중복 제거 효과가 있는지 확인한다. |
| 생성 과정이 복잡한가? | 초기화, 설정, 의존성 연결을 숨길 필요가 있는지 본다. |
| 사용하는 코드가 구체 클래스를 몰라도 되는가? | 생성 책임을 분리했을 때 의존성이 줄어드는지 확인한다. |
| 팩토리가 너무 많은 조건을 떠안고 있지는 않은가? | 팩토리 자체가 복잡해지는지 점검한다. |
'STUDY > CS' 카테고리의 다른 글
| [디자인패턴] 어댑터 패턴 (0) | 2026.09.04 |
|---|---|
| [디자인패턴] 옵저버 패턴 (0) | 2026.09.04 |
| [디자인 패턴] 전략패턴 (0) | 2026.09.04 |
| [디자인 패턴] 디자인 패턴이란? 반복되는 설계 문제를 해결하는 방법 (0) | 2026.09.03 |
| [객체지향] SOLID 원칙 : 좋은 객체지향 설계를 판단하는 5가지 기준 (0) | 2026.09.03 |