Viemodel  <->interface <- service (Iservice상속)   

 물론 그림은 어떻게 하냐에 따라 화살표가 다르나, TestVPro 기준.

(인터페이스에는 Service에서 구현해야할 메서드 또는 이벤트, 즉 ViewModel에서 interface로부터 간접적으로 불러올  Service의 메서드 또는 이벤트 정의)

 

이벤트를 사용하는 목적은 viewmodel이 service의 인터페이스로부터 데이터를 받을 목적으로 이벤트 정의

 

이벤트를 꼭 사용할 필요없다. 그저 di에서 해당 service의 메서드를 반환타입을 지정해서 반환값을 받으면 되기 때문이다(pull, 정방향)

 

이벤트는  push(역방향)이다. 이벤트를 사용하는 이유는 서비스에서 값을 제공해서 그 값을 여러 클래스 쪽에 보낼 때 사용하면 된다. (구독기반, 각 클래스마다 해당 이벤트를 등록해야하며, 사전조건으로 그 클래스들은 동일 인터페이스 상속 받아야함. )

 

그림을 보다시피 DI 기반 IOC 가 정립되며, IOC를 이루기 위한 하기 설명 참고.

 


App.xaml.cs에서 Di등록 후(인터페이스, 해당인터페이스상속받는 서비스 && 뷰모델)

Viewmodel에서 Iservice타입을 주입 
해당 Iservice메서드호출시 (service가 정의한메서드진입)

Service가 비즈니스로직처리후 데이터를 모델에 저장 및 IService에 정의한 해당 모델타입 이벤트핸들러 정의된걸 사용해 이벤트를 invoke진행. 물론 데이터들은 해당 모델타입의 이벤트핸들러 인자로 넣음.
(해당 모델은 프로젝트별 공용사용 시 Core에 넣기.
뷰모델도 이벤트함수에서 매개변수가 해당 모델타입으로 데이터를 받는 용도)

사전준비로서  뷰모델에선 생성자에 di로 iservice의 이벤트핸들러에 메서드를 생성 및 로직처리 가정하에 
Service에서 발생한 invoke로인해 뷰모델의 이벤트 메서드가 호출되어짐

결과적으로 인터페이스를 기반으로 ioc가 일어나 mvvm위배가아님.

 

서비스와 뷰모델이 직접 서로 데이터주고받는게아닌 인터페이스가 중재자로 간접적으로 데이터주고받기때문에 ioc임(DI기반)

 

 


전체 구조 요약

ViewModel <--> IService (Interface) <-- Service : IService
  • ViewModel은 직접 Service를 알지 못하고, 오직 IService만 참조
  • Service는 IService를 구현하고, 내부에서 비즈니스 로직 수행 및 이벤트 발생
  • ViewModel은 IService의 이벤트를 구독해 데이터를 간접 수신

이벤트 흐름 설명

1. App.xaml.cs에서 DI 등록

services.AddSingleton<IService, Service>();
services.AddSingleton<ViewModel>();


2. ViewModel 생성자에서 IService 주입 및 이벤트 구독

public ViewModel(IService service)
{
    _service = service;
    _service.DataReceived += OnDataReceived;
}

private void OnDataReceived(MeasurementModel model)
{
    // ViewModel에서 데이터 처리
}

 

3. Service 클래스 내부에서 데이터 처리 후 이벤트 발생

class Service : IService
{

  public event Action<MeasurementModel> DataReceived;

 ...

  private void ReceiveData()
  {
      var data = new MeasurementModel(...);
      DataReceived?.Invoke(data);
  }
  
  ...
}

 


IOC 구조로서 타당한 이유

  • ViewModel은 Service에 직접 의존하지 않고, 인터페이스에 의존
  • Service가 이벤트로 데이터를 ViewModel에 "푸시(Push)"
  • ViewModel은 해당 이벤트를 구독만 함으로써, 관심사 분리(Separation of Concerns) 유지

이 방식의 장점


장점 설명
테스트 용이 Mock<IService>를 주입하면 ViewModel 단위 테스트 가능
느슨한 결합 ViewModel ↔ Service 간 직접 참조 없음 (IoC 실현)
재사용성 IService 구현체만 바꿔 끼워도 ViewModel은 변경 불필요
MVVM 원칙 준수 ViewModel은 View의 논리만 다루고, 데이터 전달은 외부에 위임
 

 그림 보충 설명

  • 그림에서 양방향 화살표는 ViewModel이 IService를 호출하고, IService는 이벤트로 데이터를 다시 돌려주기 때문
  • Service → Interface는 구현(구현체), ViewModel → Interface는 사용(소비자)

결론

“ViewModel은 인터페이스를 통해 서비스 로직에 접근하고, 서비스는 인터페이스에 정의된 이벤트를 통해 데이터를 푸시하여 MVVM 구조와 IoC 원칙을 모두 만족시킨다.”

'C#(.Net) > WPF' 카테고리의 다른 글

다양한 뷰전환 방식  (0) 2025.08.20
CustomControl에서의 PART_ 네이밍 규칙  (1) 2025.08.04

+ Recent posts