Factory Method Pattern
Factory Method 패턴은 객체 생성의 책임을 상위 클래스가 아닌 하위 클래스에 위임하여, 클라이언트가 어떤 클래스의 인스턴스를 만들 것인지 모른 채 객체를 생성할 수 있게 한다. 추상 클래스는 인터페이스만 정의하고, 실제 객체 생성을 하위 클래스에서 담당함으로써 확장성과 유연성을 확보한다. GoF 의 23 가지 디자인 패턴 중 가장 널리 사용되는 생성 패턴으로, “Virtual Constructor” 라고도 불린다.
이 패턴은 Creator 와 Product 라는 두 개의 주요 계층구조를 통해 객체 생성 로직을 캡슐화하며, Template Method 패턴과 유사한 구조를 가진다. 프레임워크 설계, UI 컴포넌트 생성, 데이터베이스 연결 관리 등 다양한 영역에서 활용되며, 2025 년 현재 마이크로서비스 아키텍처와 AI/ML 시스템에서 그 중요성이 더욱 부각되고 있다.
특히, 다형성과 DIP(Dependency Inversion Principle) 원칙에 따라 유연하고 유지보수하기 쉬운 아키텍처 설계에 핵심 역할을 수행한다.
핵심 개념
Factory Method Pattern (팩토리 메서드 패턴) 은 객체 생성을 위한 인터페이스를 정의하고, 인스턴스화할 클래스는 서브클래스가 결정하도록 하는 생성 패턴이다.
핵심 구성 요소:
- Creator (생성자): 팩토리 메서드를 선언하는 추상 클래스
- ConcreteCreator (구체적 생성자): 팩토리 메서드를 구현하는 클래스
- Product (제품): 생성될 객체들의 공통 인터페이스
- ConcreteProduct (구체적 제품): 실제 생성되는 객체들
패턴의 본질
- 책임 위임: 객체 생성의 책임을 서브클래스에 위임
- 상속 기반: 상속을 통한 다형성 활용
- 인터페이스 통합: 공통 인터페이스를 통한 객체 접근
- 런타임 결정: 실행 시점에 구체적인 객체 타입 결정
의도 (Intent)
객체 생성을 위한 인터페이스를 정의하되, 어떤 클래스의 인스턴스를 생성할지는 서브클래스가 결정하도록 위임한다.
다른 이름 (Also Known As)
- Virtual Constructor(가상 생성자)
- Creator 패턴
동기 (Motivation / Forces)
- 객체 생성 로직을 분리하여 코드 중복, 결합도, 유지보수성 문제 해결
- 새로운 제품 추가 시 기존 코드 변경 없이 확장 가능
- 다양한 객체 생성이 필요한 상황에서 유연한 구조 제공.
적용 가능성 (Applicability)
- 생성할 객체의 구체 타입을 사전에 알 수 없거나, 변경이 빈번한 경우
- 라이브러리/프레임워크에서 확장성을 제공하고 싶을 때
- 제품군이 자주 추가/변경되는 시스템.
패턴이 해결하고자 하는 설계 문제
핵심 문제:
- 강한 결합 (Tight Coupling): 클라이언트가 구체 클래스에 직접 의존
- 확장성 부족: 새로운 객체 타입 추가 시 기존 코드 수정 필요
- 객체 생성 로직 분산: 생성 로직이 여러 곳에 중복되어 유지보수 어려움
- 컴파일 타임 의존성: 런타임에 객체 타입을 결정할 수 없음
배경
Factory Method Pattern 은 객체 지향 설계에서 " 어떤 클래스의 인스턴스를 생성할지 " 에 대한 결정을 미루는 필요성에서 탄생했습니다. 직접적인 생성자 호출은 클라이언트 코드와 구체 클래스 간의 강한 결합을 만들어 유지보수성과 확장성을 해칩니다.
목적 및 필요성
주요 목적:
- 객체 생성 로직의 캡슐화
- 클라이언트 코드와 구체 클래스 간의 결합도 감소
- 런타임에 객체 타입 결정 지연
- 새로운 제품 타입 추가 시 기존 코드 수정 최소화
필요성:
- 컴파일 타임에 생성할 객체 타입을 알 수 없는 경우
- 시스템이 어떤 제품을 생성할지 독립적으로 결정해야 하는 경우
- 제품군의 확장 가능성이 높은 경우
주요 기능 및 역할
- 객체 생성의 추상화: 클라이언트가 구체 클래스를 직접 지정하지 않고 객체를 생성한다.
- 서브클래스에 의한 구체화: 객체의 실제 타입은 서브클래스가 결정한다.
- 공통 인터페이스 제공: 생성된 객체는 공통 인터페이스를 통해 사용된다 [1][2][3].
특징
- 생성 패턴 (Creational Pattern): 객체 생성 방식에 초점을 둠.
- 상속 (Inheritance) 기반: 서브클래스가 객체 생성 로직을 구현.
- 확장성: 새로운 객체 타입 추가가 용이함.
- 결합도 감소: 클라이언트와 구체 클래스 간의 결합이 느슨함.
핵심 원칙
설계 원칙 준수
- 단일 책임 원칙 (SRP): 객체 생성 로직을 별도 클래스로 분리
- 개방 - 폐쇄 원칙 (OCP): 새로운 제품 타입 추가 시 기존 코드 수정 불필요
- 의존 역전 원칙 (DIP): 구체적인 클래스가 아닌 추상화에 의존
- 리스코프 치환 원칙 (LSP): 서브클래스가 기본 클래스를 완전히 대체 가능
패턴 적용의 결과와 트레이드오프
긍정적 결과:
- 클라이언트와 구체 제품 간의 결합도 감소
- 새로운 제품 타입 추가 시 기존 코드 변경 최소화
- 객체 생성 로직의 일관성 및 재사용성 확보
- 단위 테스트 작성 용이성 향상
트레이드오프:
- 코드 복잡성 증가로 인한 초기 개발 비용 상승
- 클래스 수 증가로 인한 프로젝트 구조 복잡화
- 간단한 객체 생성에 대한 오버엔지니어링 위험
- 상속 기반 설계로 인한 유연성 제약
관련 패턴과의 연관성
Abstract Factory Pattern 과의 관계:
- Factory Method 는 하나의 제품을, Abstract Factory 는 제품군을 생성
- Factory Method 를 여러 개 조합하여 Abstract Factory 구현 가능
Builder Pattern 과의 결합:
- 복잡한 객체 생성 시 Factory Method 와 Builder Pattern 결합
- 팩토리가 Builder 를 반환하여 단계별 객체 구성 지원
Singleton Pattern 과의 결합:
- 팩토리 인스턴스를 싱글톤으로 관리
- 생성되는 제품을 싱글톤으로 관리
현대적 구현 기법
함수형 프로그래밍 접근:
의존성 주입과의 결합:
- Spring Framework 의 @Factory 어노테이션
- 설정 기반 팩토리 bean 등록
주요 원리 및 작동 방식
- 객체 생성의 추상화: 클라이언트는 구체 클래스를 몰라도 객체를 생성할 수 있다.
- 서브클래스에 의한 구체화: 객체의 실제 타입은 서브클래스가 결정한다.
- 공통 인터페이스: 생성된 객체는 공통 인터페이스를 통해 사용된다.
classDiagram class Creator { <<abstract>> +operation() +factoryMethod() Product } class ConcreteCreatorA { +factoryMethod() ConcreteProductA } class ConcreteCreatorB { +factoryMethod() ConcreteProductB } class Product { <<interface>> +doSomething() } class ConcreteProductA { +doSomething() } class ConcreteProductB { +doSomething() } Creator <|-- ConcreteCreatorA Creator <|-- ConcreteCreatorB Creator ..> Product : creates ConcreteCreatorA ..> ConcreteProductA : creates ConcreteCreatorB ..> ConcreteProductB : creates Product <|-- ConcreteProductA Product <|-- ConcreteProductB
작동 원리:
- 클라이언트가 Creator 의 operation() 메서드 호출
- operation() 내부에서 factoryMethod() 호출
- ConcreteCreator 가 factoryMethod() 구현체 실행
- 해당하는 ConcreteProduct 인스턴스 생성 및 반환
- 생성된 객체로 비즈니스 로직 수행
구조 및 아키텍처
구성 요소
구분 | 구성요소 | 기능 | 역할 | 특징 |
---|---|---|---|---|
필수 | Creator (생성자 클래스) | 팩토리 메서드 선언, 제품 사용 로직 정의 | 객체 생성 인터페이스 제공, 비즈니스 로직 캡슐화 | 추상 클래스 또는 인터페이스로 정의 |
ConcreteCreator (구체적 생성자) | 특정 제품 생성 책임 수행 | 실제 객체 생성 로직 구현 | Creator 를 상속하여 팩토리 메서드 오버라이딩 | |
Product (제품 인터페이스) | 제품 공통 연산 정의 | 클라이언트 코드와 제품 구현 간 결합 방지 | 인터페이스 또는 추상 클래스로 정의 | |
ConcreteProduct (구체적 제품) | 실제 기능 수행 | Product 인터페이스의 구체 구현 | Product 를 구현한 실제 클래스 | |
선택 | ParameterizedFactoryMethod | 매개변수에 따라 다양한 제품 생성 | 하나의 팩토리 메서드로 여러 제품 처리 | 조건 분기 또는 enum 기반 생성, 런타임 결정 가능 |
Creator 의 역할:
- 팩토리 메서드 인터페이스 정의
- 제품 객체를 사용하는 비즈니스 로직 구현
- 구체적인 제품 생성은 서브클래스에 위임
ConcreteCreator 의 역할:
- 특정 ConcreteProduct 인스턴스를 생성하는 팩토리 메서드 구현
- 생성할 제품의 타입을 결정
Product 계층구조의 역할:
- 모든 제품이 구현해야 하는 공통 인터페이스 정의
- 클라이언트 코드가 구체 제품에 의존하지 않도록 추상화 제공
클래스 구조 다이어그램
classDiagram class Creator { <<abstract>> + factoryMethod(): Product + someOperation(): string } class ConcreteCreator { + factoryMethod(): Product } class Product { <<interface>> + usefulOperation(): string } class ConcreteProduct1 { + usefulOperation(): string } class ConcreteProduct2 { + usefulOperation(): string } Creator <|-- ConcreteCreator Product <|.. ConcreteProduct1 Product <|.. ConcreteProduct2 ConcreteCreator --> Product : creates
- Creator(추상 팩토리 역할)
factoryMethod()
선언 (추상)someOperation()
등에서 factoryMethod 호출해 반환된 Product 사용
- ConcreteCreator
factoryMethod()
구현 → 구체 Product 반환
- Product
- 클라이언트가 사용하는 공통 인터페이스
- ConcreteProduct
- Product 구현체, 실제 기능 수행
구현 기법
구현 기법 | 정의 및 설명 | 구성 요소 요약 | 목적/의도 | 장점 | 유의사항 / 단점 | 활용 사례 |
---|---|---|---|---|---|---|
표준 Factory Method | Creator 추상 클래스에 factoryMethod() 를 선언하고, ConcreteCreator 에서 이를 오버라이딩하여 객체 생성 | - Creator (추상 클래스) - ConcreteCreator - Product / ConcreteProduct | 상속 기반으로 타입 안전성과 구조적 확장성 확보 | - 타입 안전성 - 구조적 명확성 - 재사용 가능 | - 클래스 수 증가 - 제품 수만큼 서브클래스 생성 필요 | 로깅 시스템, 메시지 파서, GUI 위젯 생성 등 복잡한 객체 생성 |
파라미터화된 Factory | factoryMethod(param) 에 전달된 매개변수에 따라 서로 다른 ConcreteProduct 를 반환 (조건 분기 기반) | - Creator 클래스 하나 - 조건부 생성 로직 - Enum/상수로 타입 정의 | 하나의 팩토리에서 여러 제품 타입 동적 처리 | - 코드 중복 제거 - 클래스 수 감소 - 조건 기반 유연성 | - SRP 위반 우려 - 분기 조건이 많아지면 유지보수 어려움 | 문서 타입, 결제 수단, 알림 타입 등 다양한 제품군 처리 |
등록 기반 Factory | 제품 생성 함수를 미리 등록한 후 문자열이나 키를 통해 해당 생성자를 조회하여 객체 생성 (클래스 이름 → 생성자 매핑) | - Registry(Map) - 키 (String) - 생성자 (Supplier) - create(key) | 런타임 유연성 확보, 동적 확장 가능 | - 런타임 제품 등록/제거 가능 - 플러그인 시스템에 유리 | - 키 - 생성자 매핑 관리 필요 - 잘못된 키 전달 시 예외 발생 | 플러그인 시스템, UI 컴포넌트 생성기, DSL 해석기 |
정적 팩토리 메서드 | 생성자 대신 의미 있는 static 메서드로 객체를 생성하는 방식. 생성자 대신 명시적 메서드명을 사용함 | - private 생성자 - static create 메서드 - 메서드 오버로딩 | 의미 명확한 객체 생성, 생성자 제한 및 제어 | - 네이밍 직관적 - 인스턴스 재사용 가능 - 싱글턴·캐싱과 조합 가능 | - 상속 불가 - 인터페이스 기반 확장에는 적합하지 않음 | Optional.of() , List.of() 등 Java 객체 생성 API |
템플릿 메서드 결합형 | Creator 의 비즈니스 로직 내에서 factoryMethod() 를 호출하도록 설계. 객체 생성만 팩토리 메서드로 분리됨 | - Creator: 비즈니스 로직 포함 - factoryMethod() 분리 | 생성 절차 일부만 유연하게 변경 가능 | - 핵심 로직은 공통, 생성만 다양화 - 코드 중복 방지 | - 전체 객체 흐름이 고정되어야 함 - 커스터마이징이 제한적일 수 있음 | 문서 생성 워크플로우, 공통 처리 이후 단계적 분기 처리 |
함수형 팩토리 | JavaScript, Python 등에서 고차 함수, 클로저, 람다 등을 이용해 객체 생성을 함수로 캡슐화하여 동적으로 처리 | - 생성자 함수 또는 lambda - 키 - 함수 맵핑 - create(key) | 간결한 표현, 동적 확장 | - 코드 간결 - 동적 구성 유연 - 고차 함수로 커스터마이징 용이 | - 명시적 타입 제한 어려움 - 복잡한 구조에는 부적합 | 프론트엔드 컴포넌트 팩토리, 파서, 라우터 등 |
의존성 주입 기반 Factory | 팩토리를 외부에서 생성하거나 주입받아 사용하는 방식. Factory Method 자체는 고정되어 있고, 실제 생성자는 런타임 시 주입됨 | - 외부 DI 컨테이너 - Interface 기반 팩토리 - 생성자 또는 Setter 주입 | Factory 관리 책임 외부화로 결합도 감소 | - 테스트 용이성↑ - DI 컨테이너와의 자연스러운 통합 | - 외부 DI 환경 필요 - 구조가 과도하게 복잡해질 수 있음 | Spring, FastAPI 등 DI 환경의 서비스 팩토리 |
- 상속 기반: 전통적 방식으로 설계 명확함. 클래스 수 증가 유의.
- 파라미터 기반: if/else or switch 로 유연성↑, 복잡성↑ 시 주의.
- 등록 기반: 플러그인 구조에서 효과적, 런타임 동적 생성 가능.
- 정적 팩토리: 불변 객체/싱글턴 생성, 의미 있는 생성 메서드명 강조.
- 템플릿 결합형: 공통 비즈니스 흐름에 따라 생성만 달라지는 경우 적합.
- 함수형 팩토리: 람다/고차 함수 활용, 동적 시스템에 적합.
- DI 기반: 의존성 역전 실현, 테스트 및 유지보수에 유리.
표준 Factory Method Pattern (상속 기반)
|
|
🎯 특징: 명확한 상속 구조, 제품 추가 시 Creator 서브클래스 확장
매개변수화된 Factory Method (조건 분기 기반)
|
|
🎯 특징: 서브클래스 대신 조건 분기 사용으로 단순화 가능 (단 SRP 위반 우려)
등록 기반 Factory Method (레지스트리 기반, 동적 확장)
|
|
🎯 특징: 동적 등록/확장에 적합, 플러그인 아키텍처에 자주 사용
정적 팩토리 메서드 (Static Method 기반)
|
|
🎯 특징: 명확한 생성 메서드명 제공, 생성자 은닉 가능
함수형 팩토리 (고차 함수 기반)
|
|
🎯 특징: 코드 간결성 우수, 람다나 클로저와 결합 용이
의존성 주입 기반 Factory (DI 컨테이너 사용 가정)
|
|
🎯 특징: DI 컨테이너와 통합 용이, 테스트와 유연성 극대화
장점
카테고리 | 항목 | 설명 |
---|---|---|
1. 결합도 감소 | 느슨한 결합 (Loose Coupling) | 클라이언트가 구체적인 클래스가 아닌 추상 인터페이스에 의존함으로써, 의존성 감소 및 변경에 대한 유연성 확보 |
DIP 준수 | Creator 가 구체 Product 가 아닌 추상 Product 에 의존함으로써 Dependency Inversion Principle을 구현 | |
캡슐화 (Encapsulation) | 객체 생성 로직을 팩토리 내부에 감추어 클라이언트는 구체 구현 세부사항을 몰라도 사용 가능 | |
2. 책임 분리 | 단일 책임 원칙 (SRP) | 객체 생성 책임과 객체 사용 책임을 분리함으로써 각 클래스의 책임 명확화 |
객체 생성 캡슐화 | 객체 생성 방식을 클라이언트 코드에서 분리하여 응집도를 높이고 재사용성을 강화 | |
3. 확장성 | 개방 - 폐쇄 원칙 준수 (OCP) | 새로운 제품 타입을 기존 코드를 변경하지 않고 확장 가능 (새로운 ConcreteProduct 및 Creator 서브클래스만 추가하면 됨) |
구조 확장 용이성 | 다양한 제품군/서비스를 추가할 때 기존 로직을 건드리지 않고 Creator 하위 클래스만 확장 가능 | |
4. 테스트성 | 테스트 용이성 (Testability) | Mock 팩토리 또는 테스트 전용 팩토리 구성으로 단위 테스트 작성이 쉬움 |
의존성 주입과 결합 용이 | 생성된 객체를 외부에서 주입 가능해 테스트 더블 삽입이나 의존성 대체가 쉬움 | |
5. 구조적 품질 | 코드 재사용성 | 팩토리 메서드를 여러 클라이언트에서 재사용 가능하며, 동일한 생성 로직을 중앙화하여 관리 가능 |
구현 유연성 제공 | 다양한 생성 전략 (지연 생성, 캐싱, 객체 풀 등) 을 팩토리 내부에 적용할 수 있어 유연한 객체 생성 방식 구현 가능 |
단점과 문제점 그리고 해결방안
카테고리 | 항목 | 문제 설명 | 원인 | 영향 | 탐지/진단 | 예방 및 해결 방안 |
---|---|---|---|---|---|---|
설계 복잡성 | 클래스 수 증가 | Product, Creator, ConcreteCreator 등 다수 클래스 필요 | 제품 수가 많을수록 클래스 쌍이 반복 생성됨 | 구조 과잉, 진입 장벽 증가 | 코드 리뷰, 클래스 계층 분석 | Abstract Factory 도입, Registry 패턴, Simple Factory 또는 함수형 팩토리 적용 |
복잡성 증가 | 단순 객체 생성에도 추상화로 인해 과도한 구조 | 추상화 수준 불균형 | 오히려 가독성 및 생산성 저하 | 설계 복잡도 평가 지표 | 객체 생성 복잡도 평가 후 필요 시 적용, 빌더/템플릿/전략 패턴과 결합 | |
상속 강제성 | ConcreteCreator 는 Creator 를 반드시 상속해야 함 | 상속 기반 구현 구조의 제한 | 다형성 제약, 테스트 불편 | 구조 정적 분석 도구 | 컴포지션 기반 팩토리 또는 고차 함수 팩토리 적용 | |
유지보수성 | 팩토리 클래스 폭발 | 제품 추가 시마다 Creator/Factory 서브클래스 증가 | 제품 수요 증가, 단일 책임 원칙 준수 미흡 | 패키지 난해, 유지보수 비용 증가 | 클래스 수, 메트릭 측정 도구 | Template Method, BaseFactory 추출, Registry 기반 팩토리 활용 |
팩토리 비대화 | 하나의 팩토리에 너무 많은 생성 책임이 집중됨 | 조건 분기 또는 고정 로직 집중화 | OCP 위반, 유연성 저하 | 코드 복잡도 분석 | 팩토리 분할, Chain of Factory 또는 Abstract Factory 패턴 적용 | |
순환 의존성 | Creator ↔ Product 의존 관계가 발생하는 경우 | Product 내부에서 Creator 참조 | 컴파일 에러, 무한 루프 위험 | 의존성 분석 도구 | 의존 방향 재설계, 이벤트 기반 통신, 의존성 주입 (DI) 적용 | |
테스트성 | 테스트 복잡성 | 팩토리 별로 다양한 테스트 시나리오 필요 | 생성 대상 분기 증가, 테스트 환경 구축 어려움 | 테스트 코드 중복, 커버리지 관리 어려움 | 커버리지 분석, 테스트 전략 분석 | MockFactory, 테스트 전용 팩토리, DI 기반 구성 |
객체 상태 검증 어려움 | 생성된 객체 내부 상태 확인이 어려움 | 팩토리 은닉 구조로 인해 직접 생성자 접근 제한됨 | 객체 단위 테스트 난이도 상승 | 테스트 더블 사용 유무 분석 | 인터페이스 기반 테스트, 상태 검증 로직 도입 | |
성능 최적화 | 생성 비용 오버헤드 | 생성시마다 객체 초기화 및 연결 구성 필요 | 팩토리 호출이 매번 객체를 새로 생성 | 메모리/시간 오버헤드 | 프로파일링 도구 | Lazy Initialization, 캐싱, Object Pool 적용 |
메서드 호출 오버헤드 | 다형성 구조로 인한 간접 호출 누적 | 인터페이스 - 구현체 분리 구조 | 성능 저하, 실시간성 시스템에 불리함 | 호출 경로 트레이싱 | Hot Path 최적화, 정적 팩토리 (static factory) 적용 | |
구조적 제약 | 제네릭 타입 한계 | 제네릭 언어에서 팩토리 타입 매핑이 복잡 | 런타임 타입 소거 및 제약 | 타입 안정성 저하, 코드 가독성 저하 | 정적 분석 도구, 타입 힌트 활용 | 타입 힌트, Factory Injection, 고차 함수 기반 팩토리 적용 |
비동기 팩토리 필요 | JS/Python 등에서 비동기 객체 생성이 필요한 경우 | async 환경에서 동기 팩토리는 부적절 | Future/Callback 관리 복잡 | 비동기 호출 경로 정리 | Async Factory 구성 (async def ), 콜백 기반 또는 Promise/Future 기반 구현 적용 |
도전 과제 및 해결책
카테고리 | 도전 과제 | 설명 | 권장 해결 방안 |
---|---|---|---|
설계 복잡성 | 클래스 수 증가 | 제품 수에 따라 Creator / Product 클래스가 폭증 | 패키지 정리, Simple Factory, Abstract Factory 패턴과 결합, 코드 생성기 사용 |
설계 복잡성 증가 | 단순 객체에도 복잡한 구조 유발 가능 | 사전 복잡도 분석, 전략/템플릿/레지스트리 패턴과 결합 고려 | |
OCP 위반 가능성 | Creator 내부 조건문 도입 시 확장에 취약 | Creator 서브클래싱 유지, 조건문 최소화 | |
유지보수 및 확장성 | 유사한 팩토리 로직 중복 | ConcreteFactory 구현부가 반복될 수 있음 | BaseFactory 추출 또는 Template Method 패턴 적용 |
런타임 팩토리 선택 어려움 | 컴파일 타임 결정으로 유연성 저하 | Factory Registry, DI 컨테이너, 설정 기반 매핑 | |
제품 추가 시 변경 전파 위험 | Interface 구조 설계가 미흡하면 변경 파급 | SRP, ISP 준수 및 Product 인터페이스 안정성 확보 | |
성능 최적화 | 객체 생성 비용 | 다형성과 동적 객체 생성 오버헤드 | 객체 풀링 (Object Pool), 지연 초기화 (Lazy Init), 캐싱 메커니즘 |
메서드 호출 성능 | 팩토리 구조로 인한 호출 계층 증가 가능성 | 성능 병목 지점 프로파일링, Static Factory 고려 | |
운영 및 동시성 | 멀티스레드 환경에서 동기화 문제 | 팩토리 호출 중 race condition, 중복 생성 가능성 | Thread-safe 구현, 불변 객체 생성, ThreadLocal Factory |
버전/플랫폼 종속 문제 | 구체 팩토리가 플랫폼 또는 버전에 종속될 가능성 | 공통 인터페이스 유지 및 플랫폼 추상화 | |
테스트 용이성 | 테스트 복잡성 증가 | 팩토리 로직과 Product 동시 테스트 어려움 | MockFactory, StubFactory, 테스트 전용 Creator 구성 |
객체 상태 테스트 어려움 | 팩토리에서 생성한 객체의 내부 상태 확인 어려움 | 인터페이스 중심 테스트, 테스트 더블 (Test Double) 활용 | |
언어/플랫폼 특성 | 제네릭 타입 처리 어려움 | 제네릭 언어에서 타입 기반 매핑이 번거로움 | Factory Injection, 고차 함수 (HOF) 활용 |
동적 언어의 타입 안정성 부족 | 런타임 오류 가능성이 높음 | 정적 타입 힌트, Mypy 등 정적 분석 도구 활용, 타입 검증 메타 프로그래밍 적용 | |
비동기 팩토리 메서드 필요 | JS/Python 등에서 비동기 객체 생성을 처리할 필요 있음 | async factory , 콜백 패턴 또는 Future 기반 구현 |
분류 기준에 따른 종류 및 유형
분류 기준 | 유형 | 설명 | 적용 시 고려사항 |
---|---|---|---|
1. 구현 방식 | 추상 클래스 기반 | Creator 를 추상 클래스로 선언하고 서브클래스가 팩토리 메서드를 구현 | 상속 구조가 명확할 때 적합, 계층 설계 유지 쉬움 |
인터페이스 기반 | Creator 를 인터페이스로 정의하고 유연하게 다양한 구현 제공 | 다중 구현 또는 동적 주입이 필요한 경우 유리 | |
클래식 서브클래스 팩토리 | Creator 의 서브클래스에서 생성 책임 수행 (GoF 원형 구조) | 단일 책임 원칙 (SRP) 기반의 구조화 가능 | |
고차 함수 팩토리 | 생성 함수를 인자로 전달받아 팩토리 기능 수행 | 함수형 언어, 전략적 팩토리 교체 필요 시 유용 | |
Registry 기반 팩토리 | 생성자나 함수 객체를 Map 등에 등록하여 런타임에 룩업하여 생성 | 확장성 높은 구조, 플러그인 시스템에 적합 | |
2. 생성 방식 | 정적 팩토리 메서드 | static 메서드로 객체 생성, 주로 of() , getInstance() 형식 | 간단한 객체나 유틸리티 객체 생성에 효과적 |
인스턴스 메서드 기반 | 팩토리 메서드를 인스턴스 메서드로 구현, 객체 상태를 활용한 생성 로직 포함 | 상태 기반 생성 전략에 적합 | |
3. 생성 시점 | 즉시 생성형 | 팩토리 호출 시 바로 객체 생성 | 가벼운 객체, 빠른 반응성이 필요한 경우 |
지연 생성형 | 실제 필요 시점까지 객체 생성을 미룸 (Lazy Initialization ) | 메모리 최적화, 무거운 객체에 적합 | |
4. 매개변수 사용 | 매개변수형 팩토리 | 전달된 인자를 기반으로 생성할 제품 타입을 결정 (switch-case , enum , key ) | 조건 분기 통제 필요, 테스트 용이성 확보 |
타입별 전용 팩토리 | 각 제품군마다 전용 생성 메서드 또는 Creator 를 분리하여 구성 | 타입 안정성, 명시적 타입 처리 필요 시 유리 | |
5. 등록/확장 방식 | 정적 등록 | 제품과 생성자 매핑이 컴파일 타임에 결정됨 | 타입 안전성과 예측 가능한 구조 보장 |
동적 등록 | 런타임에 새로운 제품 타입 및 생성자 등록 가능 (플러그인, 설정 기반 팩토리) | 시스템 확장성/유연성 확보, 설정 또는 리플렉션 필요 | |
Factory Registry | 타입별 Creator 를 Map<String, Creator> 로 관리하여 실행 시 선택 | 제품군이 많은 경우 유용, 전략 또는 설정 기반 연동 구조 가능 | |
6. 반환 구조 | 단일 객체 반환 | 단일 제품 인스턴스를 생성 후 반환 | 대부분의 팩토리에 해당되는 기본 방식 |
객체 풀 / 싱글턴 반환 | 동일 객체를 재사용하거나 풀링 방식으로 반환 (Object Pool , Singleton ) | 생성 비용 높은 객체 최적화에 효과적 | |
7. 언어 특성 | 동적 팩토리 | Python, JavaScript 등 동적 언어 기반, 런타임 생성 및 타입 유연성 활용 | 리플렉션, 메타프로그래밍 활용 가능 |
정적 팩토리 | Java, C++ 등 정적 타입 언어 기반, 컴파일 타임 안전성 강조 | 제네릭, 오버로딩, 인터페이스 기반 구조 활용 |
실무 적용 예시
분야 | 적용 사례 | 구체 예시 / 기술 스택 | 적용 목적 및 효과 |
---|---|---|---|
프레임워크 | Bean 및 Handler 생성 | Spring BeanFactory , HandlerAdapter | DI 와 결합하여 유연한 객체 관리 및 요청 처리 |
데이터베이스 | DB 커넥션/드라이버 팩토리 | JDBC DriverManager , Hibernate Dialect Factory | DB 벤더 교체 대응, 커넥션 생명주기 관리 |
UI/그래픽 | UI 컴포넌트 및 LookAndFeel 생성 | Java Swing, JavaFX, Android ViewFactory | 플랫폼별 UI 추상화 및 커스터마이징 용이 |
로깅 시스템 | 로거 객체 생성 | SLF4J, Log4j LoggerFactory | 다양한 로깅 구현체를 인터페이스 기반으로 유연하게 전환 가능 |
파싱/입출력 | 파서 객체 생성 | Jackson, Gson, XML Parser Factory | JSON, XML, CSV 등 포맷에 따라 파서 자동 선택 |
웹 요청 처리 | 요청 핸들러, 필터 등 동적 생성 | Spring DispatcherServlet, Servlet FilterFactory | HTTP 요청 타입에 맞는 핸들러 동적 생성 |
게임 개발 | 게임 내 유닛, 아이템 팩토리 | UnitFactory , ItemFactory | 게임 밸런스 조정, 객체 확장성 및 스폰 전략 구성 |
마이크로서비스 | 서비스 인스턴스 생성 및 연결 | Service Discovery + Factory | 동적 서비스 연결, 부하 분산, 장애 격리 |
로그 수집/분석 | Logger, Appender 팩토리 | Logstash, Fluentd 플러그인 팩토리 | 로깅 전략 및 대상 (LogFile, TCP 등) 에 따라 유연하게 생성 |
파일 처리 | 파일 파서 또는 변환기 생성 | Apache POI, OpenCSV, Tika | 파일 확장자별 파서/리더 자동 생성 |
ORM/DAO 계층 | DAO 및 세션 팩토리 | MyBatis, Hibernate SessionFactory | DB 접근 객체의 추상화 및 유연한 관리 |
테스트 | Mock, Stub, Spy 객체 생성 | Mockito, JMock 팩토리 | 테스트 격리 및 시나리오별 테스트 객체 주입 |
플러그인 시스템 | 팩토리 레지스트리 기반 플러그인 로딩 | Eclipse ExtensionPoint, Spring SPI | 런타임 확장성 확보, 구현체 분리 및 캡슐화 |
다국어/지역화 | Locale 기반 객체 팩토리 | java.util.Calendar , ResourceBundle Factory | 지역 설정에 따른 동적 객체 제공 |
보안/암호화 | 암호화/권한 객체 생성 | JWTProvider, CipherFactory | 정책 기반 보안 객체 및 알고리즘 구현체 선택 |
활용 사례
사례 1: 멀티 클라우드 환경에서 스토리지 서비스 추상화
시스템 구성:
- CloudStorageFactory (추상 팩토리)
- AWSStorageFactory, AzureStorageFactory, GCPStorageFactory (구체적 팩토리)
- CloudStorage (인터페이스)
- S3Storage, BlobStorage, CloudStorage (구체적 구현)
graph TB Client[클라이언트 애플리케이션] %% Factory Layer subgraph "Factory Layer" CSF[CloudStorageFactory] AWSF[AWSStorageFactory] AzureF[AzureStorageFactory] GCPF[GCPStorageFactory] end %% Product Layer subgraph "Product Layer" CS[CloudStorage Interface] S3[S3Storage] Blob[BlobStorage] GCS[GCPStorage] end %% 관계 정의는 subgraph 밖에서 Client --> CSF CSF --> AWSF CSF --> AzureF CSF --> GCPF AWSF --> S3 AzureF --> Blob GCPF --> GCS CS --> S3 CS --> Blob CS --> GCS
워크플로우:
- 클라이언트가 설정된 클라우드 타입으로 팩토리 요청
- 해당 클라우드의 ConcreteFactory 가 스토리지 객체 생성
- 생성된 스토리지 객체로 파일 업로드/다운로드 수행
- 클라이언트는 구체적인 클라우드 API 를 알 필요 없음
Factory Method 의 역할:
- 클라우드 프로바이더별 인증 및 연결 로직 캡슐화
- 설정 기반 동적 스토리지 객체 생성
- 각 클라우드 서비스의 고유한 초기화 과정 처리
유무에 따른 차이점:
- 적용 전: 클라이언트 코드에 클라우드별 구체적 생성 로직 산재, 새 클라우드 추가 시 클라이언트 코드 수정 필요
- 적용 후: 설정 변경만으로 클라우드 전환 가능, 새 클라우드 추가 시 해당 팩토리와 구현체만 추가
사례 2: 다양한 데이터베이스 (MySQL, Oracle 등) 연결 객체 생성
시스템 구성:
- Product: DatabaseConnection (인터페이스)
- Concrete Product: MySQLConnection, OracleConnection
- Creator: DatabaseConnectionFactory (추상 클래스)
- Concrete Creator: MySQLConnectionFactory, OracleConnectionFactory
Workflow:
- 클라이언트는 DatabaseConnectionFactory 의 createConnection() 호출
- Concrete Creator 가 실제 Connection 객체 생성
- 클라이언트는 DatabaseConnection 인터페이스로 사용
차이점:
- Factory Method Pattern 미적용 시: 클라이언트가 구체 클래스를 직접 생성 → 결합도 높음, 확장 어려움
- 적용 시: 클라이언트는 인터페이스만 알면 됨 → 결합도 낮음, 확장 용이.
사례 3: GUI 위젯
시스템 구성: GUI 프레임워크에서 Factory Method 이용해 Button
인터페이스 기반으로 플랫폼 별 버튼 생성
구성도:
sequenceDiagram Client->>WindowsGUIFactory: createButton() WindowsGUIFactory->>WindowsButton: new() Client->>WindowsButton: render()
워크플로우:
|
|
Factory 적용 유무 비교
- 적용 시:
Client
는Button
인터페이스만 알고 플랫폼 전환 시 코드 변경 불필요 - 미적용 시: 플랫폼마다
if-else
분기 존재 → 유지보수성 급감
사례 4: 알림 (Notification) 서비스
요구사항:
- Slack, Email, SMS 세 가지 방식의 알림 지원
- 클라이언트는 어떤 알림 방식이 사용되는지 몰라도 사용 가능해야 함
시스템 구성
|
|
Workflow:
- Client 는 설정 또는 인자에 따라 Factory 선택
- Factory 의
createNotifier()
호출로 구현체 반환 send(message)
메서드로 메시지 전송
코드 구현:
|
|
사례 5: 다양한 결제 수단 객체 생성
시스템 구성:
- Product: Payment
- ConcreteProduct: CreditCardPayment, PaypalPayment 등
- Creator: PaymentFactory
- ConcreteCreator: CreditCardFactory, PaypalFactory 등
Workflow:
- 클라이언트는 PaymentFactory 의 인터페이스만 사용
- 실제 결제 객체 생성은 하위 팩토리에서 결정
- 새로운 결제 수단 추가 시 기존 코드 수정 없이 Factory/Payment 만 추가
역할: 결제 객체 생성 책임 분리, 확장성/유지보수성 강화
코드 예시:
|
|
구현 예시
Python: Database Connection
|
|
Python: Parser
|
|
Javascript
|
|
실무에서 효과적으로 적용하기 위한 고려사항 및 주의할 점
카테고리 | 항목 | 설명 | 권장사항 |
---|---|---|---|
1. 설계 단계 | 패턴 적용 판단 | 객체 종류가 적을 경우 오히려 복잡도 증가 | 제품 수가 3 개 이상이거나 제품군이 자주 변경될 때 적용 |
Creator 인터페이스 설계 | Creator 는 반드시 추상화되어야 함 | createProduct() 등으로 표준화, SRP/OCP 기반 설계 | |
Product 인터페이스 설계 | 모든 Product 들이 공통 구현 가능한 기능만 포함 | DIP 기반으로 불필요한 메서드 포함 방지 | |
계층 구조 설계 | Creator ↔ Product 간 병렬 계층 구조 유지 필요 | 1:1 매핑 유지, 필요한 경우 Abstract Factory 패턴 결합 | |
인터페이스 안정성 | 인터페이스 변경이 전체 구현체에 영향을 줄 수 있음 | 기능 최소화 및 변경 가능성 고려한 설계 | |
2. 구현 단계 | 명명 규칙 | 객체 생성 메서드는 의미 있는 명명 필요 | createXxx , buildYyy 등 도메인 기반 규칙 일관화 |
조건 분기 최소화 | if/else 문이 많아지면 Factory 의미 퇴색 | Creator 서브클래스 분리 또는 전략 패턴 결합 | |
오류 처리 | 잘못된 요청에 대한 예외 처리 및 메시지 제공 | 의미 있는 예외 타입 정의 + 로깅 + API 문서화 | |
문서화 | 각 팩토리의 목적과 생성 조건 명확히 설명 | JavaDoc, Swagger 등 도구를 통한 상세 설명 작성 | |
3. 유지보수성 | 클래스 수 관리 | Product/Creator 수 증가 시 유지보수 어려움 | Registry 패턴 또는 DI 기반 팩토리 관리 |
팩토리 확장성 | 제품 추가 시 Factory 수정 필요 | 설정 기반 팩토리 또는 리플렉션 기반 동적 등록 고려 | |
코드 복잡도 관리 | 팩토리 중복 정의 및 의미 없는 추상화 방지 | 단순 객체는 Static Factory 또는 DI 적용으로 간결화 | |
버전 관리 | 인터페이스 변경 시 하위 호환성 문제 발생 | Deprecated 처리 + 마이그레이션 가이드 제공 | |
4. 테스트/운영 | 테스트 용이성 | 인터페이스 기반 테스트 시 유리 | Mock/Stub 팩토리, 의존성 주입을 통한 테스트 환경 구성 |
로깅 및 모니터링 | 객체 생성 추적 및 오류 원인 분석 필요 | 생성 로그 수집, APM, Metrics 등 연계 | |
운영 중 성능 모니터링 | 고비용 객체 생성 시 성능 저하 발생 가능 | 프로파일링 도구 활용, 객체 풀링 및 캐시 적용 | |
객체 생성 비용 최적화 | 무거운 객체 반복 생성 방지 | Singleton, Object Pool, Prototype 패턴과의 조합 | |
5. DI/플러그인 연계 | 외부 의존성 주입 | 팩토리를 외부에서 주입받아 유연성 확보 | Spring @Bean , NestJS @Injectable() 등 DI 컨테이너 기반 구성 |
설정 기반 팩토리 선택 | 외부 설정 또는 전략 패턴 기반 팩토리 자동 선택 | 환경 변수, 설정 파일 (YAML/JSON), 전략 키 기반 분기 | |
플러그인 구조/동적 확장 | 런타임에 팩토리 추가 및 교체가 필요한 경우 | 리플렉션, SPI(Service Provider Interface), Plugin Registry 패턴 적용 |
테스트 환경에서 팩토리 패턴 적용 방법
목적:
- 테스트 환경에서 의존 객체(DB, 외부 API, 메시징 등) 를 실제 구현이 아닌 Mock, Stub, Fake 객체로 교체
- 유닛 테스트의 격리성 확보
적용 전략
전략 | 설명 | 예시 |
---|---|---|
Test Factory 구현 | 테스트용 팩토리를 별도 구현 | TestNotificationFactory → MockEmailNotifier 반환 |
팩토리 인터페이스 분리 | DI 컨테이너로 주입 가능하게 설계 | Spring @Profile, NestJS module override |
Factory Registry Mocking | 런타임에 팩토리 Map 교체 | FactoryRegistry.replace("payment", MockPaymentFactory) |
Provider 패턴 | 팩토리 대신 Provider 를 통해 주입 | Provider<DatabaseClient> 로 변경 유도 |
Configuration Based Swap | 설정 파일에 따라 팩토리 교체 | application-test.yml 에 test factory 설정 |
테스트 예시
- Java + JUnit + Mockito
|
|
테스트 환경에서의 고려사항
항목 | 설명 | 권장 사항 |
---|---|---|
생성 주체 분리 | new 사용 지양 | 팩토리 또는 DI 컨테이너 사용 |
테스트 팩토리 명확화 | 테스트 전용 팩토리를 별도 구현 | TestXxxFactory , MockXxxProvider |
설정 분리 | 테스트 환경별 구성 분리 | application-test.yml , jest.config.js 등 |
주입 전략 | Factory 를 인터페이스 기반으로 설계 | 유닛 테스트 내 Mock 주입 가능 구조 확보 |
활용 시 흔한 실수
항목 | 설명 | 해결 방안 |
---|---|---|
과도한 적용 | 단순 객체 생성에 Factory Method 를 도입해 구조만 복잡해짐 | 복잡성과 확장성 사이의 균형 평가, 단순 생성은 일반 함수로 처리 |
부적절한 인터페이스 설계 | Product 인터페이스가 너무 구체적이거나 너무 추상적 | 실제 클라이언트 요구 중심으로 인터페이스 설계 |
팩토리 메서드에 부수효과 존재 | 객체 생성 외 다른 작업 수행 (로깅, 상태 변경 등) 으로 SRP 위반 | 객체 생성을 순수하게 분리, 생성 외 로직은 외부로 이동 |
실수 1: 과도한 적용
🔻 문제점: 단순 생성인데도 팩토리 구조가 과하게 도입되어 복잡도 증가
개선 코드 예시
- 일반 함수로 대체
✅ 해결: 구조 단순화, 불필요한 클래스를 제거하여 가독성과 유지보수성 향상
실수 2: 부적절한 인터페이스 설계
🔻 문제점: 인터페이스 설계가 실제 사용자의 목적/맥락을 반영하지 않음
개선 코드 예시
- 관찰자 중심 인터페이스로 개선
|
|
✅ 해결: 클라이언트 (사용자) 가 요구하는 행위 중심 인터페이스로 개선하여 유연성 확보
실수 3: 팩토리 메서드의 부수효과
|
|
🔻 문제점: 객체 생성 이외의 부수작업 (로깅, 출력 등) 이 팩토리 메서드에 혼합되어 있음
개선 코드 예시
- 팩토리는 생성에만 집중
|
|
✅ 해결: 단일 책임 원칙(SRP) 준수, 테스트와 재사용성 향상
성능을 최적화하기 위한 고려사항
카테고리 | 항목 | 설명 | 권장사항 |
---|---|---|---|
1. 메모리 최적화 | 객체 풀링 | 자주 사용되며 생성 비용이 높은 객체를 재사용 | Object Pool 패턴, 팩토리와 결합 |
지연 초기화 (Lazy Loading) | 사용 시점까지 객체 생성을 미루어 메모리 낭비 방지 | Singleton + Lazy Initialization, Proxy 패턴 활용 | |
캐싱 | 동일한 조건의 객체를 메모리에 보관하여 재사용 | HashMap 캐시, 불변 객체 재사용 | |
메모리 누수 방지 | 객체 생명주기 미관리로 인한 메모리 누수 방지 | WeakReference, 정리 로직 (cleanup) 구현 | |
2. 실행 성능 | 생성 로직 단순화 | 복잡한 조건 분기, 불필요한 동적 로직 제거 | 조건 분리, 로직 캡슐화 |
팩토리 캐싱 | Factory 인스턴스의 재사용을 통한 반복 생성 비용 절감 | Factory Singleton 또는 DI 컨테이너 등록 | |
조기 유효성 검증 | 잘못된 인자에 대해 생성 전에 빠르게 실패 | Factory 메서드 내 매개변수 검사 도입 | |
3. 구조 관리 | 중앙 팩토리 레지스트리 | 팩토리 인스턴스를 중앙에서 관리 | Map 기반 Registry 또는 Service Loader 사용 |
인터페이스 최소화 | 과도한 추상화로 인한 오버헤드 방지 | 꼭 필요한 인터페이스만 유지 | |
생성자 호출 최소화 | new 키워드의 중복 사용 방지 | 팩토리 내부로 캡슐화 | |
4. 확장성 | 동적 로딩 | 런타임에 팩토리를 추가/등록 가능하게 구성 | Reflection 기반 Registry, Plugin 아키텍처 활용 |
DI/IoC 결합 | 팩토리를 DI 컨테이너에 등록해 유지보수와 성능 향상 | Spring @Bean , NestJS @Injectable() 등 활용 | |
전략/플러그인 조합 | 다양한 전략/서비스를 런타임에 교체 가능 | Strategy 패턴 + Factory 조합 | |
5. 동시성/안정성 | 스레드 안전성 | 멀티스레드 환경에서 데이터 충돌 방지 | ThreadLocal, 불변 객체, synchronized factory |
부하 분산 | 다수의 팩토리 인스턴스를 통해 처리 분산 | Factory Pool 구성, 로드 밸런싱 로직 적용 | |
6. 테스트/운영 | 테스트 객체 주입 | 테스트 용 팩토리 또는 MockFactory 구현 | 테스트 환경에서 유연한 객체 생성 지원 |
재사용 가능성 | 팩토리/객체를 범용적으로 재사용 가능하도록 설계 | 공통 인터페이스 및 생성 규칙 표준화 | |
유지보수성 확보 | 팩토리 구조가 과하게 복잡해지지 않도록 유지 | 최소 구성 유지 + 의미 있는 추상화 수준 유지 | |
7. 보안/제약조건 | 타입 안전성 | 런타임 오류 방지를 위해 타입 제약 강화 | Java/TypeScript 제네릭 활용, Python 타입 힌트 |
보안 객체 생성 | 권한 또는 정책에 따라 생성 제한 필요 | 보안 컨텍스트에 따른 팩토리 구현 | |
설정 기반 로딩 | 외부 설정 파일/환경변수 기반 객체 생성 | YAML/JSON 설정 + 팩토리 매핑 |
주제와 관련하여 주목할 내용
카테고리 | 주제 | 항목/키워드 | 설명 |
---|---|---|---|
1. 핵심 개념 | Factory Method Pattern | 핵심 원리, 구조, 장점/단점, 실무 적용 | 객체 생성 책임 위임으로 결합도 감소 및 확장성 향상, 실무 전반에 활용 |
생성자 분리 | new 연산자를 팩토리 내부로 숨김 | 클라이언트 코드 단순화 및 SRP 준수 | |
2. 설계 원칙 | SOLID 원칙 | DIP, OCP, SRP | 추상화에 의존하여 확장에 열리고 수정에 닫힌 구조 실현 |
느슨한 결합 | Creator-Product 구조 분리 | 구조적으로 의존성을 줄이고 유연성 확보 | |
3. 생성 패턴 비교 | Simple Factory | 정적 메서드 + 조건문 | 간단하지만 OCP 위반 가능 |
Abstract Factory | 제품군 생성 | 관련 객체군 생성 책임 위임, Factory Method 와 조합 사용 가능 | |
Builder Pattern | 단계적 객체 조립 | 복잡한 객체 조립 시 Factory 와 결합 가능 | |
Prototype Pattern | 객체 복제 기반 생성 | 상태 기반 복제에 적합한 구조 | |
4. 테스트 전략 | 테스트 더블 | Mock, Stub, Fake | 인터페이스 기반 팩토리를 통한 테스트 객체 주입 용이 |
Mock Factory | 테스트 목적 전용 팩토리 구현 | 테스트 시점에 조건별 객체 주입 가능 | |
Test Double 팩토리 | 다양한 테스트 시나리오 구성 | 유지보수 및 테스트 자동화 향상 | |
5. 프레임워크 활용 | DI/IoC 연계 | Spring, Guice, NestJS 등과 통합 | 팩토리 기반 객체 주입 자동화, @Bean, @Factory 활용 가능 |
Constructor Injection | 생성자 기반 DI | 팩토리 생성 객체를 의존성으로 주입 | |
6. 고급 구현 전략 | Generic Factory | 타입 안전성 확보 | 제네릭 기반 팩토리 구현으로 컴파일 타임 검증 가능 |
Reflection-based Factory | 런타임 동적 클래스 로딩 | 유연성 극대화 (단, 보안/성능 유의) | |
Annotation-driven Factory | 메타데이터 기반 자동 팩토리 | 프레임워크나 도구와의 통합에 용이 | |
Registry Factory | 팩토리 맵 등록/검색 구조 | 플러그인 및 모듈 동적 로딩에 활용 | |
Lazy Loading Factory | 지연 초기화 구조 | 리소스 최적화 및 객체 생명주기 관리 | |
Object Pool Factory | 재사용 가능한 객체 풀과 연계 | 반복적 객체 생성을 성능 관점에서 최적화 | |
7. 아키텍처 통합 | 레이어드 아키텍처 | 서비스 레이어 분리 | 객체 생성 로직과 비즈니스 로직 분리 |
플러그인 아키텍처 | 확장점/핫스왑 구조 | 런타임 동적 확장 및 유연성 제공 | |
Hexagonal Architecture | 외부 인터페이스 분리 | 포트 - 어댑터와 팩토리 결합 | |
마이크로서비스 | 팩토리 기반 서비스 생성 | 서비스별 구현체 구성 시 팩토리 패턴 활용 | |
CQRS | 명령 - 쿼리 객체 생성을 분리 | 팩토리로 각 역할 객체를 적절히 분리 생성 | |
Event Sourcing | 이벤트 재구성용 팩토리 구조 | 애그리게이트 재생성 시 활용 | |
CI/CD 통합 | 배포 파이프라인에서 팩토리 적용 | 인프라 리소스/파이프라인 구성 자동화 | |
8. 도메인 주도 설계 | 애그리게이트 팩토리 | 복잡한 도메인 객체 생성 책임 분리 | 도메인 유효성 보장 + 생성 규칙 캡슐화 |
값 객체 팩토리 | 불변 값 객체 생성 | 생성 시점에서 유효성 보장 | |
9. 성능/보안 최적화 | 성능 최적화 | 팩토리 프로파일링, 객체 재사용 | 성능 병목 파악 및 최적화 가능 |
보안 강화 | 보안 컨텍스트 팩토리, 암호화 객체 생성 | 정책 기반 객체 생성 및 권한 기반 흐름 설계 | |
10. 리액티브/비동기 | 비동기 팩토리 | CompletableFuture, RxJava 활용 | 비동기 흐름에서 객체 생성 최적화 |
스트림 기반 생성 | Java Stream, Python Generator 활용 | 대량 데이터 기반 객체 생성에 유리 |
추가 학습 주제
카테고리 | 주제 | 설명 |
---|---|---|
패턴 비교 및 응용 | Simple Factory vs Factory Method | 조건 기반 객체 생성 vs 하위 클래스에 생성 책임 위임 |
Factory Method vs Abstract Factory | 단일 제품 생성 vs 제품군 생성, 구조와 확장성 비교 | |
Factory vs Builder Pattern | 생성 절차 캡슐화 vs 객체 조립 과정 단계화 | |
고급 구현 전략 | Generic Factory Methods | 제네릭을 이용해 타입 안전성과 유연성 강화 |
Reflection-based Factory | 런타임 클래스 로딩을 통한 동적 객체 생성 | |
Annotation-driven Factory | 어노테이션 기반 메타데이터로 자동 팩토리 로직 생성 | |
Static Factory Method | 정적 메서드를 이용한 간단하고 효율적인 팩토리 구현 | |
Parameterized Factory | 매개변수를 통해 다양한 객체를 반환 | |
Registry Factory | 팩토리 객체를 키 기반으로 등록·관리 | |
Lazy Loading Factory | 객체 생성을 요청 시점까지 지연시켜 리소스 최적화 | |
Object Pooling with Factory | 팩토리에서 객체 풀과 연동하여 성능 최적화 | |
아키텍처 통합 | Factory in Hexagonal Architecture | 포트 - 어댑터 구조에서 팩토리를 통한 외부 의존성 분리 |
Microservices Factory Patterns | 마이크로서비스 환경에서 제품군 객체 생성 전략 | |
CQRS with Factory Pattern | 명령/쿼리 분리에 따른 생성 책임 구분 | |
Event Sourcing Factory | 이벤트 기반 애그리게이트 생성을 위한 팩토리 적용 | |
Service Mesh Integration | 런타임 동적 서비스 생성을 위한 팩토리 적용 | |
Infrastructure as Code Factory | IaC 리소스 생성을 위한 팩토리 구조 | |
Factory in CI/CD Pipelines | 배포 자동화 파이프라인에서 팩토리를 활용하여 유연한 구성 적용 | |
설계 원칙 및 구조 설계 | SOLID (OCP, DIP, SRP) | 객체 생성 책임 분리를 통한 의존성 역전과 확장 가능성 확보 |
Creator/Product 병렬 계층 구조 | 상속 계층을 나란히 설계하여 구조적 일관성과 확장성 확보 | |
인터페이스 설계 | Product, Creator 추상화 설계를 통해 구현체 교체 유연성 확보 | |
DI/IoC 결합 | 프레임워크 (Spring/NestJS) 와 통합하여 팩토리 자동 주입 구조 설계 | |
플러그인 구조 | IDE/게임 엔진 등에서 동적 확장을 위한 팩토리 기반 플러그인 아키텍처 | |
Factory + Strategy | 제품 생성 + 로직 결정 구조를 조합하여 런타임 유연성 확보 | |
테스트 전략 | Test Factory Patterns | 테스트용 객체 생성을 위한 팩토리 설계 |
Mock 객체 생성 | 테스트 더블 (Mock/Stub) 와 팩토리 조합 | |
통합 테스트 및 변이 테스트 | 팩토리와 생성 객체를 통합하여 테스트 시나리오 구성 | |
성능/보안 최적화 | Factory Performance Profiling | 팩토리 메서드 호출 성능 분석 |
Memory Management | 팩토리에서 생성된 객체의 생명주기 및 메모리 관리 전략 | |
Secure Factory Implementation | 객체 생성 시 보안 이슈 (예: 인젝션) 방지 설계 | |
Factory Pattern Security Audit | 팩토리 코드의 보안 취약점 검토 및 점검 | |
프로그래밍 언어/도구 | 제네릭/정적 타입 언어 기반 구현 | Java, TypeScript 등에서 타입 안정성 있는 팩토리 구현 |
함수형 프로그래밍 | 고차 함수 기반의 팩토리 구현 방식 (함수 반환, 클로저 활용 등) | |
코드 생성기 | 팩토리/제품 클래스를 자동으로 생성하는 도구 활용 |
용어 정리
카테고리 | 용어 | 설명 |
---|---|---|
핵심 구조 요소 | Product | 생성될 객체의 인터페이스 또는 추상 클래스 |
ConcreteProduct | Product 를 구현한 실제 클래스 | |
Creator | 팩토리 메서드를 선언하는 추상 클래스 또는 인터페이스 | |
ConcreteCreator | Creator 를 상속받아 팩토리 메서드를 오버라이드하고 객체를 생성하는 클래스 | |
Factory Method | 객체 생성을 하위 클래스에 위임하는 메서드로, 다형성 기반 생성 책임 위임 | |
패턴 확장 요소 | Registry Factory | 이름 또는 키 기반으로 등록된 팩토리를 선택하는 방식 |
Parameterized Factory Method | 매개변수를 통해 생성할 객체 타입을 결정하는 팩토리 메서드 | |
Static Factory Method | 정적 메서드로 객체를 생성하는 방식 (생성자 대체) | |
Reflection-based Factory | 리플렉션을 이용해 런타임에 클래스를 로드하고 객체 생성 | |
Factory Chain | 여러 팩토리가 연결되어 복합적인 객체 생성 절차를 처리하는 구조 | |
Aggregate Factory | 도메인 주도 설계 (DDD) 에서 애그리게이트 루트를 생성하는 전용 팩토리 | |
Functional Factory | 함수형 인터페이스와 람다식으로 구현한 팩토리 패턴 | |
Template Factory Method | Template Method 패턴과 결합된 생성 메서드 구조 | |
Annotation-driven Factory | 어노테이션 기반 자동 팩토리 구현 방식 | |
구조적 개념 | Creator Hierarchy | Creator 클래스 계층 구조 |
Product Hierarchy | Product 클래스 계층 구조 | |
Parallel Class Hierarchies | Creator 와 Product 가 병렬 계층 구조를 형성하는 설계 | |
Virtual Constructor | Factory Method 의 별칭, 다형성 기반 생성 방식 강조 | |
설계 원칙 관련 | OCP (Open/Closed Principle) | 확장에는 열려 있고 수정에는 닫혀 있는 원칙 |
DIP (Dependency Inversion Principle) | 구현이 아닌 추상에 의존하도록 설계 | |
Loose Coupling | 클래스 간의 결합도를 낮춰 유연한 설계를 유도 | |
Encapsulation | 객체 생성 로직을 외부에 노출하지 않고 내부로 캡슐화 | |
프로그래밍 기법 | Lazy Initialization | 객체가 실제로 필요할 때까지 생성을 지연하는 최적화 기법 |
Dynamic Loading | 런타임에 클래스 또는 팩토리를 로드하여 동적으로 객체 생성 | |
Object Pool | 생성된 객체를 재사용하여 성능을 높이는 풀링 기법 | |
아키텍처 응용 | Plugin Architecture | 런타임 시 플러그인을 통해 동적 기능 확장을 허용하는 구조 |
테스트 관련 용어 | Test Double | 테스트 용도로 실제 객체를 대신하는 객체 전체 그룹 (Stub, Mock 등 포함) |
Mock Object | 특정 동작을 검증하기 위해 사용하는 테스트용 객체 |
참고 및 출처
- Factory Method – Refactoring.Guru
- Factory Method Design Pattern in Java – GeeksforGeeks
- The Factory Design Pattern in Java – Baeldung
- Factory Design Pattern in Java – DigitalOcean
- Factory method pattern – Wikipedia