Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delegates와 Notification 방식의 차이점에 대해 설명하시오. #14

Open
Do-hyun-Kim opened this issue Sep 6, 2023 · 4 comments
Labels
Swift Swift CS 개념 공부

Comments

@Do-hyun-Kim
Copy link
Contributor

No description provided.

@Do-hyun-Kim Do-hyun-Kim added the Swift Swift CS 개념 공부 label Sep 6, 2023
@Do-hyun-Kim
Copy link
Contributor Author

Delegates와 Notification 방식의 차이점에 대해 설명하시오.

NotificationCenter 이란?

  • NotificationCenter 객체로 부터 어떤 이벤트를 전달 받아 자신에게 등록된 객체들에게 알림을 보내주는 객체이다.
  • Notification 을 발송하면 NotificationCenter 에서 메세지를 전달한 observer를 처리할때 까지 대기한다.
  • NotificationCenter을 통해서 다른 객체간의 데이터를 전달 할 수 있으며, 어플리케이션 어느 곳에도 상호 작용 할 수 있다. 이것은 SingleTone Pattern 의 장점을 사용한 것 같다.

Nofication 이란?

  • NotificationCenter를 통해 저장하기 위한 구조체 이다.
  • observer들에게 전달 되는 구조체 정보가 담겨져 있으며, 해당 알림을 등록한 observer에게만 데이터가 전달된다.

name : 전달하고자 하는 Nofication의 이름(식별자)

object : 발신자 observer에게 보내려는 객체

userInfo: Notification과 관련된 값 또는 객체의 저장소 Extra data를 보내는데 사용 가능

public struct Notification : ReferenceConvertible, Equatable, Hashable {
   /// A tag identifying the notification.
    public var name: Notification.Name

    /// An object that the poster wishes to send to observers.
    ///
    /// Typically this is the object that posted the notification.
    public var object: Any?

    /// Storage for values or objects related to this notification.
    public var userInfo: [AnyHashable : Any]?
}

NotificationCenter 예시 코드

extension Notification.Name {
    static let didDeliveName = Notification.Name("didDeliveName")
    static let didDeliveAge = Notification.Name("didDeliveAge")
}




class Jenny {
    
    func didDeliveName() {
        NotificationCenter.default.post(name: NSNotification.Name.didDeliveName, object: "jenny")
    }
    
    func didDeliveAge() {
        NotificationCenter.default.post(name: NSNotification.Name.didDeliveAge, object: 26)
    }
    
}


class Company {
    
    var employeeName: String?
    var employeeAge: Int?
    
    
    init() {
        NotificationCenter.default.addObserver(self, selector: #selector(didReceiveName(_:)), name: .didDeliveName, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(didReceiveAge(_:)), name: .didDeliveAge, object: nil)
    }
    
    @objc
    private func didReceiveName(_ notification: Notification) {
        
        /// 해당 notification 에서는 jenny object 만 넘겨짐 -> didReceiveName 식별자에게 전달되는 데이터는 "jenny" 이기 떄문
        print("object Data: \(notification.object)")
        
        guard let employeeName = notification.object as? String else { return }
        self.employeeName = employeeName
    }
    
    @objc
    private func didReceiveAge(_ notification: Notification) {
        /// 해당 notification 에서는 26 object 만 넘겨짐 -> didReceiveAge 식별자에게 전달되는 데이터는 26 이기 떄문
        print("object age data: \(notification.object)")
        guard let employeeAge = notification.object as? Int else { return }
        self.employeeAge = employeeAge
    }
    
}


let jenny: Jenny = Jenny()

let myCompany: Company = Company()

jenny.didDeliveName()
jenny.didDeliveAge()
print(myCompany.employeeName)
print(myCompany.employeeAge)

NotificationCenter 장점

  • NotificationCenter 를 통해서 객체들 간의 이벤트 전달을 할 수 있다.
  • 많은 코드작성이 필요 없으며, Swift 내부 Foundation FrameWork 에서 제공되기 때문에 쉽게 구현이 가능하다.

NotificationCenter 단점

  • Notification Post 이후에 대한 정보를 받을 수 없다.
  • Key 값으로 Notification 의 Name과 userInfo 를 서로 맞추기 때문에 컴파일 시에 구독이 잘 되고 있는지, 올바르게 userInfo의 Value를 받아오는지 불가능 하다.
  • NotificationCenter 내부적으로 SingleTone Pattern 을 사용하고 있기 때문에 테스트가 어려울 뿐더러, 객체간의 결합도를 높일 수 있다. 때문에 deinit 시에 removeObserver 해줘야 한다.

Delegates와 Notification 방식의 차이점에 대해 설명하시오.

Delegate는 Protocol 기반으로 정의 하여 사용되기때문에 이벤트를 대신 처리할 객체가 채택하여 사용하게 됩니다. 이처럼 1:1 로 커뮤니케이션 할때 유용하게 사용 할 수 있으며 1:N 으로 커뮤니케이션을 하게 된다면 불필요한 메소드를 구현하게 되어 불필요한 메서드를 구현 하게 될 수 있습니다. 이 뿐만 아닌 Delegate는 Protocol 기반으로 구현되기 때문에 Notification 보다 많은 코드량을 요구 하게 되며 이벤트를 알리고 싶은 경우 NotificationCenter 보다 비효율적인 부분이 있습니다

Notification 같은 경우에는 NotificationCenter 객체를 사용하여 여러 Notification 이 오면 Observer Pattern 을 통해 등록된 Observer 들에게 Notification 을 전달 할 수 있기 때문에 1:N 커뮤니케이션에 유용합니다. 하지만 제 3자 객체 (NotificationCenter) 객체가 필수적으로 필요하며 key값으로 Notification.Name 이 필요하기 때문에 컴파일 시에 구독이 잘 되고 있는지에 대해 확인이 어렵다는 것이 단점이며, SingleTone Pattern을 사용하고 있기 때문에 deinit 시에 removeObserver 를 해줘야 합니다.

📝 참고 사이트

@ronick-grammer
Copy link
Contributor

Notification 이란

이벤트 발생여부를 옵저버를 등록한 객체들에게 알려주는 방법이다.

  • 송신측: NotificationCenter를 통해 특정한 이름(Notification.Name)에 해당하는 이벤트를 송신(post) 한다.
  • 수신측: NotificationCenter를 통해 특정한 이름(Notification.Name에 해당하는 이벤트를 구독하고 수신받는다(addObserver).
// 1) Notification을 보내는 ViewController
class PostViewController: UIViewController {
    @IBOutlet var sendNotificationButton: UIButton!
    
    @IBAction func sendNotificationTapped(_ sender: UIButton) {
        guard let backgroundColor = view.backgroundColor else { return }
      
        // Notification에 object와 dictionary 형태의 userInfo를 같이 실어서 보낸다.
        NotificationCenter.default.post(name: Notification.Name("notification"), object: sendNotificationButton, userInfo: ["backgroundColor": backgroundColor])
    }
}

// 2) Notification을 받는 ViewController
class ObserverViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 옵저버를 추가해 구독이 가능하게끔 함
        NotificationCenter.default.addObserver(self, selector: #selector(notificationReceived(notification:)), name: Notification.Name("notification"), object: nil)
    }
    
    // iOS 9 이상이 아닐 경우에는 removeObserver를 해줘야 함
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    @objc func notificationReceived(notification: Notification) {
        // Notification에 담겨진 object와 userInfo를 얻어 처리 가능
        guard let notificationObject = notification.object as? UIButton else { return }
        print(notificationObject.titleLabel?.text ?? "Text is Empty")
        
        guard let notificationUserInfo = notification.userInfo as? [String: UIColor],
              let postViewBackgroundColor = notificationUserInfo["backgroundColor"] else { return }
        print(postViewBackgroundColor)
    }
}

Delegate와 Notification의 차이점

delegate

  • 장점

    • 매우 엄격한 Syntax로 인해 프로토콜에 필요한 메소드들이 명확하게 명시됨
    • 컴파일 시 경고나 에러가 떠서 프로토콜의 구현되지 않은 메소드를 알려줌
    • 로직의 흐름을 따라가기 쉬움
    • 프로토콜 메소드로 알려주는 것뿐만이 아니라 정보를 받을 수 있음
    • 커뮤니케이션 과정을 유지하고 모니터링하는 제 3의 객체(ex: NotificationCenter 같은 외부 객체)가 필요없음
    • 프로토콜이 컨트롤러의 범위 안에서 정의됨
  • 단점

    • 프로토콜의 메서드를 구현해야하는 등의 많은 줄의 코드가 필요
    • 많은 객체들에게 이벤트를 알려주는 것이 여려움

Notification

  • 장점

    • 많은 줄의 코드가 필요없이 쉽게 구현이 가능
    • 다수의 객체들에게 동시에 이벤트의 발생을 알려줄 수 있음
    • Notification과 관련된 정보를 Any? 타입의 object, [AnyHashable: Any]? 타입의 userInfo로 전달할 수 있음
  • 단점

    • post객체와 observer 객체간의 연결을 위한 제 3의 객체(NotificationCenter) 가 필요
    • key 값으로 Notification의 이름과 userInfo를 서로 맞춰야 하기 때문에 컴파일 시 구독이 잘 되고 있는지, 올바르게 userInfo의 value를 받아오는지 체크가 어려움
    • 배터리와 메모리 성능적인 측면에서 좋지 않음
    • Notificaiton post 이후 정보를 받을 수 없음

무엇을 사용하는 것이 좋을까

다수의 객체에게 이벤트를 알려야 한다면 Notification을 사용하는 것이 좋을 수 있다. delegate 패턴을 사용하게 되면 로직의 흐름을 따라가기 수월하다는 장점이 있지만, 다수의 객체가 이벤트를 받아야 하기 때문에 그 이벤트를 받는 객체의 수만큼 delegate를 생성하고 뷰들의 depth에 따라 넘겨주고 이벤트 위임 처리를 해야하는 어려움이 있다. Notification을 사용하면 광역적으로(전역적으로) 그러할 필요없이 처리해줄 수 있다.

📝 참고 사이트

@Hminchae
Copy link
Member

Hminchae commented Sep 7, 2023

Delegate

  • Delegate 는 보통 Protocol 을 정의하여 사용

Delegate 사용 장점

  • 엄격한 Syntax 로 인해 프로토콜에 필요한 메소드들이 명확하게 명시되어 있음
  • 프로코콜에 정의되어 있는 메소드 들을 구현하지 않으면 컴파일 시 경고 혹은 에러 가 발생함
  • 커뮤니케이션 과정을 유지하고 모니터링하는 제 3의 객체(NotificationCenter) 가 필요하지 않음

Delegate 단점

  • 많은 줄의 코드 가 필요함
  • delegate 설정에 nil이 들어가지 않게 주의해야 함 (crash 주된 원인)
  • 많은 객체들에게 이벤트를 알리는것이 어렵고 비효율적임

Notification

  • NotificationCenter 라는 싱글턴 객체 를 통해서 이벤트들의 발생 여부를 옵저버를 등록한 객체 들에게 Notification 을 post 하는 방식으로 사용함
  • NotificationName 이라는 key 값 을 통해 보내고 받을 수 있음

Notification 사용 장점

  • 많은 줄의 코드 가 필요없이 쉽게 구현 가능
  • 다수의 객체 들에 동시에 이벤트를 전달할 수 있음
  • Notoification 과 관련된 정보를 Any? 타입의 object ,[AnyHashable: Any]? 타입의 userInfo 로 전달 할 수 있음

Notification 사용 단점

  • key 값으로 Notification 의 이름과 userInfo 를 서로 맞추기 때문에 컴파일 시 구독이 잘 되고 있는지 , 올바르게 userInfo 의 value 를 받아오는지 확인이 불가능함
  • Notification 의 post 이후 그에 대한 응답 정보를 받을 수 없음

📝 참조

@vichye-1
Copy link

vichye-1 commented Sep 7, 2023

공통점

  • ViewViewController 와 같이 각각의 객체들 사이에서 소통이 필요할 때 사용한다.
  • 특정 이벤트가 일어나면 원하는 객체에 알려주어 해당되는 처리를 하는 방법
    → 값의 변화를 포착하여 이벤트를 발생시킨다는 공통점이 있다.

Delegation

특징

  • protocol을 정의하여 사용함
  • Delegate로 지정된 객체가 해야 하는 메소드들의 원형을 적어 놓는다
  • Delegate 역할을 하려는 객체는 정의된 protocol을 따르며 원형만 있던 메소드들의 구현을 한다.
  • 어떤 이벤트가 일어났을 시 delegate로 지정한 객체에 알려줄 수 있다.

장점

  • 매우 엄격한 Syntax로 인해 프로토콜에 필요한 메소드들이 명확하게 명시됨
  • 컴파일 시 경고나 에러가 떠서 프로토콜의 구현되지 않은 메소드를 알려줌
  • 로직의 흐름을 따라가기 쉬움
  • 프로토콜 메소드로 알려주는 것뿐만 아니라 정보를 받을 수 있음
  • 커뮤니케이션 과정을 유지하고 모니터링하는 제3의 객체(ex: NotificationCenter 같은 외부 객체)가 필요 없음.
  • 프로토콜이 컨트롤러의 범위 안에서 정의됨

단점

  • 많은 줄의 코드가 필요하다
  • delegate 설정에 nil이 들어가지 않게 조심해야함. 크래시를 일으킬 수 있음
  • 많은 객체들에게 이벤트를 알려주는 것이 어렵고 비효율적임

Notification

특징

  • Notification Center 라는 싱글턴 객체를 통해서 이벤트들의 발생 여부를 옵저버를 등록한 객체들에게 Notification을 post하는 방식으로 사용한다.
  • Notification name이라는 key 값을 통해 보내고 받을 수 있다.

장점

  • 많은 줄의 코드가 필요 없이 쉽게 구현이 가능
  • 다수의 객체들에게 동시에 이벤트의 발생을 알려줄 수 있음
  • Notification과 관련된 정보를 Any? 타입의 object, [AnyHashable: Any]? 타입의 userInfo로 전달할 수 있음

단점

  • key 값으로 Notification의 이름userInfo를 서로 맞추기 때문에 컴파일 시 구독이 잘 되고 있는지, 올바르게 userInfovalue를 받아오는지 체크가 불가능함
  • 추적이 쉽지 않을 수 있음
  • Notification post 이후 정보를 받을 수 없음

어디에 써야할까?

  • 프로토콜로 정의되어 있는 Delegation을 사용하는 것이 좋다.
    • Delegate로 연결을 하면 코드가 읽기도 쉽고 추적이 쉽기때문이다
  • 하지만, 여러 오브젝트들이 동시에 어떤 이벤트를 받고, 이를 모두 반영해야 하는 경우 Notification이 적절할 수 있다.
    • 예: 로그인 상태가 변하여 많은 뷰들을 업데이트해야 하는 경우

정리

DelegationNotification의 가장 큰 차이점은 수신자가 발신자의 정보를 알고 있는지의 여부이다.

Delegation 방식에서는 수신자가 발신자의 정보를 알고 있어야 한다.

하지만 Notification은 단순히 어떤 값의 변화를 포착하여 그에 맞는 이벤트를 발생시켜주면 된다.

Delegate를 사용하여 설계하지 않고 Notification만 가지고 설계를 했다면 다른 사람이 코드를 유지보수할 때 이 Notification을 누가 Subscribe 하고 있는지 알기가 어렵다.

반면 Delegate로 설계를 했다면 해당 Delegate의 이름, 프로토콜의 메서드 등을 통해 어떤 과정에 의해 이벤트 처리 로직이 작동하는지 파악하기 한결 수월하다.

하지만 여러 오브젝트들의 동시에 어떤 이벤트를 받고, 이를 모두 반영해야하는 경우, Notification이 적절할 수 있다. 이에 대한 예로는 로그인 상태가 변하여 많은 뷰들을 업데이트해야 하는 경우가 있다.

📝 참고

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Swift Swift CS 개념 공부
Projects
None yet
Development

No branches or pull requests

4 participants