Creational

생성 패턴은 객체 생성 방식을 다양한 방법으로 추상화하여, 시스템의 유연성과 확장성을 높이는 디자인 패턴이다.
이러한 패턴은 객체 생성 로직을 별도의 클래스로 분리하거나, 객체 생성을 위한 인터페이스를 제공함으로써, 코드의 결합도를 낮추고, 유지보수성과 테스트 용이성을 향상시킨다.
대표적인 생성 패턴으로는 싱글톤 (Singleton), 팩토리 메서드 (Factory Method), 추상 팩토리 (Abstract Factory), 빌더 (Builder), 프로토타입 (Prototype) 등이 있다. Factory Method는 서브클래스에 생성 책임을 위임하고, Abstract Factory는 관련 객체군을 생성하며, Builder는 복잡 객체를 단계적으로 구성하고, Prototype은 복제 방식을 제공하며, Singleton은 전역 인스턴스를 보장한다.

배경 및 필요성

목적 및 필요성

핵심 개념

생성 디자인 패턴은 객체 생성 로직을 분리하여, 코드의 유연성, 재사용성, 유지보수성을 향상시키는 설계 패턴이다. 이를 통해 객체 생성 과정을 캡슐화하고, 복잡한 생성 로직을 감추며, 다양한 객체 생성 요구를 효율적으로 처리한다.

기본 개념

심화 개념

실무 구현 연관성

패턴적용 상황효과
Factory Method로그, 메시지 처리 등 특정 구현 객체가 런타임 결정런타임 유연성 증가
Abstract FactoryUI 테마 세트, DB 드라이버 플랫폼 대응 등제품군 일관성 유지
Builder복잡 객체 생성 (예: HTTP 클라이언트, 파일 포맷)가독성↑, 생성 옵션 구조화
Prototype비용이 큰 객체 복제 시 (예: 게임 엔티티 복제)복제 간편, 런타임 구성 가능
Singleton전역 설정, 로깅, 캐시, DB 연결 등전역 접근성, 자원 절약 효과

주요 기능 및 역할

특징

핵심 특징:

기술적 특징:

핵심 원칙

  1. 프로그래밍은 인터페이스에 대해, 구현에 대해서가 아니다
  2. 상속보다 객체 합성을 선호하라
  3. 변화하는 것을 캡슐화하라
  4. 느슨한 결합 (Loose Coupling) 추구

생성 패턴의 종류 및 비교

패턴핵심 개념주요 특징·장점사용 시점 / 목적실무 예시
Singleton애플리케이션 전체에서 오직 하나의 인스턴스만 존재하도록 보장하고, 전역 접근 지점 제공• 전역 상태 공유
• Lazy Initialization 및 Thread-safe 구현 가능
• 인스턴스 관리 일원화
• 설정, 로그, 캐시 등 하나만 있으면 되는 자원 관리
• DB 연결·커넥션 풀처럼 동시에 여러 곳에서 동일 자원을 요청할 때
데이터베이스 커넥션 풀 관리 객체를 단일 인스턴스로 노출해 다중 스레드가 공유하도록 구성
Factory Method상위 클래스에 생성 인터페이스를 정의하고, 실제 객체 생성은 하위 클래스가 결정• 생성 로직을 서브클래스에 위임 → OCP 충실
• 클라이언트 - 코드와 구체 클래스 간 결합 최소화
• OS·플랫폼별로 다른 구현체가 필요한 UI 위젯, 로거 등
• 라이브러리에서 확장 포인트 제공하고 싶을 때
운영체제마다 서로 다른 Button 을 반환하도록 하는 크로스 - 플랫폼 GUI 툴킷
Abstract Factory연관된 객체군(제품 패밀리) 을 일관성 있게 생성하는 상위 인터페이스 제공• 제품군 간 호환성·일관성 보장
• 클라이언트는 구체 공장·제품 클래스 알 필요 없음
• 테마·브랜드·OS 에 따라 버튼 + 체크박스 + 메뉴 등을 세트로 바꿔야 할 때
• 제품군 교체를 런타임 설정으로 전환하려 할 때
라이트/다크 테마 UI 컴포넌트를 한 번에 교체하는 테마 엔진
Builder복잡한 객체를 단계별로 조립하고, 동일 공정으로 서로 다른 표현을 생성• 가독성 높은 단계별 API(플루언트 인터페이스)
• 파라미터 폭발·불변 객체 문제 해결
• Director 를 통해 생성 절차 재사용
• 필드가 많은 DTO, JSON, HTML, 그래프 등 복합 구조 생성
• 선택적·반복적 구성 요소가 많은 경우
메서드 체인을 이용해 SELECT·WHERE·ORDER BY 를 조립하는 SQL Query Builder
Prototype기존 객체를 복제 (clone) 하여 새로운 객체 생성• 객체 생성 비용·복잡도↓
• 런타임에 타입 몰라도 복제 가능
• 깊은/얕은 복제 전략 선택
• 데이터 - 집약적 초기화가 큰 비용을 차지할 때
• 동적 로딩 플러그인에서 새로운 인스턴스 필요할 때
게임에서 몬스터 템플릿을 미리 생성해 스폰 시마다 복제하여 성능 최적화

비교 분석이 반드시 필요한 패턴 조합

Factory Method vs. Abstract Factory

항목Factory Method 패턴Abstract Factory 패턴
패턴 목적객체 생성을 하위 클래스에게 위임관련된 객체군 (Family of Products) 을 일관되게 생성
생성 단위단일 객체제품군 (예: 버튼 + 체크박스 같이 관련된 UI 컴포넌트)
확장성새로운 제품 추가 시 서브클래스 확장제품군 확장은 어렵고 전체 팩토리를 교체해야 함
클라이언트 추상화 수준객체 생성 방법을 캡슐화 (단일 create 메서드)제품군 단위로 캡슐화된 여러 개의 create 메서드 제공
사용 예시다양한 버튼 타입 생성 시 (MacButton, WindowsButton 등)GUI 툴킷처럼 일관된 UI 구성 요소를 생성할 때 (버튼 + 체크박스 등)
관계성객체 간 관계 없음관련 객체들을 함께 생성 (일관된 인터페이스 제공 목적)
패턴 복잡도상대적으로 단순구조가 복잡하고 팩토리 클래스가 여러 개 필요
대표 인터페이스Creator.createProduct()Factory.createButton(), Factory.createCheckbox()
주요 구현 방식Creator 클래스를 상속하여 구현인터페이스 기반의 팩토리 + 제품 인터페이스 집합 구성
Factory Method 예시
 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
31
32
33
34
35
36
37
38
39
# 제품 인터페이스
class Button:
    def render(self):
        pass

# 구체적인 제품
class WindowsButton(Button):
    def render(self):
        return "Rendering Windows Button"

class MacButton(Button):
    def render(self):
        return "Rendering Mac Button"

# Creator 추상 클래스 (Factory Method 정의)
class Dialog:
    def create_button(self) -> Button:
        pass

    def render_window(self):
        button = self.create_button()
        print(button.render())

# 구체 Creator: Windows
class WindowsDialog(Dialog):
    def create_button(self) -> Button:
        return WindowsButton()

# 구체 Creator: Mac
class MacDialog(Dialog):
    def create_button(self) -> Button:
        return MacButton()

# 클라이언트 코드
def client_code(dialog: Dialog):
    dialog.render_window()

client_code(WindowsDialog())  # Rendering Windows Button
client_code(MacDialog())      # Rendering Mac Button

핵심 포인트: Factory Method 는 하나의 객체 (Button) 생성 책임만 하위 클래스에 위임

Abstract Factory 예시
 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# 제품 인터페이스들
class Button:
    def render(self):
        pass

class Checkbox:
    def check(self):
        pass

# 제품군: Windows
class WindowsButton(Button):
    def render(self):
        return "Rendering Windows Button"

class WindowsCheckbox(Checkbox):
    def check(self):
        return "Checking Windows Checkbox"

# 제품군: Mac
class MacButton(Button):
    def render(self):
        return "Rendering Mac Button"

class MacCheckbox(Checkbox):
    def check(self):
        return "Checking Mac Checkbox"

# 추상 팩토리
class GUIFactory:
    def create_button(self) -> Button:
        pass

    def create_checkbox(self) -> Checkbox:
        pass

# 구체 팩토리: Windows
class WindowsFactory(GUIFactory):
    def create_button(self):
        return WindowsButton()

    def create_checkbox(self):
        return WindowsCheckbox()

# 구체 팩토리: Mac
class MacFactory(GUIFactory):
    def create_button(self):
        return MacButton()

    def create_checkbox(self):
        return MacCheckbox()

# 클라이언트 코드
def client_code(factory: GUIFactory):
    button = factory.create_button()
    checkbox = factory.create_checkbox()
    print(button.render())
    print(checkbox.check())

client_code(WindowsFactory())
client_code(MacFactory())

핵심 포인트: Abstract Factory 는 **관련된 객체군 (Button + Checkbox)**을 함께 생성하여 일관성 유지.

Factory Method vs. Builder

항목Factory Method 패턴Builder 패턴
패턴 목적객체 생성의 책임을 서브클래스에 위임객체 생성 절차 (단계) 를 캡슐화하여 유연하게 구성
생성 대상단일 객체 생성복합 객체 조립 (구성 요소 다양)
생성의 결정 시점어떤 객체를 만들지 결정 (종류 선택)어떻게 구성할지 결정 (속성 조합 및 조립)
적용 상황다양한 타입 중에서 객체 선택이 필요할 때객체를 여러 단계로 구성하거나 다양한 표현이 필요한 경우
디렉터 사용 여부일반적으로 사용 안 함보통 Director 가 빌더 단계를 조립함
확장성제품을 추가하려면 서브클래스만 추가빌더와 디렉터만 조정하면 다양한 제품 구성 가능
장점클라이언트 코드에서 구체 클래스 제거 가능동일한 생성 절차로 다양한 객체 생성 가능
예시 비유팩토리에서 " 어떤 모델을 주문할지 " 선택건축가가 집을 지을 때, 벽, 지붕, 창문을 단계별로 조립
결과 객체의 복잡도일반적으로 단순 (1 개 인스턴스)일반적으로 복잡 (구성 요소 포함된 객체)
Factory Method 패턴 예시

" 무엇을 만들 것인가?" 를 하위 클래스에 위임 (객체의 종류 선택)

 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
31
32
33
34
35
36
37
38
# 제품 인터페이스
class Notification:
    def send(self, message: str):
        pass

# 구체 제품
class EmailNotification(Notification):
    def send(self, message: str):
        print(f"📧 Email sent: {message}")

class SMSNotification(Notification):
    def send(self, message: str):
        print(f"📱 SMS sent: {message}")

# Creator 추상 클래스
class NotificationCreator:
    def create_notification(self) -> Notification:
        pass

    def notify(self, message: str):
        notification = self.create_notification()
        notification.send(message)

# 구체 Creator들
class EmailNotificationCreator(NotificationCreator):
    def create_notification(self) -> Notification:
        return EmailNotification()

class SMSNotificationCreator(NotificationCreator):
    def create_notification(self) -> Notification:
        return SMSNotification()

# 클라이언트
def client_code(creator: NotificationCreator):
    creator.notify("Hello, this is a Factory Method test.")

client_code(EmailNotificationCreator())  # Email sent
client_code(SMSNotificationCreator())    # SMS sent

핵심: 어떤 객체를 만들지는 create_notification() 을 통해 서브클래스에서 결정됨

Builder 패턴 예시

" 어떻게 만들 것인가?" 를 단계적으로 캡슐화 (복합 객체 조립)

 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 복합 객체
class Car:
    def __init__(self):
        self.engine = None
        self.wheels = None
        self.color = None

    def specs(self):
        return f"🚗 Car with {self.engine} engine, {self.wheels} wheels, and {self.color} color."

# Builder 인터페이스
class CarBuilder:
    def set_engine(self): pass
    def set_wheels(self): pass
    def set_color(self): pass
    def get_result(self): pass

# 구체 Builder
class SportsCarBuilder(CarBuilder):
    def __init__(self):
        self.car = Car()

    def set_engine(self):
        self.car.engine = "V8"

    def set_wheels(self):
        self.car.wheels = 4

    def set_color(self):
        self.car.color = "Red"

    def get_result(self):
        return self.car

# Director
class CarDirector:
    def __init__(self, builder: CarBuilder):
        self.builder = builder

    def construct(self):
        self.builder.set_engine()
        self.builder.set_wheels()
        self.builder.set_color()
        return self.builder.get_result()

# 클라이언트
builder = SportsCarBuilder()
director = CarDirector(builder)
car = director.construct()
print(car.specs())

핵심: 객체의 구성 방식 (엔진, 휠, 색상 등) 을 빌더가 단계적으로 설정하며 조립

Prototype Vs Builder

항목Prototype 패턴Builder 패턴
패턴 목적기존 객체를 복제하여 새로운 객체 생성객체를 단계적으로 구성하여 유연하게 생성
생성 방식clone() 메서드 기반 깊은 복사 / 얕은 복사Director 를 통해 Builder 단계를 순차적으로 호출
사용 상황동일한 설정을 가진 객체가 자주 반복적으로 필요할 때다양한 속성 조합이 가능한 복잡한 객체를 구성해야 할 때
객체 복잡도비교적 단순하거나 사전 정의된 구조복합 객체 (속성, 파트가 다양하고 구성 순서가 존재함)
유연성객체 구조는 고정, 값만 다름구조와 값 모두 유연하게 설정 가능
성능빠른 생성 (복제 기반)느리지만 유연함 (조립 기반)
대표 메서드.clone().set_xxx(), .build()
디렉터 존재 여부없음일반적으로 Director 가 단계 호출
대표 예시템플릿 문서, UI 컴포넌트, 몬스터 복제 등차량 생성, 사용자 설정 기반 보고서, 음식 주문 조립 등
Prototype 패턴 예시

" 복사 (Clone) 기반으로 객체 생성 “
설정된 객체를 기반으로 새로운 객체를 빠르게 복제

 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
import copy

# Prototype 인터페이스
class Document:
    def clone(self):
        pass

# 구체적인 Prototype
class Resume(Document):
    def __init__(self, name, education, experience):
        self.name = name
        self.education = education
        self.experience = experience

    def show(self):
        print(f"📄 Resume: {self.name}, {self.education}, {self.experience}")

    def clone(self):
        return copy.deepcopy(self)

# 클라이언트 코드
original = Resume("현윤", "서울대", "삼성전자")
original.show()

# 복제한 객체
copy1 = original.clone()
copy1.name = "지훈"
copy1.show()

핵심: 기존 객체를 clone() 메서드로 복사하여 빠르게 유사 객체 생성

Builder 패턴 예시

” 단계별로 복합 객체 조립 “
생성 절차를 분리하여 유연하게 다양한 구성으로 객체 생성 가능

 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 복합 객체
class Resume:
    def __init__(self):
        self.name = None
        self.education = None
        self.experience = None

    def show(self):
        print(f"📄 Resume: {self.name}, {self.education}, {self.experience}")

# Builder 인터페이스
class ResumeBuilder:
    def set_name(self, name): pass
    def set_education(self, education): pass
    def set_experience(self, experience): pass
    def build(self): pass

# 구체 Builder
class ConcreteResumeBuilder(ResumeBuilder):
    def __init__(self):
        self.resume = Resume()

    def set_name(self, name):
        self.resume.name = name

    def set_education(self, education):
        self.resume.education = education

    def set_experience(self, experience):
        self.resume.experience = experience

    def build(self):
        return self.resume

# Director
class ResumeDirector:
    def __init__(self, builder: ResumeBuilder):
        self.builder = builder

    def construct_resume(self, name, education, experience):
        self.builder.set_name(name)
        self.builder.set_education(education)
        self.builder.set_experience(experience)
        return self.builder.build()

# 클라이언트 코드
builder = ConcreteResumeBuilder()
director = ResumeDirector(builder)
resume = director.construct_resume("현윤", "KAIST", "NAVER")
resume.show()

핵심: 객체 생성 로직을 분리하고, 다양한 설정을 적용 가능하게 함

Prototype Vs Factory Method

항목Prototype PatternFactory Method Pattern
목적객체를 복제 (clone) 하여 생성객체 생성을 서브클래스에 위임
생성 방법clone() 호출로 기존 객체 복제create() 호출로 새 인스턴스 생성
사용 이유생성 비용이 크거나, 복잡한 설정의 객체를 빠르게 복제하고자 할 때객체 생성 로직을 확장 가능하게 만들고자 할 때
유연성런타임 시점에 객체의 상태를 유지한 채 복제 가능새로운 타입의 객체를 쉽게 추가 가능
패턴 구조 중심인스턴스를 복제하는 방식서브클래스화된 팩토리 메서드로 객체 생성 위임
장점복잡한 초기화를 피하고 성능 최적화 가능제품 계열을 유연하게 추가/변경 가능
단점깊은 복사 이슈, 상태 관리의 어려움서브클래스가 많아질 수 있음
적합한 상황캐싱, 템플릿, 초기화된 인스턴스 재사용 등다양한 파생 클래스가 필요한 경우 (예: UI 구성요소 생성)
예시문서 템플릿 시스템, 게임 캐릭터 복제UI 컴포넌트 생성기, 알림 팝업 팩토리 등
Prototype Pattern 예시
 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
import copy

# Prototype 인터페이스
class Shape:
    def clone(self):
        return copy.deepcopy(self)

# ConcretePrototype
class Circle(Shape):
    def __init__(self, radius, color):
        self.radius = radius
        self.color = color

    def __str__(self):
        return f"Circle(radius={self.radius}, color={self.color})"

# Client
def main_prototype():
    circle1 = Circle(10, "red")
    circle2 = circle1.clone()  # 객체 복제
    circle2.color = "blue"

    print("Prototype Pattern:")
    print(circle1)  # 원본
    print(circle2)  # 복제본
Factory Method Pattern 예시
 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
31
32
33
34
35
36
37
38
# Product 인터페이스
class Shape:
    def draw(self):
        pass

# Concrete Products
class Circle(Shape):
    def draw(self):
        return "Drawing a Circle"

class Square(Shape):
    def draw(self):
        return "Drawing a Square"

# Creator (Factory Method 정의)
class ShapeFactory:
    def create_shape(self):
        raise NotImplementedError

class CircleFactory(ShapeFactory):
    def create_shape(self):
        return Circle()

class SquareFactory(ShapeFactory):
    def create_shape(self):
        return Square()

# Client
def main_factory():
    factory1 = CircleFactory()
    shape1 = factory1.create_shape()

    factory2 = SquareFactory()
    shape2 = factory2.create_shape()

    print("\nFactory Method Pattern:")
    print(shape1.draw())
    print(shape2.draw())

Singleton vs. Factory/Abstract Factory

항목Singleton 패턴Factory Method 패턴Abstract Factory 패턴
주요 목적단 하나의 객체를 보장객체 생성 로직을 서브클래스로 캡슐화관련 객체군을 일관되게 생성
객체 생성 시점최초 호출 시 1 회만 생성 (지연 초기화 가능)호출할 때마다 객체 생성호출할 때마다 관련 객체 각각 생성
객체 수 제한항상 하나여러 개 가능여러 개 가능 (제품군 단위로)
주요 책임전역 접근 가능한 단일 인스턴스 보장객체 생성 방식 분리 (유연성 확보)제품군 단위 생성의 일관성 유지
사용 예로깅 시스템, DB 연결 풀다양한 타입의 Notification, Shape 생성GUI Toolkit(Button, Checkbox 등) 생성
의존성 주입 용이성낮음 (전역 접근 지향)중간 수준 (인터페이스를 통한 캡슐화)높음 (전체 제품군을 통째로 주입 가능)
코드 확장성낮음 (하나의 클래스 고정)중간 수준 (서브클래스 확장)높음 (새로운 제품군 팩토리만 추가)
패턴 구조 복잡도매우 단순중간비교적 복잡 (여러 인터페이스와 클래스 필요)
결과 객체의 다양성없음 (항상 동일 객체)존재 (서브클래스마다 다름)제품군 단위로 다양성 존재
Singleton 패턴 예시

” 단 하나의 인스턴스만 존재 " 하도록 보장하고, 어디서든 접근 가능하게 만듦

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Logger:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            print("🔧 Creating new Logger instance")
            cls._instance = super().__new__(cls)
        return cls._instance

    def log(self, message: str):
        print(f"LOG: {message}")

# 클라이언트
logger1 = Logger()
logger2 = Logger()

logger1.log("Singleton pattern test.")
print(f"logger1 is logger2? {logger1 is logger2}")  # True

핵심: 오직 하나의 Logger 객체만 생성되며, 재사용된다.

Factory Method 패턴 예시

" 객체 생성 책임을 하위 클래스에게 위임 “

 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
# 제품 인터페이스
class Notification:
    def send(self, message: str):
        pass

# 구체 제품
class EmailNotification(Notification):
    def send(self, message: str):
        print(f"📧 Email sent: {message}")

# Creator
class NotificationCreator:
    def create_notification(self) -> Notification:
        pass

    def notify(self, message: str):
        notification = self.create_notification()
        notification.send(message)

# 구체 Creator
class EmailNotificationCreator(NotificationCreator):
    def create_notification(self) -> Notification:
        return EmailNotification()

# 클라이언트
creator = EmailNotificationCreator()
creator.notify("Hello from Factory Method")

핵심: 어떤 객체를 만들지는 하위 클래스에서 결정되며, 객체는 필요할 때마다 생성

Abstract Factory 패턴 예시

” 관련된 객체군을 일관되게 생성하는 팩토리 객체 “

 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
31
# 제품 인터페이스
class Button:
    def render(self): pass

class Checkbox:
    def check(self): pass

# 구체 제품군: Windows
class WindowsButton(Button):
    def render(self): print("🪟 Rendering Windows Button")

class WindowsCheckbox(Checkbox):
    def check(self): print("🪟 Checking Windows Checkbox")

# 추상 팩토리
class GUIFactory:
    def create_button(self) -> Button: pass
    def create_checkbox(self) -> Checkbox: pass

# 구체 팩토리
class WindowsFactory(GUIFactory):
    def create_button(self): return WindowsButton()
    def create_checkbox(self): return WindowsCheckbox()

# 클라이언트
factory = WindowsFactory()
button = factory.create_button()
checkbox = factory.create_checkbox()

button.render()
checkbox.check()

핵심: 관련된 객체 (Button + Checkbox) 를 함께 생성하여 UI 구성 일관성 확보

장점

구분항목설명원인/특성
장점유연성객체 생성 방식을 동적으로 변경할 수 있음객체 생성 캡슐화
확장성새로운 객체 유형을 쉽게 추가할 수 있음객체 생성 책임 분리
책임 분리클라이언트 코드와 객체 생성 코드를 분리하여 복잡성 낮춤객체 생성 책임 분리
재사용성객체 생성 로직을 여러 곳에서 재사용 가능객체 생성 캡슐화

단점과 문제점 및 해결방안

단점

항목설명해결책
복잡성패턴 적용 시 시스템 복잡성 증가명확한 인터페이스, 문서화
러닝커브패턴 이해 및 적용에 학습 필요교육, 예제 제공

문제점

항목원인영향탐지/진단예방 방법해결 방법 및 기법
객체 생성 실패팩토리 생성 실패객체 사용 불가코드 리뷰팩토리 검증팩토리 생성 검증
싱글톤 오용불필요한 싱글톤 적용확장성 저하코드 리뷰필요시만 적용패턴 선택 재검토

도전 과제

카테고리핵심 도전 과제구체적 문제점대표 해결 전략·모범 사례
설계 · 선택패턴 선택의 복잡성• 상황별 적절 패턴 결정 난도
• 과도한 추상화로 코드 가독성 저하
• 요구사항·제약조건 매트릭스 작성 후 의사결정
• 프로토타입으로 타당성 검증 (PoC)
• " 패턴 카탈로그 " 와 체크리스트로 오남용 방지
언어 · 플랫폼언어적 한계·Reflection 의존• 생성자 오버로드 부족
• 리플렉션·프록시 남용 시 성능·보안 저하
• - 변형 Factory(등록 맵·람다 팩토리) 로 동적 타입 해결
• 메타프로그래밍 대신 코드 생성 (Annotation Processor, Codegen) 활용
동시성 · 안정성싱글턴 스레드 안전• 초기화 경합·데드락·중복 생성• Double-Checked Locking(volatile)·정적 Holder
• JVM 이니셜라이저·enum 싱글턴
• DI 컨테이너 Scope 활용
테스트 · 운영테스트용 교체 (스왑) 곤란• 생산 코드와 결합 강해 Mock/Stub 주입 어려움• 팩토리 주입 (Strategy 패턴)·Service Locator 추상화
• Provider 인터페이스 + DI 컨테이너로 런타임 스왑
최신 기술 환경클라우드·서버리스·MSA 적용• 인스턴스 생성 주기·스케일 아웃으로 싱글턴 의미 희석
• 무상태 함수형 플랫폼과 충돌
• 컨테이너 당 싱글턴 → Stateless Factory 로 전환
• 외부 스테이트 (예: Config Server, Redis) 활용
성능 최적화생성 오버헤드·메모리• 빈번한 객체 생성으로 GC 부하
• 대형 객체 초기화 비용 증가
• 객체 풀링·Flyweight
• Lazy Initialization·캐싱 전략
• Builder 단계별 스트림 처리로 중간 객체 감소
메모리 관리객체 수명 · 누수 통제• 길게 참조된 객체로 메모리 누수• 약참조 (Weak/Soft Reference)·Scope 관리
• Prototype + Pooling 혼합으로 수명 제어

실무 사용 예시

도메인/시스템사용 패턴적용 목적구체적 사례 (라이브러리·기술)주요 효과
인프라‧설정 관리Singleton전역 상태·자원 (로그·설정 등) 단일 인스턴스 공유Log4j Logger, 환경 ConfigurationManager인스턴스 일관성, 동시성 안전, 자원 관리 효율
데이터베이스 접근 계층Abstract FactoryURL·드라이버 종류별 커넥션 객체군 생성JDBC DriverManager → 특정 Driver 선택DB 종속성 최소화, 멀티 - 벤더 확장성
웹 프레임워크Factory Method요청 경로·HTTP 메서드에 따른 처리기 동적 생성Spring MVC HandlerMapping(factory method 로 매핑 객체 반환)모듈화, OCP 준수, 테스트 용이성
UI 테마 시스템Abstract Factory버튼·체크박스 등 위젯 세트를 통일된 L&F 로 생성Swing / WPF Look-and-Feel FactoryUI 일관성, 테마 교체 유연성
HTTP 클라이언트Builder헤더·쿼리·타임아웃 등 옵션 체인 방식으로 요청 구성OkHttp Request.Builder, Retrofit Retrofit.Builder가독성, 선택적 파라미터 관리, 불변 객체 유지
게임 개발Prototype캐릭터·아이템 템플릿을 빠르게 복제해 인스턴스화Unity ScriptableObject 기반 오브젝트 복제생성 비용 절감, 런타임 성능 향상

활용 사례

사례 1: 전자상거래 플랫폼

시나리오: 대규모 온라인 쇼핑몰 시스템에서 다양한 결제 방식과 배송 옵션을 지원하는 주문 처리 시스템

시스템 구성:

1
2
3
4
5
6
7
[주문 관리자] ─── [결제 처리 팩토리] ─── [신용카드 처리기]
     │                 │                    │
     │                 └─── [페이팔 처리기]   │
     │                                      │
     └─── [배송 서비스 팩토리] ─── [일반 배송]    │
                 │                         │
                 └─── [익일 배송] ──────────┘

활용된 패턴들:

  1. Abstract Factory: 결제 처리와 배송 서비스의 패밀리 생성
  2. Builder: 복잡한 주문 정보 구성
  3. Singleton: 전역 설정 관리자

Workflow:

  1. 고객이 주문 생성 요청
  2. 주문 빌더가 단계별로 주문 정보 구성
  3. Abstract Factory 가 결제 방식에 따른 처리기 생성
  4. Singleton 설정 관리자에서 배송 정책 조회
  5. 구성된 주문 객체 반환

담당 역할:

사례 2: HTTP 클라이언트 구성

문제: GET, POST, 헤더, 쿼리 스트링 등 다양한 옵션의 조합이 필요하기 때문에 Builder 패턴을 사용

적용:

시스템 구성 다이어그램:

sequenceDiagram
    participant Client
    participant Builder
    participant Product

    Client->>Builder: new Builder()
    Client->>Builder: setUrl(), setHeader(), setBody()
    Client->>Builder: build()
    Builder-->>Product: complete Request 객체

Builder 사용 여부 효과 비교*:

사례 3: 객체 생성 로직 캡슐화

Factory 패턴 적용 사례

시스템 구성:

Workflow:

  1. Client 가 Factory 에 객체 생성 요청
  2. Factory 가 Product 생성
  3. Client 가 Product 사용

역할:

차이점:

구현 예시:

 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
# Factory 패턴 예시
class Product:
    def operation(self):
        pass

class ConcreteProductA(Product):
    def operation(self):
        print("ConcreteProductA operation")

class ConcreteProductB(Product):
    def operation(self):
        print("ConcreteProductB operation")

class Factory:
    def create_product(self, type_):
        if type_ == "A":
            return ConcreteProductA()
        elif type_ == "B":
            return ConcreteProductB()
        else:
            raise ValueError("Unknown type")

# 사용 예시
factory = Factory()
product = factory.create_product("A")
product.operation()  # 출력: ConcreteProductA operation

실무 적용 고려사항

카테고리고려 항목설명권장 사항주의할 점
설계패턴 선택 기준문제 유형과 복잡도에 맞는 패턴 선정 필요요구사항 분석 후 적절한 패턴만 사용단순 객체 생성에 과도한 패턴 적용 금지
추상화 수준 조절고차 추상화는 유지보수와 협업 난이도 증가 가능필요 최소한의 추상화, 구조 명확화과도한 추상화로 인한 코드 난독화
구현인터페이스 명확화팩토리·빌더 등 생성자 인터페이스는 명확하고 단순해야 함기능별 인터페이스 분리, 메서드 체이닝 및 alias 제공의미 불분명한 메서드 및 중복 로직
구조적 분리생성 관련 클래스의 위치·의존성 정리 필요패키지/모듈 분리, 네이밍 표준화생성자 클래스와 도메인 로직 혼합 금지
테스트테스트 용이성 확보전역 객체나 고정 인스턴스는 테스트를 어렵게 만듦DI 기반 설계, 팩토리 추상화, Mock 객체 구성Singleton 남용 시 테스트 격리 어려움
객체 조합 테스트다양한 생성 경로와 조합에 대한 테스트 필요단위/통합 테스트 강화, 테스트 케이스 자동화테스트 커버리지 부족으로 인한 오류 누락
성능객체 생성 비용 고려무거운 객체는 필요 시점에 생성 또는 재사용Lazy Initialization, 객체 풀링, 캐싱 전략 적용불필요한 사전 초기화로 인한 메모리 낭비
메모리 관리객체 생명주기 명확히 해야 누수 방지 가능약참조 활용, 불필요 객체 해제, GC 유도 고려참조 지속으로 인한 GC 회수 실패
유지보수구조 변경 영향도 최소화생성 로직 변경 시 시스템 전체에 영향 미치지 않도록 분리 구성생성 책임 모듈화, OCP 원칙 적용코드 변경 시 ripple effect 발생 가능
문서화 및 공유패턴 사용 이유와 구조는 명확히 공유되어야 협업 가능UML, README, 주석 등으로 생성 흐름 및 책임 명시과도한 문서화로 실시간 유지 어려움

최적화하기 위한 고려사항 및 주의할 점

카테고리항목설명권장사항주의점
메모리 최적화객체 풀링자주 생성되는 객체를 재사용하여 메모리 할당 감소Object Pool, Reuse 전략 적용메모리 누수, 동기화 필요
객체 생성 캐싱동일 객체 중복 생성을 방지하여 메모리 사용량 절감객체 Cache 또는 Flyweight 패턴 적용캐시 갱신 정책, 불일치 이슈
메모리 프로파일링생성 및 유지 객체 수 모니터링을 통해 최적화 포인트 도출실제 운영 환경에서 메모리 사용 모니터링프로파일링 자체의 오버헤드
성능 최적화지연 초기화실제로 필요한 시점에 객체 생성하여 불필요한 리소스 낭비 방지Lazy Initialization첫 사용 시점 지연 발생 가능
팩토리 호출 오버헤드단순 객체 생성에 복잡한 팩토리 사용은 오히려 성능 저하직접 생성 또는 경량 팩토리 도입 고려과도한 추상화 또는 Factory 오용
복제 비용 관리프로토타입 패턴 사용 시 깊은 복제는 성능 이슈 유발 가능얕은 복제 (Shallow Copy) 또는 복제 전략 분리깊은 복제 시 자원 낭비 가능
동시성 및 안정성스레드 안전성멀티스레드 환경에서 객체 공유 시 적절한 동기화 필요synchronized, volatile, Concurrent 구조 사용과도한 동기화로 인한 병목
싱글턴 동기화 전략동시 초기화 시 race condition 방지 필요enum Singleton, static inner class, DCL(Double-Checked Locking)잘못된 동기화는 예외나 중복 인스턴스 초래
생성 전략 관리생성 비용 고려고비용 객체는 매번 새로 생성하지 않도록 주의Pool, Prototype 전략, Factory 패턴 활용재사용보다 단순 생성이 더 나은 경우 고려
불필요한 추상화 제거단순 객체 생성에 불필요한 추상화 계층 도입 시 성능 오히려 저하설계 간결화, 간단한 경우 직접 생성 사용유지보수보다 성능이 중요한 경우만 적용
객체 생명주기 관리빌더 객체 재사용Builder 매번 새로 생성하면 GC 부하 증가 가능재사용 가능한 Builder 설계재사용 시 내부 상태 초기화 주의
생성/삭제 시점 최적화객체를 언제 만들고 제거할 것인지 전략적으로 관리 필요지연 생성, 비동기 제거, 참조 관리객체 누수, 참조 카운팅 실패 등

주제와 관련하여 주목할 내용

카테고리주제핵심 항목설명
기술 트렌드클라우드/서버리스객체 수명 관리, Stateless 생성클라우드 환경에서 Singleton, Pool, Lazy Init 등의 생성 전략 재정의 필요
웹어셈블리 (WASM)경량 객체 팩토리WASM 모듈 내 객체 생성 비용을 줄이기 위한 팩토리 최적화
GraphQL 런타임 처리동적 스키마 생성 팩토리GraphQL 스키마를 런타임에 조립하는 동적 팩토리 전략 활용
함수형 프로그래밍불변 객체 생성Immutable 객체 생성을 위한 Builder 변형 활용
아키텍처 접근도메인 주도 설계 (DDD)애그리게이트 팩토리복잡한 도메인 객체 (애그리게이트 루트) 생성을 전담하는 팩토리 적용
이벤트 소싱이벤트 기반 빌더이벤트 로그로부터 객체 상태를 단계적으로 재구성 (Rehydration)
디자인 패턴 결합복합 설계 전략Builder + Prototype, Abstract Factory + Singleton 등 패턴 조합 사용 증가
코드 품질 · 생산성테스트 자동화Mock 객체 생성생성 책임을 분리함으로써 테스트 시 의존성 주입과 Mock 구성 용이
유지보수성객체 생성 책임 분리생성 로직 모듈화를 통해 변경 시 영향도 축소 및 재사용성 증가
조직 운영·교육팀 협업패턴 교육·표준화 필요생성 패턴 적용은 팀 내 공통 이해와 적용 방식 일관화가 중요
코드 품질 문화생성 패턴 도입 효과적절한 생성 패턴은 구조적 품질 향상, 확장성·유지보수성 향상 유도

하위 주제로 분류한 추가 학습 항목

카테고리주제간략한 설명
GoF 디자인 패턴생성 패턴 5 종Singleton, Factory Method, Abstract Factory, Builder, Prototype 등
생성 패턴과의 비교구조 패턴 vs. 생성 패턴구조 패턴은 클래스/객체의 구성, 생성 패턴은 객체 생성 책임을 다룸
객체지향 설계 원칙DIP, OCP, SRP생성 패턴은 의존 역전 원칙 (DIP) 및 개방 폐쇄 원칙 (OCP) 과 긴밀히 연관됨
실전 구현 전략DI 컨테이너와의 연계Spring, NestJS 등 프레임워크에서 생성 패턴을 어떻게 적용하고 자동화하는지 분석
객체 생명주기 관리Scope, LifecycleSingleton, Request, Session 등 다양한 생명주기를 갖는 객체 생성 관리 전략
테스트 전략객체 모킹 및 스텁생성 패턴을 통해 테스트 대역 (Mock, Stub) 객체를 쉽게 주입 가능

관련 분야 포함 추가 학습 필요 항목

카테고리주제설명
🧩 핵심 이론생성 패턴 5 종Singleton, Factory Method, Abstract Factory, Builder, Prototype 등 주요 생성 패턴 학습
생성 패턴 vs 구조 패턴구조 패턴은 객체 구성, 생성 패턴은 객체 생성 책임과 관련됨
객체 생성 로직의 캡슐화생성 로직을 분리해 코드 유지보수성과 유연성을 향상
SOLID 원칙 (특히 DIP, OCP, SRP)생성 패턴은 의존 역전, 개방 폐쇄, 단일 책임 원칙과 깊은 관련

용어 정리

카테고리용어설명
1. 생성 패턴 (GoF Creational Patterns)Factory Method객체 생성 로직을 서브클래스에 위임하여 캡슐화하는 패턴
Abstract Factory관련된 객체군 (Product Family) 을 일관되게 생성하는 인터페이스 제공
Builder Pattern복잡한 객체를 단계별로 구성하여 생성하는 패턴
Prototype Pattern기존 객체 (Prototype) 를 복제하여 새로운 객체를 생성
Singleton Pattern클래스 인스턴스를 단 하나로 제한하고 전역 접근을 제공
2. 설계 원칙 및 개념Encapsulate What Varies변화하는 부분을 캡슐화하여 유연하고 유지보수 가능한 구조 유도
디커플링 (Decoupling)구성 요소 간의 결합도를 낮추어 모듈화와 확장성을 확보하는 설계 기법
객체 생성 메커니즘 (Object Creation Mechanism)시스템 내에서 객체를 생성하고 초기화하는 다양한 기법 또는 패턴의 총칭
3. 테스트 및 품질 관련Mock / Stub 객체테스트 시 실제 객체를 대체하여 사용되는 가짜 객체 (행위 검증용)
Object Pool (객체 풀)재사용 가능한 객체를 미리 생성하여 풀로 관리하는 메모리 최적화 패턴
Lazy Initialization (지연 초기화)객체가 실제로 필요할 때까지 생성을 지연시키는 초기화 전략
4. 소프트웨어 설계 접근법DI (Dependency Injection)객체 간 의존성을 외부에서 주입하여 느슨한 결합과 테스트 용이성 확보
DDD (Domain-Driven Design)도메인 모델 중심으로 복잡한 시스템을 설계하는 소프트웨어 접근 방식
5. 배경 및 역사GoF (Gang of Four)디자인 패턴을 체계화한 저자 네 명 (Gamma, Helm, Johnson, Vlissides) 을 일컫는 용어로, 디자인 패턴의 표준적 기초 제공

참고 및 출처

종합 가이드 및 이론 정리

실무 적용 및 사례 기반 자료

프레임워크 및 플랫폼 관점 자료

소프트웨어 아키텍처 연계