[Swift Apple ] Swift 디자인 패턴 완전 정리

Swift 개발자라면 꼭 알고 있어야 할 디자인 패턴(Design Patterns) 에 대해 알아보겠습니다. 디자인 패턴은 효율적이고 유지보수하기 쉬운 코드를 작성하기 위한 검증된 설계 방법이에요.  이번 글에서는 Swift에서 자주 사용되는 디자인 패턴을 중심으로 개념, 특징, 그리고 실습 예제를 통해 쉽게 이해할 수 있도록 정리해드릴게요!


[Swift Apple ] Swift 디자인 패턴 완전 정리
 [Swift Apple ] Swift 디자인 패턴 완전 정리




🎨 Swift 디자인 패턴 완전 정리

– 효율적인 코드 작성을 위한 필수 설계 전략!


✅ 디자인 패턴이란 무엇인가요?

디자인 패턴(Design Pattern)이란,
반복적으로 발생하는 문제를 해결하기 위한 최고의 설계 방식입니다. 복잡한 소프트웨어를 개발할 때, 문제를 매번 새롭게 해결하기보다는 검증된 설계 방법을 활용하면 더 안정적이고 효율적인 코드를 만들 수 있어요. Swift에서도 다양한 디자인 패턴이 활용됩니다.


🚀 Swift에서 자주 사용하는 디자인 패턴 TOP 7

패턴명

설명

Singleton

하나의 인스턴스만 생성

Delegate

객체 간 의사소통 (이벤트 전달)

MVC

앱 구조를 Model-View-Controller로 분리

Observer

변화 감지 및 알림

Factory

객체 생성을 캡슐화

Strategy

알고리즘을 동적으로 교체

Builder

복잡한 객체 생성 절차 관리




1️⃣ 싱글톤 패턴 (Singleton)


앱 전체에서 하나의 인스턴스만 사용하는 패턴


예제: 설정 관리 클래스

class Settings {
    static let shared = Settings()
    private init() {}

    var theme: String = "Light"
}

Settings.shared.theme = "Dark"

  • 전역 상태 관리에 유용

  • 남용하면 코드가 의존적이 될 수 있으니 주의!




2️⃣ 델리게이트 패턴 (Delegate)


객체 간 소통을 위한 대표적인 패턴

iOS 개발에서 가장 많이 사용되는 패턴!


예제: 다운로드 완료 알림

protocol DownloadDelegate: AnyObject {
    func downloadDidFinish()
}

class Downloader {
    weak var delegate: DownloadDelegate?

    func startDownload() {
        // 다운로드 완료 시
        delegate?.downloadDidFinish()
    }
}

  • 이벤트 전달용으로 사용

  • 반드시 weak 참조로 설정 (순환 참조 방지)





3️⃣ MVC 패턴 (Model-View-Controller)


앱 구조를 세 부분으로 분리해서 관리

구성요소

역할

Model

데이터와 비즈니스 로직

View

화면(UI)

Controller

중간 조율자

Swift의 UIKit 기반 앱은 기본적으로 MVC 구조를 따릅니다.



4️⃣ 옵저버 패턴 (Observer)


상태 변화가 발생하면 자동으로 알림을 보내는 패턴


예제: NotificationCenter 활용

NotificationCenter.default.addObserver(self, selector: #selector(handleEvent), name: .init("EventOccurred"), object: nil)

NotificationCenter.default.post(name: .init("EventOccurred"), object: nil)

  • 데이터 변경 사항을 여러 객체에 알릴 때 유용

  • SwiftUI에서는 @Published, @ObservedObject 등이 이 패턴을 적용한 사례!




5️⃣ 팩토리 패턴 (Factory)


객체 생성 로직을 분리해서 관리하는 패턴


예제:

class AnimalFactory {
    static func createAnimal(type: String) -> Animal {
        switch type {
        case "Dog": return Dog()
        case "Cat": return Cat()
        default: return Animal()
        }
    }
}

  • 객체 생성 방식이 바뀌어도 코드 수정 최소화 가능!




6️⃣ 전략 패턴 (Strategy)


알고리즘을 유연하게 교체할 수 있는 패턴


예제:

protocol PaymentStrategy {
    func pay(amount: Int)
}

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

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

class PaymentContext {
    var strategy: PaymentStrategy
    init(strategy: PaymentStrategy) {
        self.strategy = strategy
    }

    func executePayment(amount: Int) {
        strategy.pay(amount: amount)
    }
}

  • 런타임 중 전략 변경 가능!





7️⃣ 빌더 패턴 (Builder)


복잡한 객체 생성 과정을 단계별로 관리


Swift에서는 주로 메서드 체이닝 방식으로 구현합니다.

class BurgerBuilder {
    private var ingredients: [String] = []

    func addLettuce() -> BurgerBuilder {
        ingredients.append("Lettuce")
        return self
    }

    func addPatty() -> BurgerBuilder {
        ingredients.append("Patty")
        return self
    }

    func build() -> String {
        return "Burger with " + ingredients.joined(separator: ", ")
    }
}

let burger = BurgerBuilder().addLettuce().addPatty().build()
print(burger)  // Burger with Lettuce, Patty


빌더 패턴 (Builder)
빌더 패턴 (Builder)




✏️ 실습 아이디어

  1. 싱글톤 패턴으로 로그인 상태 관리 클래스 만들기

  2. 델리게이트 패턴을 활용한 사용자 입력 이벤트 처리

  3. 팩토리 패턴으로 다양한 UI 버튼 생성기 만들기

  4. 옵저버 패턴으로 설정 변경 감지 시스템 구현

  5. 전략 패턴으로 배송 방법 선택 시스템 설계




✅ 1. 싱글톤 패턴 – 로그인 상태 관리 클래스

class LoginManager {
    static let shared = LoginManager()
    private init() {}

    private(set) var isLoggedIn = false
    private(set) var username: String?

    func login(user: String) {
        isLoggedIn = true
        username = user
        print("🔐 \(user) 로그인 완료")
    }

    func logout() {
        isLoggedIn = false
        username = nil
        print("🔓 로그아웃 완료")
    }
}

// 사용 예시
LoginManager.shared.login(user: "peter")
print(LoginManager.shared.isLoggedIn)  // true
LoginManager.shared.logout()


싱글톤 패턴 – 로그인 상태 관리 클래스
싱글톤 패턴 – 로그인 상태 관리 클래스





✅ 2. 델리게이트 패턴 – 사용자 입력 이벤트 처리

protocol InputDelegate: AnyObject {
    func didSubmitInput(_ text: String)
}

class TextField {
    weak var delegate: InputDelegate?

    func simulateUserTyping(text: String) {
        print("⌨️ 입력됨: \(text)")
        delegate?.didSubmitInput(text)
    }
}

class ViewController: InputDelegate {
    func didSubmitInput(_ text: String) {
        print("📥 사용자가 입력한 값 처리 중: \(text)")
    }
}

// 사용 예시
let inputField = TextField()
let vc = ViewController()
inputField.delegate = vc
inputField.simulateUserTyping(text: "Hello Swift!")



델리게이트 패턴 – 사용자 입력 이벤트 처리
델리게이트 패턴 – 사용자 입력 이벤트 처리




✅ 3. 팩토리 패턴 – 다양한 UI 버튼 생성기

import UIKit

protocol UIButtonStyle {
    func makeButton() -> UIButton
}

class PrimaryButton: UIButtonStyle {
    func makeButton() -> UIButton {
        let button = UIButton()
        button.setTitle("Primary", for: .normal)
        button.backgroundColor = .systemBlue
        return button
    }
}

class DangerButton: UIButtonStyle {
    func makeButton() -> UIButton {
        let button = UIButton()
        button.setTitle("Danger", for: .normal)
        button.backgroundColor = .systemRed
        return button
    }
}

class ButtonFactory {
    static func createButton(style: String) -> UIButton {
        switch style {
        case "primary": return PrimaryButton().makeButton()
        case "danger": return DangerButton().makeButton()
        default: return UIButton()
        }
    }
}

// 사용 예시 (UIViewController 내부라면)
let button = ButtonFactory.createButton(style: "danger")
// button을 화면에 추가




✅ 4. 옵저버 패턴 – 설정 변경 감지 시스템

class Settings {
    static let shared = Settings()

    var observers: [SettingsObserver] = []

    var darkMode: Bool = false {
        didSet {
            observers.forEach { $0.didChangeDarkMode(to: darkMode) }
        }
    }

    func addObserver(_ observer: SettingsObserver) {
        observers.append(observer)
    }
}

protocol SettingsObserver {
    func didChangeDarkMode(to enabled: Bool)
}

class ViewController: SettingsObserver {
    func didChangeDarkMode(to enabled: Bool) {
        print("🌙 다크모드 변경됨 → \(enabled ? "ON" : "OFF")")
    }
}

// 사용 예시
let vc = ViewController()
Settings.shared.addObserver(vc)
Settings.shared.darkMode = true


옵저버 패턴 – 설정 변경 감지 시스템
옵저버 패턴 – 설정 변경 감지 시스템




✅ 5. 전략 패턴 – 배송 방법 선택 시스템

protocol DeliveryStrategy {
    func deliver(item: String)
}

class FastDelivery: DeliveryStrategy {
    func deliver(item: String) {
        print("🚚 빠른 배송으로 \(item) 보내기")
    }
}

class StandardDelivery: DeliveryStrategy {
    func deliver(item: String) {
        print("📦 일반 배송으로 \(item) 보내기")
    }
}

class DeliveryContext {
    var strategy: DeliveryStrategy

    init(strategy: DeliveryStrategy) {
        self.strategy = strategy
    }

    func send(item: String) {
        strategy.deliver(item: item)
    }
}

// 사용 예시
let context = DeliveryContext(strategy: FastDelivery())
context.send(item: "아이폰")  // 🚚 빠른 배송으로 아이폰 보내기

context.strategy = StandardDelivery()
context.send(item: "맥북")   // 📦 일반 배송으로 맥북 보내기



전략 패턴 – 배송 방법 선택 시스템
 전략 패턴 – 배송 방법 선택 시스템




🎯 요약

실습 주제

핵심 설계 패턴

주요 포인트

로그인 상태 관리

싱글톤(Singleton)

앱 전역에서 상태 공유

사용자 입력 처리

델리게이트(Delegate)

사용자와 UI 간 이벤트 전달

UI 버튼 생성

팩토리(Factory)

스타일별 생성 분리

설정 변경 감지

옵저버(Observer)

상태 변화 감지 및 반응

배송 전략 선택

전략(Strategy)

런타임에 알고리즘 교체



🎯 마무리하며

디자인 패턴은 단순히 “형식적인 코드”가 아닙니다. 효율적이고 유지보수하기 쉬운 구조를 만들기 위한 개발자의 지혜입니다! 


Swift 개발에서 자주 쓰이는 패턴을 잘 익히면:

  • 코드 재사용성 향상

  • 확장성 있는 앱 설계

  • 팀 프로젝트에서 일관된 코드 유지

  • 문제 해결 속도 향상


댓글 쓰기