프로젝트 구조에 대해 어떻게 생각하시나요?

안녕하세요. 눈팅만 하다 글을 쓰는 건 이번이 처음이네요.

저는 초급 C# 개발자입니다. 입사한 회사에서 외주로 맡긴 프로그램이 닷넷으로 개발된 탓에 얼떨결에 C#에 입문했다 보니 배워야 할 것과 공부해야 할 것이 투성이네요.

최근에는 WPF와 MVVM 패턴에 대해 고민하고 있습니다. 특이한 구조를 가진 MVVM 패턴이 재미있고 신기하면서도, 대학에서 곁다리로 c만 얕게 배웠던 저에게는 그만큼 낯설기도 하네요.

그 중에서도 MVVM을 엄격하게 구현할 때 프로젝트 구조를 어떻게 구성할 것인가, 특히 특정 모듈의 뷰모델과 뷰를 어떤 방식으로 분리할 것인가는 생각해 볼 점이 많은 것 같아 다른 개발자분들과 의견을 나누고 싶습니다.

예를 들어 하나의 프로그램 안에서 그림판 기능을 하는 모듈과 메모장 기능을 하는 모듈이 있을 때, 크게는 이 프로그램의 프로젝트 구조를 어떻게 구성할 것인지, 작게는 모듈별 구조를 어떻게 구성할 것인지입니다.

아래는 제가 생각한 방안들입니다.

  1. View를 포함한 모듈을 메인 프로젝트와 분리하되, 각 모듈의 View와 ViewModel을 동일 프로젝트에서 관리한다.

그림판과 메모장 모듈의 UI 및 로직을 메인 프로젝트와 분리하되, 각 모듈의 뷰와 뷰모델은 동일한 프로젝트 안에서 함께 관리되는 구조입니다. 물론 각 뷰모델과 뷰는 분리되어 있어야겠죠. 프로젝트 구조는 다음과 같을 수 있겠네요.

  • MyProgram.Paint
  • MyProgram.Notepad
  • MyProgram

프로그램의 메인 View는 MyProgram 프로젝트 내에 있겠지만, 각 모듈을 구성하는 View는 각 모듈 프로젝트 안에 존재합니다. 메인 프로젝트에서는 UI를 구성하면서 각 모듈의 View를 가져오는 방식으로 사용하게 될 겁니다.

  1. 별도의 프로젝트에서 UI를 구성하고, 각 모듈별 프로젝트에서 로직을 담당한다.

UI를 별개 프로젝트에서 관리하고, 각 모듈 UI마다 해당하는 모듈의 ViewModel을 바인딩하는 방식입니다. 프로젝트는 아래와 같이 만들 수 있을 것 같습니다.

  • MyProgram.Paint
  • MyProgram.Notepad
  • (MyProgram.Views)
  • MyProgram

개발하기에 따라 View가 메인 프로젝트 안에 존재할 수도 있고 완전히 별개의 프로젝트로 분리될 수도 있고, 혹은 MyProgram.Paint.Views와 같은 방식으로 각 모듈별로 View를 전부 분리할 수도 있겠지만 어쨌든 핵심은 모듈의 View와 로직이 완전히 분리된다는 점입니다.

어쨌든 View와 ViewModel을 별개 어셈블리로 분리할 것인지 여부가 가장 큰 차이점인 것 같습니다.

말인즉슨 모듈화 대상을 로직과 UI를 별개로 볼 것인지, 로직과 UI를 함께 볼 것인지의 관점 차이 같네요. 1의 경우 UI만 갈아치우면 된다지만 어쨌든 전체 프로젝트의 입장에서 보면 한 프로젝트 안에 묶여 있는 것이기도 하니까요. 개발하기에 따라 다르겠지만 UI에 대한 종속성은 로직만 모듈화된 후자가 더 느슨할 것 같네요.

글재주가 적어 횡설수설 했는데 써놓고 보니 결국 취향 차이와 개발 노하우의 문제인 것 같기도 하군요…

좋아요 6

@루나시아 님의 관점을 잘 표현해 올려주셔서 감사합니다. 관련해서 아마 많은 분들이 고민이 있을 것 같아요.

저의 경험으로는 프로젝트 참조 종속을 고려해서 디자인 해보시는게 어떨까 하는데요.

View와 ViewModel 프로젝트 구성

ViewModel은 View를 참조해서는 안됩니다. 구현의 단순함 때문에 다수의 분들이 MVVM으로 구현할 때 이렇게 구성하는데요, 가장 대표적인게 View에 종속성이 있는 클래스를 ViewModel에서 사용하는 경우 입니다. 이렇게 되면 ViewModel이 View에 결합되어서 모듈화를 해치게 되는데요,

이것을 프로젝트 구조로 원천적으로 막는 방법은 View와 ViewModel을 프로젝트로 분리해서 ViewModel이 View 프로젝트를 참조하지 않게 하면 됩니다.

로직의 정의와 View - ViewModel - Model 간의 역할

로직을 화면 동작 기능순수 기능으로 구분하신다면 좀 더 명확하게 프로젝트로 구조화 가능하시지 않을까 합니다. MVVM 관점에서는 화면 동작에 관련된 기능은 View에 배치하는게 좋습니다. 이 관점은 ViewModel - Model은 그대로 두고 다른 UI 프레임워크로 적용하고자 할 때 드러납니다. 화면 관련된 로직은 View에, 순수 기능은 ViewModel 및 Model에 배치하는게 좋습니다.

불필요한 구조화를 살펴봐야 합니다.

MVVM을 적용한 프로젝트라도 대부분 View의 디자인이 바뀌는 경우는 있어도 View의 전체가 바뀌는 경우는 극히 적습니다. 제 기준은 프로젝트 참조 기준에서 큰 틀을 잡고

  • View - ViewModel - Model간 프로젝트 참조
    • View는 ViewModel을 참조
    • View는 Model을 참조
    • ViewModel은 View를 참조하지 않음
    • ViewModel은 Model을 참조
    • Model은 View를 참조하지 않음
    • Model은 ViewModel을 참조하지 않음

이정도의 규칙으로 프로젝트 구조를 잡고 나머지는 느슨하게 진행하는 편입니다. 왜냐하면 프로젝트 진행에 따라 ViewModel의 로직이 Model로 이동하기도 하고 View의 것이 VIewModel로 이동하기도 하거든요

좋아요 7

소중한 조언 감사합니다.

MVVM을 가지고 프로젝트를 개발하는데 있어 가장 중요한 것은 결국 MVVM 본래 목적을 해치지 않도록 프로젝트 구조를 설계하는 것이 관건인 듯합니다. View와 ViewModel을 각각 잘 추상화하고 서로 간의 참조가 발생하지 않도록 해야 MVVM으로 구현하는 의미가 있을 테니까요.

물론 엄격한 MVVM 구현에만 중점을 두느라 오히려 코드 복잡성이 증가하거나 개발 기간이 지나치게 늘어지는 등 주객이 전도되는 일이 있어서도 안되겠죠.

결국은 그 둘 사이에서 본인의 노하우나 개발 여건에 따라 적절한 지점을 찾는 게 중요한 것 같습니다.

좋아요 4

MVVM에 대한 언급만 있고 객체지향에 대한 언급이 없어서 몇자 남깁니다.
저는 MVVM은 Model이 들어가는 순간 객체지향의 확장판이라고 생각합니다.

뷰라는 객체, 뷰모델이라는 뷰를 위한 모델 객체, 그리고 모델 객체…

모델은 객체지향에서 말하는 그런 객체의 기준이므로, MVVM과도 전혀 상관이 없어야하고 그 자체적으로 기능이 캡슐화 되어야할 것입니다.

또한 뷰모델 역시 모델인데 뷰에서 사용되는 모델이라는 느낌으로, 객체지향의 모델과 같지만 뷰의 데이터를 다루는 특수한 모델이라 생각합니다. 이것 역시 뷰와는 무관한 그냥 C# 객체이므로 단위테스트가 가능해야할 것입니다. 개인적으로 뷰모델이 뷰와 의존성을 가장 잘 끊어내는 방법은 우선적으로 단위테스트가 가능하냐 불가능하냐의 여부일 것으로 생각합니다.

뷰모델에서 뷰에 의존하는…Control 이라던지, FrameworkElement 같은 클래스를 참조하고 있으면, 단위 테스트에서는 뷰라는 개념이 없기때문에 테스트가 불가능할 것입니다. 따라서 그냥 콘솔앱에서도 사용할 수 객체로 작성해야만 합니다.

그리고 뷰모델에서 뷰의 요소를 가질 수 없으니 메세지박스나 다이얼로그 같은 것을 제어하는 쪽에서 임의로 띄워줘야할 때 뷰모델에서 그런 행위를 하면 MVVM을 해치므로 뷰모델을 도와주는 객체가 필요할 것입니다. 이걸 service라고 부른다고 생각합니다.

따라서 mvvm을 이루기 위해 여러 객체가 자기 자신의 책임만가지고 일을 하고 의존성을 최소화한다는 면에서 그냥 객체지향이라고 생각합니다.

그리고 또한 말씀하신 부분인,

결국은 그 둘 사이에서 본인의 노하우나 개발 여건에 따라 적절한 지점을 찾는 게 중요한 것 같습니다.

이것 역시 매우 공감합니다.
모든 설계와 개발은 트레이드 오프, 선택의 산물이기 때문입니다.
팀원의 지적능력, 팀원의 객체지향 훈련도, 팀원의 개발지식에 대한 성취감, 프로젝트 완료일 까지 고려해야할 변수는 많을테니까요.

이미 답은 알고 계신 것 같습니다.

좋아요 6

좋은 말씀 감사드립니다.

디자인 패턴의 구현이나 기능 학습뿐만 아니라 말씀해 주신 방법론적인 부분에 대해서도 더 많이 생각해 봐야겠습니다.

좋아요 3

주제가 자유게시판보다는 모두의 Q&A 가 맞을 것 같아서 게시판을 변경해두도록 하겠습니다.

좋아요 4