느슨하게 결합된 구성 요소 간 통신

참고 항목

이 전자책은 2017년 봄에 게시되었으며 그 이후로 업데이트되지 않았습니다. 이 책에는 귀중한 기본 많이 있지만 일부 자료는 구식입니다.

게시-구독 패턴은 게시자가 구독자로 알려진 수신자를 몰라도 메시지를 보내는 메시징 패턴입니다. 마찬가지로 구독자는 게시자를 전혀 알지 못해도 특정 메시지를 수신 대기합니다.

.NET의 이벤트는 게시-구독 패턴을 구현하는데, 이는 컨트롤과 컨트롤을 포함하는 페이지처럼 느슨한 결합이 필요하지 않은 경우 구성 요소 간의 통신 레이어를 위한 가장 간단한 접근 방식입니다. 그러나 게시자 수명과 구독자 수명은 상호 개체 참조에 의해 결합되어 있으며, 구독자 유형에는 게시자 유형에 대한 참조가 있어야 합니다. 이로 인해 특히 정적 이벤트를 구독하는 수명이 짧은 개체 또는 수명이 긴 개체가 있는 경우 메모리 관리 문제가 발생할 수 있습니다. 이벤트 처리기가 제거되지 않은 경우, 구독자는 게시자에 있는 해당 구독자에 대한 참조에 의해 활성 상태로 유지되고, 이로 인해 구독자의 가비지 수집이 방지 또는 지연됩니다.

MessagingCenter 소개

이 클래스는 Xamarin.FormsMessagingCenter 게시-구독 패턴을 구현하여 개체 및 형식 참조로 연결하는 데 불편한 구성 요소 간의 메시지 기반 통신을 허용합니다. 이 메커니즘을 사용하면 게시자와 구독자가 서로 참조하지 않고도 통신할 수 있으므로 구성 요소 간의 종속성을 줄이는 동시에 구성 요소를 독립적으로 개발하고 테스트할 수 있습니다.

MessagingCenter 클래스에서는 멀티캐스트 게시-구독 기능을 제공합니다. 즉, 단일 메시지를 게시하는 여러 게시자가 있을 수 있으며 동일한 메시지를 수신 대기하는 여러 구독자가 있을 수 있습니다. 그림 4-1에서는 이 관계를 보여 줍니다.

Multicast publish-subscribe functionality

그림 4-1: 멀티캐스트 게시-구독 기능

게시자는 MessagingCenter.Send 메서드를 사용하여 메시지를 보내는 한편, 구독자는 MessagingCenter.Subscribe 메서드를 사용하여 메시지를 수신 대기합니다. 또한 구독자는 필요한 경우 MessagingCenter.Unsubscribe 메서드를 사용하여 메시지 구독을 구독 취소할 수도 있습니다.

내부적으로 MessagingCenter 클래스에서는 약한 참조를 사용합니다. 즉, 개체가 활성 상태로 유지되지 않으며 가비지 수집될 수 있습니다. 따라서 클래스가 더 이상 메시지를 받지 않으려는 경우에만 메시지의 구독을 취소해야 합니다.

eShopOnContainers 모바일 앱은 클래스를 MessagingCenter 사용하여 느슨하게 결합된 구성 요소 간에 통신합니다. 앱은 다음 세 가지 메시지를 정의합니다.

  • AddProduct 메시지는 항목이 장바구니에 추가될 때 CatalogViewModel 클래스에 의해 게시됩니다. 그 대가로 클래스는 BasketViewModel 메시지를 구독하고 응답에 따라 장바구니의 항목 수를 증분합니다. 또한 클래스는 BasketViewModel 이 메시지에서 구독을 취소합니다.
  • 사용자가 Filter 카탈로그에서 표시되는 항목에 CatalogViewModel 브랜드 또는 형식 필터를 적용하면 클래스에서 메시지를 게시합니다. 그 대가로 클래스는 CatalogView 메시지를 구독하고 필터 조건과 일치하는 항목만 표시되도록 UI를 업데이트합니다.
  • 메시지는 ChangeTab 클래스가 MainViewModel 새 주문을 성공적으로 만들고 제출한 다음으로 이동할 MainViewModelCheckoutViewModel 게시됩니다. 그 대가로 클래스는 MainView 메시지를 구독하고 내 프로필 탭이 활성화되도록 UI를 업데이트하여 사용자의 주문을 표시합니다.

참고 항목

MessagingCenter 클래스는 느슨하게 결합된 클래스 간 통신을 허용하지만 이 문제에 대한 유일한 아키텍처 솔루션을 제공하지는 않습니다. 예를 들어 뷰 모델과 뷰 간의 통신을 바인딩 엔진과 속성 변경 알림을 통해 수행할 수도 있습니다. 또한 탐색 중에 데이터를 전달하여 두 뷰 모델 간의 통신을 수행할 수도 있습니다.

eShopOnContainers 모바일 앱 MessagingCenter 에서 다른 클래스에서 발생하는 작업에 대한 응답으로 UI에서 업데이트하는 데 사용됩니다. 따라서 메시지는 UI 스레드에 게시되며 구독자는 동일한 스레드에서 메시지를 받습니다.

UI 업데이트를 수행할 때 UI 스레드로 마샬링합니다. 백그라운드 스레드에서 보낸 메시지가 UI를 업데이트해야 하는 경우 Device.BeginInvokeOnMainThread 메서드를 호출하여 구독자의 UI 스레드에서 메시지를 처리합니다.

자세한 MessagingCenter내용은 MessagingCenter를 참조 하세요.

메시지 정의

MessagingCenter 메시지는 메시지를 식별하는 데 사용되는 문자열입니다. 다음 코드 예제에서는 eShopOnContainers 모바일 앱 내에 정의된 메시지를 보여 있습니다.

public class MessageKeys  
{  
    // Add product to basket  
    public const string AddProduct = "AddProduct";  

    // Filter  
    public const string Filter = "Filter";  

    // Change selected Tab programmatically  
    public const string ChangeTab = "ChangeTab";  
}

이 예제에서는 상수를 사용하여 메시지를 정의합니다. 이 방법의 장점은 컴파일 시간 형식 안전성 및 리팩터링 지원을 제공한다는 것입니다.

메시지 게시

게시자는 MessagingCenter.Send 오버로드 중 하나로 구독자에게 메시지를 알립니다. 다음 코드 예제에서는 AddProduct 메시지를 게시하는 방법을 보여 줍니다.

MessagingCenter.Send(this, MessageKeys.AddProduct, catalogItem);

이 예제에서 메서드는 Send 세 개의 인수를 지정합니다.

  • 첫 번째 인수는 보낸 사람 클래스를 지정합니다. 메시지를 받으려는 모든 구독자가 보낸 사람 클래스를 지정해야 합니다.
  • 두 번째 인수는 메시지를 지정합니다.
  • 세 번째 인수는 구독자에게 보낼 페이로드 데이터를 지정합니다. 이 경우 페이로드 데이터는 인스턴스입니다 CatalogItem .

Send 메서드에서는 실행 후 제거(fire-and-forget) 방법을 사용하여 메시지와 페이로드를 게시합니다. 따라서 메시지를 수신하도록 등록된 구독자가 없는 경우에도 메시지가 전송됩니다. 이 경우 보낸 메시지는 무시됩니다.

참고

MessagingCenter.Send 메서드는 제네릭 매개 변수를 사용하여 메시지 배달 방법을 제어할 수 있습니다. 따라서 메시지 ID를 공유하지만 여러 다른 페이로드 데이터 형식을 보내는 여러 메시지를 다른 구독자가 수신할 수 있습니다.

메시지 구독

구독자는 MessagingCenter.Subscribe 오버로드 중 하나를 사용하여 메시지를 받도록 등록할 수 있습니다. 다음 코드 예제에서는 eShopOnContainers 모바일 앱이 메시지를 구독하고 처리하는 AddProduct 방법을 보여 줍니다.

MessagingCenter.Subscribe<CatalogViewModel, CatalogItem>(  
    this, MessageKeys.AddProduct, async (sender, arg) =>  
{  
    BadgeCount++;  

    await AddCatalogItemAsync(arg);  
});

이 예제에서 메서드는 Subscribe 메시지를 구독 AddProduct 하고 메시지 수신에 대한 응답으로 콜백 대리자를 실행합니다. 람다 식으로 지정된 이 콜백 대리자는 UI를 업데이트하는 코드를 실행합니다.

변경할 수 없는 페이로드 데이터를 사용하는 것이 좋습니다. 여러 스레드가 수신된 데이터에 동시에 액세스할 수 있으므로 콜백 대리자 내에서 페이로드 데이터를 수정하지 마세요. 이 시나리오에서는 동시성 오류를 방지하기 위해 페이로드 데이터를 변경할 수 없도록 합니다.

구독자는 게시된 메시지의 모든 인스턴스를 처리할 필요가 없으며 이는 Subscribe 메서드에 지정된 제네릭 형식 인수를 통해 제어할 수 있습니다. 이 예제에서 구독자는 페이로드 데이터가 인스턴스인 클래스에서 CatalogViewModel 보낸 메시지만 받 AddProduct 습니다CatalogItem.

메시지에서 구독 취소

구독자는 더 이상 수신하지 않을 메시지를 구독 취소할 수 있습니다. 이는 다음 코드 예에서 설명한 것처럼 MessagingCenter.Unsubscribe 오버로드 중 하나를 사용하여 달성됩니다.

MessagingCenter.Unsubscribe<CatalogViewModel, CatalogItem>(this, MessageKeys.AddProduct);

이 예제 Unsubscribe 에서 메서드 구문은 메시지를 받기 AddProduct 위해 구독할 때 지정된 형식 인수를 반영합니다.

요약

이 클래스는 Xamarin.FormsMessagingCenter 게시-구독 패턴을 구현하여 개체 및 형식 참조로 연결하는 데 불편한 구성 요소 간의 메시지 기반 통신을 허용합니다. 이 메커니즘을 사용하면 게시자와 구독자가 서로 참조하지 않고도 통신할 수 있으므로 구성 요소 간의 종속성을 줄이는 동시에 구성 요소를 독립적으로 개발하고 테스트할 수 있습니다.