Factory — 객체 생성을 팩토리 메서드에 위임하는 생성 패턴입니다. 모바일 개발에서 Factory Method와 Abstract Factory는 ViewModel, NetworkClient, Repository 및 기타 종속성을 생성하는 데 사용됩니다. Factory는 인스턴스화 로직을 분리하여 구현 변경을 단순화합니다. 자세한 내용은 — Refactoring Guru: Factory Method를 참조하세요.
핵심 사항
Factory — GoF 카탈로그의 생성 디자인 패턴입니다. 주요 아이디어: 객체 생성 로직을 클라이언트 코드에서 별도의 메서드나 클래스로 분리하는 것입니다. 클라이언트는 인터페이스나 추상 클래스로 작업하고, 구체적인 구현은 팩토리가 생성합니다. 이는 의존성 역전 원칙을 구현합니다: 클라이언트는 구체 클래스에 의존하지 않고 추상화에만 의존합니다.
두 가지 변형 Factory: Factory Method와 Abstract Factory. Factory Method — 서브클래스가 객체를 생성하기 위해 재정의하는 클래스의 단일 메서드. Abstract Factory — 관련 객체 그룹을 생성하기 위한 팩토리 메서드군을 가진 인터페이스. 두 변형 모두 동일한 문제를 해결합니다: 클라이언트가 직접 new MyClass()를 호출하지 않고 팩토리에 타입이나 매개변수에 따라 객체 생성을 요청합니다.
Factory vs new() — 직접 객체 생성은 코드를 구체적 구현에 강하게 결합시킵니다. Factory는 계층을 추가합니다: 구현 변경 시 모든 클라이언트가 아닌 팩토리만 수정하면 됩니다. 모바일 개발에서 Factory는 ViewModel(ViewModelProvider.Factory), 네트워크 클라이언트(Retrofit.create()), 목록 어댑터 및 직렬화 팩토리 생성에 적극적으로 사용됩니다. DI 컨테이너(Dagger, Koin)는 자동으로 팩토리를 생성합니다.
Factory Method — 프로토콜이나 추상 클래스에 선언된 메서드로, 특정 타입의 객체를 반환합니다. 서브클래스가 메서드를 구현하여 구체적인 인스턴스를 생성합니다. Swift에서는 프로토콜의 정적 메서드나 기본 클래스의 메서드가 될 수 있습니다. Kotlin에서는 — 팩토리 메서드가 있는 companion object나 추상 클래스의 open fun입니다. 이 패턴은 파서, 오류 팩토리 및 쿼리 빌더를 만드는 데 널리 사용됩니다.
protocol PaymentGateway {
func processPayment(amount: Decimal) async throws -> PaymentResult
}
final class StripeGateway: PaymentGateway { /* ... */ }
final class ApplePayGateway: PaymentGateway { /* ... */ }
enum PaymentType { case stripe, applePay }
final class PaymentFactory {
// Factory Method
static func create(type: PaymentType) -> PaymentGateway {
switch type {
case .stripe: return StripeGateway()
case .applePay: return ApplePayGateway()
}
}
}
// 사용법
let gateway = PaymentFactory.create(type: .stripe)
Kotlin 버전의 Factory Method는 타입을 제한하기 위해 companion object나 sealed class를 사용합니다. Sealed class는 when 분기가 모든 가능한 타입을 포괄하도록 보장합니다 — 컴파일러가 완전성을 확인합니다. 이는 팩토리가 빌드 플레이버나 구성에 따라 다른 Repository나 DataSource 구현을 생성하는 Android 프로젝트에서 일반적입니다.
sealed class PaymentType {
object Stripe : PaymentType()
object ApplePay : PaymentType()
}
interface PaymentGateway {
suspend fun processPayment(amount: BigDecimal): PaymentResult
}
class PaymentFactory {
companion object {
fun create(type: PaymentType): PaymentGateway = when (type) {
PaymentType.Stripe -> StripeGateway()
PaymentType.ApplePay -> ApplePayGateway()
}
}
}
Abstract Factory — 구체 클래스를 지정하지 않고 관련되거나 상호 의존적인 객체군을 생성하기 위한 패턴입니다. 클라이언트는 추상 팩토리 인터페이스로 작업하며, 이는 각 제품군을 생성하는 메서드를 정의합니다. 구체 팩토리가 인터페이스를 구현하고 특정 변형의 객체를 생성합니다. 예를 들어, iOS용 UI 컴포넌트 팩토리는 UIButton, UILabel, UITableView를 생성하고, Android용은 Button, TextView, RecyclerView를 생성합니다.
Abstract Factory vs Factory Method — Factory Method는 상속을 통해 하나의 객체 타입을 생성하고, Abstract Factory는 구성을 통해 객체군을 생성합니다. Factory Method는 서브클래스에서 재정의되고, Abstract Factory는 프로토콜을 통해 여러 팩토리 메서드를 제공합니다. Abstract Factory는 종종 여러 Factory Method를 포함합니다. 모바일 개발에서 Abstract Factory는 플랫폼 종속 컴포넌트, 테마 디자인 및 데이터베이스 팩토리에 사용됩니다.
| 특성 | Factory Method | Abstract Factory |
|---|---|---|
| 제품 수 | 하나 | 군(여러 개) |
| 메커니즘 | 상속(override) | 구성(프로토콜/인터페이스) |
| iOS 예제 | PaymentFactory.create() | iOS/Android용 UIComponentFactory |
| Android 예제 | ViewModelProvider.Factory | ThemeFactory: 버튼, 텍스트, 카드 생성 |
| 유연성 | 간단한 서브클래스 교체 | 완전한 군 교체 |
실제 사례 Android의 Abstract Factory — 단일 DatabaseFactory 인터페이스를 통한 다양한 데이터베이스 타입(SQLite vs Room) 구현. 팩토리는 DAO 객체, 마이그레이션 및 연결 풀을 생성합니다. iOS에서는 — 다양한 환경(Development/Staging/Production)을 위한 서비스 팩토리. Abstract Factory는 직접적으로 거의 사용되지 않습니다 — 그 기능은 DI 컨테이너(Dagger Module, Swinject Assembly)가 담당합니다.
Swift Factory는 프로토콜과 정적 메서드를 통해 구현됩니다. Factory 프로토콜은 추상 타입을 반환하는 create() 메서드를 선언합니다. 구체 팩토리가 프로토콜을 구현하고 필요한 객체를 생성합니다. Swift는 단순한 경우 별도의 팩토리 클래스가 필요하지 않습니다 — enum이나 struct의 정적 메서드로 충분합니다. 복잡한 시나리오에서는 DI 주입이 있는 Factory 프로토콜이 사용됩니다.
iOS SDK의 Factory — 많은 시스템 팩토리: UIStoryboard.instantiateViewController(withIdentifier:), NSKeyedUnarchiver.unarchivedObject(ofClass:from:), JSONDecoder().decode(_:from:). 개발자는 ViewController(StoryboardFactory), 서비스(ServiceFactory) 및 데이터 모델용 팩토리를 만듭니다. Factory Method는 VIPER 및 Clean Swift 아키텍처에서 화면 모듈을 생성하는 데 적극적으로 사용됩니다.
Factory + DI — 현대적인 대안: DI 컨테이너(Swinject, Factory)가 등록된 타입에 대한 팩토리를 자동 생성합니다. 컨테이너는 객체 생성 레시피를 저장하고 종속성을 해결합니다. Factory 라이브러리(github.com/hmlongco/Factory)는 자동 주입에 @Injected(.service)를 사용합니다. DI 팩토리는 한 줄로 전체 모듈을 교체하여 테스트됩니다: container.register { MockService() }.
Android Factory — 전형적인 예: 매개변수로 ViewModel을 생성하는 ViewModelProvider.Factory. Google은 자동 ViewModel 팩토리 생성을 위해 Hilt 사용을 권장합니다 — @HiltViewModel 애너테이션이 자동으로 Factory를 생성합니다. 단순 객체의 경우 create() 또는 invoke() 메서드가 있는 companion object가 사용됩니다. Kotlin에서 invoke 연산자는 팩토리를 함수처럼 호출할 수 있게 합니다: Factory(param).
Jetpack Compose의 Factory — 팩토리는 상태와 효과를 생성하는 데 사용됩니다. remember { Factory.create() }는 첫 번째 렌더링 시 객체를 생성하고 composable의 수명 동안 유지합니다. Compose의 ViewModel은 viewModel()을 통해 생성됩니다 — 이는 Hilt가 관리하는 팩토리입니다. Compose에서는 DI와 Compose StateManager가 객체 생성을 처리하므로 팩토리가 명시적으로 덜 사용됩니다.
Factory vs Hilt — Dagger/Hilt는 컴파일 타임에 자동으로 팩토리를 생성합니다. @Module + @Provides는 Factory Method를 대체하고, @Binds는 Abstract Factory를 대체합니다. 수동 팩토리는 런타임 동적 구현 선택(A/B 테스트, 기능 플래그)에 여전히 유효합니다. 정적 종속성의 경우 Hilt가 객체 생성을 완전히 자동화합니다 — 개발자는 인터페이스와 애너테이션만 작성합니다.
자주 묻는 질문
Factory Method는 상속을 통해 하나의 객체 타입을 생성합니다 — 서브클래스가 팩토리 메서드를 재정의합니다. Abstract Factory는 구성을 통해 객체군을 생성합니다 — 팩토리 인터페이스가 여러 제품의 메서드를 선언합니다. Factory Method는 더 간단하고, Abstract Factory는 플랫폼 종속 또는 테마별 컴포넌트에 더 유연합니다.
Factory는 런타임 동적 구현 선택(A/B 테스트, 기능 플래그, 다른 등급에 다른 API)에 적합합니다. DI(Hilt, Dagger, Koin)는 정적 종속성에 선호됩니다 — 생성과 주입을 자동화합니다. Factory와 DI는 상호 배타적이지 않습니다: DI는 모듈 내에서 Factory를 사용할 수 있습니다.
Factory는 프로토콜을 통해 팩토리를 교체하여 테스트됩니다. 테스트에서는 동일한 프로토콜을 구현하고 Mock 객체를 반환하는 TestFactory가 생성됩니다. 정적 Factory 메서드의 경우 테스트가 더 복잡합니다 — DI 컨테이너나 swizzling이 필요합니다. 테스트 용이성을 유지하기 위해 항상 Factory에 프로토콜을 사용하는 것이 좋습니다.
ViewModelProvider.Factory는 Jetpack의 인터페이스로, 사용자 정의 매개변수로 ViewModel을 생성할 수 있습니다. 팩토리가 없으면 ViewModel은 리플렉션을 통해 생성되며 빈 생성자만 가질 수 있습니다. Factory는 매개변수(리포지토리, 애플리케이션 컨텍스트)를 받아 ViewModel 생성자에 전달합니다. Hilt는 @HiltViewModel에 대해 자동으로 Factory를 생성합니다.
Factory는 개방-폐쇄 원칙을 구현합니다: 시스템은 확장에 열려 있지만(새 구현이 팩토리에 추가됨) 수정에는 닫혀 있습니다(클라이언트 코드는 변경되지 않음). 새 제품 타입을 추가하려면 모든 클라이언트가 아닌 팩토리만 수정하면 됩니다. 이것이 직접 객체 생성에 비해 Factory의 주요 이점입니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.