MVVM, Clean Architecture

o2k_iOS·2025년 2월 19일

내부의 Circle에서는 외부의 Circle에 대해서 몰라야 합니다.

의존성은 외부 → 내부 의 흐름으로 진행되어야 합니다.

  • 외부는 쉽게 변경이 될 수 있는 저수준의 컴포넌트
  • 내부로 갈수록 쉽게 변경 되지 않는 고수준의 컴포넌트

Ex) MVVM 패턴 기준

  • Presentaion(UI, Controller)과 같이 자주 변경되는 요소 및 Action이 전달되는 요소 → 외부
  • Domain(UseCase, Entitiy)과 같이 쉽게 변경되지 않는 비즈니스 로직 → 내부
  • Data(Network, DB)와 같이 쉽게 변경이 되는 것 → 외부
  1. Presentation
    1. View
    2. ViewModel
  2. Domain
    1. Buisness Logic
  3. Data
    1. Data Repositories

MVC에서 View Controller가 너무 많은 일을 하게 되어 Massive View Controller가 되듯이

MVVM에서도 View Model이 너무 많은 일을 하게 되어 Massive View Model이 될 수 있기 때문에

Clean Architecture를 적용합니다.

  1. 역할 분리를 세밀하게 합니다
  2. 테스트가 용이해 집니다
  3. 변경에 대처하기 용이해 집니다

→ 확장성, 유지보수성, Testable 한 코드를 작성할 수 있게 됩니다.

https://youtu.be/--qKOhdgJAs?si=GXWAZdaZDuTMcucF

  • Model
    • UI와 완전히 독립적
    • App이 무엇을 수행 하는지 설명하는 모든 Data + Logic
    • 실제 기능, 역할
  • View
    • 항상 Model의 현재 상태를 반영
    • 사실상 상태가 존재하지 않음 (@State는 예외)
    • App이 사용자에게 어떻게 보이는지를 담당
  • ViewModel
    • Model에서의 변경 사항을 감지하고 이를 View에 전달
    • View에 필요한 데이터를 제공하고 변환
    • 사용자가 View에서 발생시키는 이벤트를 처리하여 반환

ViewModel - View는 데이터 바인딩을 하는 방법

  • Combine 프레임워크
  • Custom Observable Class
    class Observable<T> {
        
        var closure: ((T) -> Void)?
        
        var value: T {
            didSet {
                closure?(value)
            }
        }
        
        init(_ value: T) {
            self.value = value
        }
         
        // bind에 작성한 구문이 바로 동작하게끔 하고 싶은 경우
        // bind 바로 작동 O
        func bind(closure: @escaping (T) -> Void) {
            //closure(value)이 없는 경우 초기값을 바인딩하지 않음.
            closure(value) // init
            self.closure = closure
        }
        // bind가 바로 작동 X
        func lazyBind(closure: @escaping (T) -> Void) {
            self.closure = closure
        }
    }
profile
느려도 조금씩 성장

0개의 댓글