seong_hye, the developer

Swift) 디자인 패턴에 대해 정리하기 본문

IOS

Swift) 디자인 패턴에 대해 정리하기

seong_hye 2023. 2. 7.

 

📘Swift - 디자인 패턴

반복되는 문제를 재사용 가능한 구조로 해결해주는 아키텍처적 가이드

Swift에서 사용되는 디자인 패턴은 소프트웨어 설계의 모범 사례

iOS 앱 개발에서 특히 많이 쓰이며, Swift 언어의 특성과 잘 맞도록 함수형/구조체 기반으로도 진화해 옴


🔹디자인 패턴의 분류

디자인 패턴은 일반적으로 다음 3가지로 분류됨

분류 설명
생성 (Creational) 객체 생성과 관련된 패턴
구조 (Structural) 클래스 / 객체의 조합 구조를 효율적으로 구성
행위 (Behavioral) 객체 간의 커뮤니케이션 패턴

🔹Swift에서 자주 사용되는 디자인 패턴 

🔍 싱글톤 패턴 (Singletion)

오직 하나의 인스턴스만 존재해야 할 때 사용 (ex. 네트워크 매니저, DB 등)

class NetworkManager {
	static let shared = NetworkManager()
    private init() {}
    
    func fetchData() { ... }
}

 

🔍 팩토리 패턴 (Factory)

객체 생성 로직을 분리해서 유연한 인스턴스 생성이 가능하게 함

protocol Animal {
	func sound() -> String
}

class Dog: Animal {
	func sound() -> String { "멍멍" }
}

class Cat: Animal {
	func sound() -> String { "야옹" }
}

enum AnimalType {
	case dog, cat
}

class AnimalFactory {
	static func create(type: AnimalType) -> Animal {
    	switch type {
        case .dog: return Dog()
        case .cat: return Cat()
    	}
    }
}

 

🔍 옵저버 패턴 (Observer)

객체의 상태 변화에 따라 다른 객체들이 반응하게 하는 패턴

Swift에서는 Combine, NotificationCenter, @Published, @ObservedObject 등이 해당 역할을 함

class ViewModel: ObservableObject {
	@Published var count = 0
}

 

🔍 델리게이트 패턴 (Delegate)

책임을 다른 객체에게 위임하는 패턴

UIKit에서 가장 많이 사용하는 패턴

protocol MyDelegate: AnyObject {
	func didUpdate(value: Int)
}

class Sender {
	weak var delegate: MyDelegate?
    
    func update() {
    	delegate?.didUpdate(value: 42)
    }
}

 

🔍 전략 패턴 (Strategy)

알고리즘을 캡슐화해서 런타임에 선택할 수 있게 함

protocol PaymentStrategy {
	func pay(amount: Double)
}

struct CardPayment: PaymentStrategy {
	func pay(amount: Double) { print("카드로 \(amount)원 결제")}
}

struct CashPayment: PaymentStrategy {
	func pay(amount: Double) { print("현금으로 \(amount)원 결제")}
}

class PaymentContext {
	var strategy: PaymentStrategy
    init(strategy: PaymentStrategy) {
    	self.strategy = strategy
    }
    
    func processPayment(amount: Double) {
    	strategy.pay(amount: amount)
    }
}

 

🔍 MVVM 패턴 (Model - View - ViewModel) 

SwiftUI와 가장 궁합이 잘 맞는 구조

- Model : 데이터 / 비즈니스 로직

- ViewModel: 상태 / 로직을 가공해 View에 전달

- View: 화면

// Model
struct CounterModel {
	var count: Int
}
// ViewModel
struct CounterViewModel: ObservableObject {
	@Published private var model = CounterModel(count: 0)
    
    var countText: String {
    	"현재 숫자: \(model.count)"
    }
    
    func increment() { model.count += 1 }
    func decrement() { model.count -= 1 }
    func reset() { model.count = 0 }
}
// View
struct ContentView: View {
	@StateObject private var viewModel = CounterViewModel()
    
    var body: some View {
    	VStack(spacing: 20) {
        	Text(viewModel.countText)
            	.font(.largeTitle)
            
            HStack {	
            	Button(" + ") {
                	viewModel.increment()
                }
                Button(" - ") {
                	viewModel.decrement()
                }
                Button(" reset ") {
                	viewModel.reset()
                }
            }
        }
        .padding()
    }
}

🔹디자인 패턴 사용 시 유의점

포인트 설명
구조체 중심 사고 클래스를 꼭 쓸 필요가 없을 땐 struct 우선 고려
값 타입 vs 참조 타입 상태 공유가 필요 없으면 struct, 필요하면 class 사용
Combine / Swift Concurrency 옵저버 / 리액티브 패턴은 Combine이나 async/await로 대체 가능
간단한 건 함수로 전략 패턴 같은 건 클로저로 대체 가능 ( () -> Void )

 

Comments