[내일배움캠프 48일차] 디자인 패턴

NH·2025년 5월 9일

내일배움캠프

목록 보기
48/62
post-thumbnail

디자인 패턴

디자인 패턴이란


  • 일반적인 개발 상황에서 접하게 되는 문제들을 해결하기 위한 설계 패턴
  • 개발 과정에서 설계에 대한 지침서

디자인 패턴의 특징


  • 이미 증명된 솔루션이기 때문에 개인적으로 생각해낸 해결 방안보다 사용할 근거가 충분
  • 디자인 패턴은 약속되어 있음. 👉 그렇기 때문에 사용했을 때, 아예 모르는 사람이 나의 코드를 처음 보게 되더라도, 디자인 패턴에 대한 이해만 있다면 더 수월하게 코드를 이해 가능

디자인 패턴 종류


1. 싱글톤 패턴 (Singleton)

싱글톤 패턴이란, 특정 클래스의 인스턴스가 앱 전체에서 단 하나만 존재하며, 앱 전역에서 모두 접근할 수 있도록 하는 디자인 패턴을 말한다.

싱글톤 패턴 사용에 적합한 상황

  • 개별적인 인스턴스를 생성할 필요가 없으며
  • 단 하나의 인스턴스를 재활용해서 여러 곳에서 활용할 때

싱글톤 패턴을 자주 사용하는 예시

  • 위치 서비스
  • 로깅 서비스
  • UserDefaults 전체 관리 클래스
  • 네트워크 중복 로직 관리 클래스

싱글톤 예시

  • 전반적인 관리의 역할을 하는 클래스를 일반적으로 Manager 라는 키워드를 붙여서 네이밍합니다.

    import Foundation
    
    // 싱글톤 클래스.
    class Adam {
    		// shared 를 통해서 싱글톤 접근.
       static let shared = Adam()
       var mbti = "ENTJ"
       var age = 29
       
       // 클래스 생성 자체를 막아버리기 위해 init 을 private 으로 선언.
       private init() {}
       
       func printInfo() {
           print("[Adam Info]")
           print("mbti: \(mbti)")
           print("age: \(age)")
       }
    }
    
    // shared 를 통해서 싱글톤 클래스 사용.
    Adam.shared.printInfo()
    Adam.shared.mbti = "INTJ"
    Adam.shared.age = 30
    Adam.shared.printInfo()
  • static let shared 라는 싱글톤 접근점을 선언
  • private init() {} 으로 클래스를 생성하지 못하도록 막음.
    • 싱글톤의 인스턴스는 오직 shared 객체 하나만 살아있도록 구현.
  • static 키워드가 붙으면, 가장 처음 호출될때 메모리에 올라감.
    • 앱이 종료될때까지 한번도 불리지 않는다면 메모리에 Adam 싱글톤은 한번도 올라가지 않게 됨.
  • Adam.shared 가 불리고 난 뒤에는 앱이 종료될때까지 메모리 위에 올라가있는 상태.
    • 그 뒤로 Adam.shared 를 호출하는 모든 부분은 단 하나의 인스턴스를 바라보고 접근하게 됨.
  • 따라서 싱글톤 패턴을 사용하려면, 메모리적으로 손해를 보지 않는지 반드시 고려해야 함.


2. 델리게이트 패턴 (Delegate)

  • Delegate : 대리자, 대신 수행하는 사람, 위임자.
  • 어떤 일을 대신 처리하게 하는 패턴
  1. protocol 에 누군가 대신 처리해주길 바라는 내용을 작성하며 넘김.
  2. 그리고 그 일을 위임받은 객체는 그 일을 구체적으로 대신 처리.
  • UIKit 내부에서도 많이 사용하는 디자인 패턴.

델리게이트 패턴 예제

import Foundation

// 바리스타 프로토콜.
// 이 프로토콜을 만족하는 클래스는 커피를 만드는 책임을 갖습니다.
protocol Barista: AnyObject {
    func makeCoffee() -> String
}

// 커피숍 클래스
class CoffeeShop {
	  // 델리게이트로 바리스타 프로토콜을 만족하는 클래스를 찾습니다.
    weak var delegate: Barista?
    
    init() {}
    
    // 커피숍이 커피를 제공(serve) 하는 메서드를 갖고있습니다.
    // 사실 내부를 살펴보면 delegate 가 커피를 만들고 (makeCoffe),
    // 커피숍은 그 결과를 사용합니다.
    func serveCoffee() {
        guard let coffee = delegate?.makeCoffee() else { return }
        print("주문하신 \(coffee) 나왔습니다.")
    }
}

// 커피숍 인스턴스 생성
let coffeeShop = CoffeeShop()

// 바리스타 프로토콜을 만족하는 Adam 클래스.
// 프로토콜을 만족하기 때문에 커피숍의 델리게이트가 될 수 있습니다.
class Adam: Barista {
    func makeCoffee() -> String {
        "아이스 아메리카노"
    }
}

let adam = Adam()

// 커피숍의 커피 만드는 위임자를 아담으로 설정.
coffeeShop.delegate = adam

// 커피숍에서 위임자를 사용해서 커피 제공 성공.
coffeeShop.serveCoffee()

델리게이트 패턴의 특징

  • 커피숍 입장에서는 구체적으로 어떤 클래스가 커피를 제공해줄지는 상관이 없음.(= 구체 타입을 몰라도 됨.)
    Barista 프로토콜을 만족하는 누군가 대신 수행해주길 바라며 프로토콜의 메서드를 사용.
  • 프로토콜로 타입을 지정했기 때문에, 수정에 용이한 구조가 됨.
    커피를 다른 방식으로 만들고 싶어졌을때, 위임자만 교체하면 된다는 뜻.
    따라서 커피숍 클래스 내부 코드의 수정이 필요하지 않음

아래 코드 확인

import Foundation

protocol Barista: AnyObject {
    func makeCoffee() -> String
}
    
class CoffeeShop {
    weak var delegate: Barista?
    init() {}
    func serveCoffee() {
        guard let coffee = delegate?.makeCoffee() else { return }
        print("주문하신 \(coffee) 나왔습니다.")
    }
}

let coffeeShop = CoffeeShop()

class Adam: Barista {
    func makeCoffee() -> String {
        "아이스 아메리카노"
    }
}

let adam = Adam()

coffeeShop.delegate = adam
coffeeShop.serveCoffee()

class Eve: Barista {
    func makeCoffee() -> String {
        "카페라뗴"
    }
}

let eve = Eve()

coffeeShop.delegate = eve
coffeeShop.serveCoffee()
  • 아이스 아메리카노와 카페라떼를 만들어주는 서로 다른 객체에 위임
  • 필요한 메뉴에 따라서 위임 받은 객체가 커피를 만들면 됨.

UIKit 의 델리게이트 패턴 활용 예시

UITableViewDelegatetableView(_:heightForRowAt:) 메서드.

  • “테이블 뷰 셀의 높이 설정하기” 라는 작업을
  • UIViewController 에서 tableView.delegate = self 라는 코드를 작성함으로써 내가 그 위임자가 되겠다고 선언.
  • tableView(_:heightForRowAt:) 메서드 안에 실질적으로 높이를 설정하는 코드 작성.

3. 옵저버 패턴 (Observer)


출처: https://refactoring.guru/ko/design-patterns/observer

옵저버 패턴이란

  • 어떤 객체의 상태가 변화할 때, 관찰하는 구독자들에게 이벤트를 전달시켜주는 디자인 패턴
  • 이 때 이벤트를 발행하는 객체를 Publisher(=Observable, = Subject)
  • 구독자를 Observer (= 관찰자)
  • 이벤트 발행 시 곧바로 구독자가 이벤트를 받아보고 그에 맞는 행동을 취함.

  • 이벤트 발생 시, Publisher 가 구독자에게 바로 전달해주는 방식
  • 이벤트 발생 시, 구독한 구독자에게만 정보를 전달
  • Publisher는 구독자가 누구인지 구체적인 타입으로 몰라도 되고,
    구독자들만 이벤트를 발행하는 주체를 구체적으로 알고 있는 느슨한 결합구조
  • iOS 개발에서는 보통 ViewData 를 구독하며, Data 의 변화가 일어났을 때 그 DataView 에 적용시키는 구조로 많이 활용.
profile
iOS 개발 블로그

0개의 댓글