3d 그래픽스 개발 시 MVVM, MVC 두 아키텍처가 필요했던 이유

박두팔이·2025년 9월 4일
0

ELECTRON

목록 보기
6/6

Vue와 3D 뷰어, MVVM과 MVC로 두 마리 토끼 잡기

이번 프로젝트에서 Electron과 Vue.js를 사용하여 복잡한 3D 뷰어 애플리케이션을 개발했다. 이 과정에서 반응형 UI와 무거운 3D 렌더링 로직을 어떻게 효과적으로 분리하고 관리할 수 있을지에 대한 깊은 고민이 있었다.

MVVM(Model-View-ViewModel)과 MVC(Model-View-Controller)를 함께 사용하는 하이브리드 아키텍처를 채택했습니다. 이 글에서는 내가 왜 이런 구조를 선택했고, 어떻게 두 아키텍처를 성공적으로 결합했는지 공유하고자 한다.

전체 애플리케이션 구조: MVVM

애플리케이션의 전체적인 구조는 MVVM 패턴을 따른다. Vue.js의 핵심 사상과 가장 잘 맞기 때문이다. 데이터 바인딩을 통해 View와 ViewModel을 연결하여 상태 관리를 매우 효율적으로 할 수 있다.

  • View: src/renderer/views 폴더의 .vue 파일들이다. 사용자가 직접 보는 UI를 담당하며, ViewModel의 상태를 화면에 그리고 사용자 입력을 ViewModel에 전달한다.

  • ViewModel: src/renderer/viewModels 폴더의 Pinia 스토어(...Store.ts)와 Command객체(...Command.ts)들입니다. View를 위한 상태와 비즈니스 로직을 가진다. View는 ViewModel의 데이터를 구독하고, 변경이 생기면 자동으로 업데이트된다.

  • Model: src/main/models의 데이터 구조 및 각종 서비스 로직을 포함한다. 이 프로젝트에서는 3D 뷰어 모듈 전체가 하나의 거대한 모델 역할을 하기도 한다.

    src/renderer/
      ├── views/          # View (Vue Components)
      ├── viewModels/     # ViewModel (Pinia Stores, Commands)
      └── models/         # Model (Data Structures)
    		```
     

3D 뷰어 모듈: MVC 패턴으로 캡슐화

프로젝트의 가장 핵심적이고 복잡한 부분은3D 뷰어다. 이 부분은
독립적인 컴포넌트처럼 작동하며, 내부 로직이 매우 복잡하다.

이러한 복잡성을 관리하기 위해 나는 뷰어 모듈 내부에 MVC 패턴을 적용했다. 이를 통해 뷰어의 데이터, UI, 그리고 제어 로직을 명확하게 분리할 수 있었다.

  • Model: repositories와 services가 이 역할을 한다.
    • propRepository.ts: 3D 객체(prop)의 상태 데이터를 저장하고 관리하는 저장소다.
    • propService.ts: Repository의 데이터를 가져와 실제 비즈니스 로직(객체 변환, 투명도 조절 등)을
      수행한다.
  • View: VTK.js와 같은 렌더링 라이브러리가 실제 View의 역할을 합니다. SceneManagerAdapter 클래스가 씬(Scene)을 관리하며 View를 제어합니다.

  • Controller: controllers 폴더의 클래스들이다. 외부로부터의 요청을 받아 Model(Service)과 View(SceneManager)의 업데이트를 조정하는 오케스트레이터 역할을 한다.

    이 구조를 통해 데이터의 흐름이 Controller -> Service -> Repository로 명확해지며, 각 부분의 책임이 분리되어
    테스트와 유지보수가 용이해졌다.

두 아키텍처의 연결고리: Facade 패턴

그렇다면 MVVM으로 구성된 외부 애플리케이션은 어떻게 MVC로 만들어진 3D 뷰어와 소통할까?

정답은 바로 Facade 패턴에 있다. 저희는 viewerFacade.ts라는 클래스를 만들어 3D 뷰어 모듈의 유일한 출입구(entry point)로 삼았다.

  1. ViewModel(Pinia 스토어 등)은 오직 ViewerFacade에만 의존한다.
  2. ViewerFacade는 ViewModel으로부터 받은 요청을 내부의 적절한 Controller에게 위임한다.
  3. Controller는 Service(Model)를 호출하여 비즈니스 로직을 처리하고, 필요하다면 View를 업데이트한다.

이러한 구조 덕분에 ViewModel은 3D 뷰어의 복잡한 내부 구현(Controller, Service, Repository 등)을 전혀 알 필요가 없다. 그저 ViewerFacade가 제공하는 단순하고 명확한 API만 호출하면 된다.

결론

복잡한 애플리케이션을 만들 때 하나의 아키텍처 패턴만을 고집할 필요는 없다. 애플리케이션의 UI영역에는 MVVM을, 독립적이고 복잡한 3D 뷰어 모듈에는 MVC를 적용하는 하이브리드 전략을 선택했다. 그리고 Facade 패턴을 이용해 두 아키텍처를 완벽하게 분리하고 연결했다.

이러한 접근 방식은 다음과 같은 장점을 가져다주었다.

  • 명확한 관심사 분리(SoC): 각 모듈이 자신의 역할에만 집중할 수 있다.
  • 향상된 유지보수성: 특정 기능 수정 시 영향을 받는 범위가 명확하고 제한적이다.
  • 높은 확장성: 새로운 기능을 추가하거나 기존 기능을 변경하기 용이하다.
profile
기억을 위한 기록 :>

0개의 댓글