IT/WEB

클린 아키텍처2

개발자 두더지 2023. 2. 15. 22:03
728x90

일본의 블로그 글을 번역한 포스트입니다. 오역 및 직역, 의역이 있을 수 있으며 틀린 내용은 지적해주시면 감사하겠습니다.

 

 지난 클린 아키텍처1에 이어서 두 번째 그림에 대해 해설하기 위한 포스팅이다. 

 클린 아키텍처1에서 만든 코드를 위와 같은 그림으로 표현하자면 다음과 같다.

 박스 위에 글자가 있는 것이 있는데 <I>는 Interface고, <DS>는 Data Structure(데이터구조체)이다. 대체로 그림대로 재현하고 있지만 유일하게 외부쪽 환경에서 UserCreateViewModel에 의존하는 View가 재현되지 못 했다.

 이번 스크립트는 Presenter가 ViewModel를 다뤄, Consol 표현을 하고 있으므로 원래 View의 역할을 Presenter가 하고 있는 형상이 됐다. 이 부분을 어떻게 하면 첫 번째 그림과 동일한 구조로 만들 수 있을까?

 

 

View의 재현


 ViewModel은 Presenter과 View를 중개하는 것이지만, 아매루도 그 배치 방법에 대해서는 명확하게 정해져 있지는 않는 것 같다.

 서적에 기재되어 있는 내용을 보아도, Presenter는 그 데이터를 적당한 문자열로 포맷 변환하여 View에서 발견할 수 있는 Viewmodel이라는 심플한 데이터 구조에 배치한다라고만 적혀있다.  그럼 왜 그림에서는 Presenter은 View와 나눠져 있을까? 각각의 역할을 생각해보자.

 Presenter의 사양은 OutputData를 ViewModel로 변환하여, 표현 가능한 평식으로 바꾸는 것이며, View의 사양은 그 ViewModel을 표현하는 것이다.

 이러한 이유는 원래 View가 테스트하기 어려우므로, "단순히 표현"하는데에 특화되어 테스트하지 않아도 된다라는 생각이 깔려있다. 이러한 견해가 Humble Object 패턴이다.

 View를 Humble로 하기 위한 패턴으로서 잘 알려진 것이 MVVM패턴과 MVP이 있다.

 

 

MVVM 패턴


 MVVM 패턴은 View와 ViewModel가 쌍방향 바인딩으로 동기화한다. 즉 ViewModel의 값을 변경하면 그 변경이 View에도 전달된다.

 Presenter가 ViewModel의 값을 변경했을 때에 View에 전달하면 그림과 같은 상황이된다. 그러나, MVVM패턴은 쌍방향 바인딩을 실현하기 위한 구조가 필요하므로 프레임워크에 따라 조금씩 다르다.

 

 

MVP 패턴


 MVP패턴은 Model View Presenter 패턴의 약어이다. 또한 MVP패턴은 Humble View패턴과 Supervising Controller패턴 두 종류가 있다. 

 

Humble View

Humble View패턴은 Presenter이 View를 다루는 형태이다. 먼저 View부터. 

public interface ICreateUserView{
  void Update(UserCreateViewModel viewModel);
}

public class ConsoleView : ICreateUserView{
  public void Update(UserCreateViewModel viewModel){
    Console.WriteLine("id:" + viewModel.UserId + " created:" + viewModel.CreatedDate);
  }
}

 이 View를 Presenter가 이용하도록 한다.

public class UserCreatePresenter : IUserCreatePresenter {
  private readonly ICreateUserView view;

  public UserCreatePresenter(ICreateUserView view){
    this.view = view;
  }

  public void Complete(UserCreateOutputData outputData) {
    var userId = outputData.UserId;
    var createdDate = outputData.Created;
    var createdDateText = createdDate.ToString("yyyy/MM/dd");
    var model = new UserCreateViewModel(userId, createdDateText);
    view.Update(model);
  }
}

 이로써 Presenter와 View를 분리하는 것이 가능하다. 그러나, 이 코드를 방금 그림과 같이 표현하면 Presenter에서 화살표가 나아가는 형식이 된다.

 이렇게 보면 원하던 결과와 조금 다르다는 느낌을 받았으므로, 또 다른 패턴을 살펴보자.

 

Supervising Controller 패턴

 이 패턴은 Model의 변경을 View가 Observer 패턴으로 감시하는 형태이다. 감시하기 위해서는 오브젝트를 준비해야한다.

// ViewModel의 변경을 통지하는 용도
public class UserCreateSubject {
  private UserCreateViewModel viewModel;

  public event Action<UserCreateViewModel> UserCreateViewModelUpdated;

  public UserCreateViewModel UserCreateViewModel {
    get => viewModel;
    set {
      viewModel = value;
      UserCreateViewModelUpdated(viewModel);
    }
  }
}

 이 UserCreateSubject를 사용한 경우의 Presenter과 View는 다음과 같다.

public class UserCreatePresenter : IUserCreatePresenter {
  private readonly UserCreateSubject subject;

  public UserCreatePresenter(UserCreateSubject subject) {
    this.subject = subject;
  }

  public void Complete(UserCreateOutputData outputData) {
    var userId = outputData.UserId;
    var createdDate = outputData.Created;
    var createdDateText = createdDate.ToString("yyyy/MM/dd");
    var model = new UserCreateViewModel(userId, createdDateText);
    subject.UserCreateViewModel = model;
  }
}

public class ConsoleView : IDisposable {
  private readonly UserCreateSubject subject;

  public ConsoleView(UserCreateSubject subject) {
    // ViewModel의 변경통지를 서브스크라이브
    subject.UserCreateViewModelUpdated += Update;
  }

  public void Dispose() {
    subject.UserCreateViewModelUpdated -= Update;
  }

  public void Update(UserCreateViewModel viewModel) {
    Console.WriteLine("id:" + viewModel.UserId + " created:" + viewModel.CreatedDate);
  }
}

 이벤트가 발생하여 데이터를 주고받으므로, 다음의 그림과 같이 됐다고 봐도 좋을 것 같다. 

 

 

Presenter와 View에 대해서 정리


 View와 연결되는 부분에 대해서 자세히 언급되어 있지 않다. 이와 관련해서는 경우에 따라 프론트의 구현이 크게 바뀌는 경우가 많기 때문에 주제로 삼기에는 방대하기 때문일거라고 생각된다.

 가장 중요한 것은 OutputData에 프론트를 위한 데이터가 포함되는 것이 아닌, OutputData에서 Presenter로 이동하여 프론트를 위한 데이터를 만들어 주는 부분이다. 

 그외의 다른 부분에 대해서는 서적 클린 아키텍처를 직접 참고하는 것이 좋을 것 같다.


참고자료

https://qiita.com/nrslib/items/a5f902c4defc83bd46b8#%E3%82%82%E3%81%86%E4%B8%80%E3%81%A4%E3%81%AE%E5%9B%B3

 

728x90

'IT > WEB' 카테고리의 다른 글

Atomic Design을 그만두고 디렉토리 구조를 바꾼 이야기  (0) 2023.07.30
[Spring] @Autowired  (0) 2023.07.09
클린 아키텍처1  (0) 2023.02.13
좋지 않은 Repository 패턴(안티패턴)  (0) 2023.02.02
SPA, SSR, SSG는 무엇인가?  (0) 2023.01.24