[Architecture] Matching MVVM architecture in a modular architecture

2024. 5. 23. 12:12🍏/Swift

Cocoa-MVC에 이어 MVVM 아키텍쳐 적용 방식에 대한 정리입니다.

 

[Architecture] Matching Cocoa-MVC architecture in a modular architecture

https://github.com/chanheki/swifty-proteins현재는 pirvate 이지만 완성 후 public으로 공개 예정 레포지토리입니다.위 프로젝트에서 Modular architecture를 적용하여 설계, 구현하고 있습니다.레이어별로 모듈화를

chanhhh.tistory.com

 

MVVM을 Modular architecture에 적용시 어떤 부분이 어떤 layer에 들어가는지 정리하기 위해서 작성한 글입니다.


모듈러 아키텍처 설계

  1. App Layer
    • 앱의 진입점 및 전체적인 앱 라이프사이클 관리
    • 주요 앱 설정 및 초기화 코드
  2. Feature Layer
    • 사용자 인터페이스 및 사용자의 액션을 처리
    • 뷰(View) 및 뷰와 관련된 로직
    • 각 기능별로 독립적인 UI 및 로직 (AuthFeature, ProfileFeature 등)
  3. Domain Layer
    • 비즈니스 로직과 애플리케이션의 도메인 모델
    • 엔터티, 유스케이스, 리포지토리 인터페이스 등
    • 비즈니스 로직 및 ViewModel 역할
  4. Core Layer
    • 앱의 비즈니스를 포함하지 않는 순수 기능성 모듈
    • 네트워킹, 데이터베이스, 바이오메트릭스 등 (NetworkingModule, DatabaseModule 등)
  5. Shared Layer
    • 공용으로 사용되는 모델, 유틸리티, 확장 기능 등
    • 로깅, 확장 기능, 공통 유틸리티 (UtilityModule, LoggingModule 등)
  6. Shared (UserInterface) Layer
    • 공용 뷰, 디자인 시스템, 리소스 등 UI 요소
    • 디자인 시스템, 공용 뷰 요소 (DesignSystem, LocalizableManager 등)

MVVM과 모듈러 아키텍처의 매칭

Model

  • Domain Layer
    • 도메인 모델 및 비즈니스 로직
    • 엔터티, 유스케이스, 리포지토리 인터페이스 등
    • 예: AuthDomain, ProfileDomain, ProteinDomain
  • Shared Layer
    • 공용 모델 정의
    • 예: ProteinModel 등

View

  • Feature Layer
    • 사용자 인터페이스 및 뷰 로직
    • 뷰를 구성하는 UI 컴포넌트
    • 예: AuthFeature, ProfileFeature, ProteinFeature
  • Shared (UserInterface) Layer
    • 공용 뷰 요소 및 디자인 시스템
    • 예: DesignSystem, LocalizableManager

ViewModel

  • Domain Layer
    • 비즈니스 로직 및 데이터 변환 로직
    • 예: AuthViewModel, ProfileViewModel, ProteinViewModel

매칭 예시

Model (Domain Layer, Shared Layer)

Domain Layer
   |
   |-- AuthDomain
   |-- ProteinDomain
   |
Shared Layer
   |
   |-- ProteinModel
   |-- UtilityModule
   |-- LoggingModule

 

View (Feature Layer, Shared (UserInterface) Layer)

Feature Layer
   |
   |-- AuthFeature
   |-- ProfileFeature
   |-- ProteinFeature
   |
Shared (UserInterface) Layer
   |
   |-- DesignSystem
   |-- LocalizableManager

 

ViewModel (Domain Layer)

Domain Layer
   |
   |-- AuthViewModel
   |-- ProteinViewModel
   |-- ProfileViewModel

 

예제 코드

Model (Domain Layer, Shared Layer) 

// Shared Layer
struct ProteinModel {
    var id: String
    var name: String
}

// Domain Layer
class ProteinDomain {
    // 비즈니스 로직
    func fetchProteins() -> [ProteinModel] {
        // API 호출 등
        return []
    }
}

 

ViewModel (Domain Layer)

class ProteinViewModel {
    private let proteinDomain: ProteinDomain
    
    init(proteinDomain: ProteinDomain) {
        self.proteinDomain = proteinDomain
    }
    
    func getProteins() -> [ProteinModel] {
        return proteinDomain.fetchProteins()
    }
}

 

View (Feature Layer)

class ProteinFeatureViewController: UIViewController {
    private let viewModel: ProteinViewModel
    
    init(viewModel: ProteinViewModel) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let proteins = viewModel.getProteins()
        // proteins 데이터를 사용하여 UI 업데이트
    }
}