Skip to content

Project Module Architecture

Hyunsik-Yoo(유현식) edited this page Aug 26, 2023 · 2 revisions

1. Module Architecture

  • v4부터는 Tuist를 사용한 모듈화 아키텍처를 적용합니다.
V4 Module 설계도
V4 Module 설계도

1-1 Module별 역할

  • Networking: API 통신을 담당하는 모듈입니다. URLSession과 async/await을 사용하여 구현되어있습니다.
    • RequestProvider: API 요청을 담당합니다.
    • ResponseProvider: RequestProvider에서 요청한 API의 응답을 받아 디코딩하여 결과값을 추출하는 기능을 제공합니다.
    • NetworkLogger: 요청과 응답을 개발하면서 보기 쉽게 로깅하는 역할을 합니다.
  • DesignSystem: 가슴속 3천원에서 사용하는 디자인 리소스, 컴포넌트로 구성됩니다.
  • Common: 피처를 구현하면서 기본적으로 필요한 Base 클래스, 각종 Extension이 포함되어있고 유틸성 매니저들이 포함됩니다.
    • Base: 공통으로 처리하는 Base클래스들이 위치합니다.
    • Extension: 사용하기 편하도록 만들 extension들이 위치합니다.
    • Manager: Extensions과 마찬가지로 사용하기 편하도록 만든 매니저가 포함됩니다.
  • Features: 하위 모듈들을 사용하여 하나의 피처를 구성한 단위 모듈입니다. V4에서는 탭 단위로 피처 모듈을 구성하려합니다.
  • APP: 가슴속 3천원 앱 본체고 피처모듈만 포함하도록 구성합니다.

2. 아키텍처 패턴

  • MVVM with Combine
  • Code base로 UI 구현 (SnapKit)
  • Coordinator Pattern 사용 (프로토콜과 익스텐션을 사용해 라이트하게 사용중)
  • Combine을 사용한 ViewModel로 V4버전 타겟으로 변경중입니다. V3까지는 ReactorKit을 사용했습니다.

2. 피처모듈 디렉토리 구성

image
  • Domains: 피처모듈에서 구현되는 화면 단위의 디렉토리들의 묶음입니다.
  • Models: 피처모듈에서 사용하는 Presentation Model들이 정의되는 디렉토리입니다.

3. Boilerplate code

한 화면에 대해서 사용되는 Boilerplate code는 다음과 같습니다.

  • View.swift: UIComponent와 Layout을 정의합니다.
  • ViewController.swift: View와 ViewModel을 바인딩시켜주는 역할을 합니다.
  • ViewModel.swift: 비즈니스로직에 해당하는 코드들만 존재합니다.
  • Coordinator.swift: 네비게이션(화면이동) 역할을 합니다. (Deprecated. 제거하려고 합니다.)

3-1. TemplateView.swift

  • Common 모듈의 BaseView를 상속받아서 사용합니다.
import Common

final class TemplateView: BaseView {
    private let templateLabel = UILabel()    
    // ...
    
    override func setup() {        // 뷰 추가
        self.addSubviews([self.templateLabel])
        // ...        
    }

    override func bindConstraints() {        // 오토레이아웃 설정
        self.templateLabel.snp.makeConstraints {
            // ...
        }
    }
    
    // Optional
    func bind(model: Model) {
        // 모델에 따라 변경되는 뷰가 있다면 여기서 변경시킵니다.
    }
}

3-2. TemplateViewModel.swift

  • 비즈니스로직을 ViewModel 형식에 맞춰서 정의합니다.
  • Common모듈의 BaseViewModel을 상속받아 정의합니다.
import Common

final class TemplateViewModel: BaseViewModel {
    struct Input {
        // Input 정의
    }
    
    struct Output {
        // Output 정의
    }
    
    struct State {
        // state 정의
    }
    
    override func bind() {
    // Input -> Output 비즈니스 로직 정의
    }
}

3-3. TemplateViewController.swift

  • Common 모듈의 BaseViewController를 상속받아 정의합니다.
  • 위에서 구현한 Coordinator도 채택시켜서 정의합니다.
import Common

final class TemplateViewController: BaseViewController, TemplateCoordinator {
    private let templateView = TemplateView()
    private let viewModel = TemplateViewModel()
    
    override func loadView() {
        // 뷰 설정
        self.view = self.templateView
    }
        
    override func bindViewModelInput() {
        // ViewModel의 Input으로 바인딩시키는 곳입니다.
    }

    override func bindViewModelOutput() {
        // ViewModel의 Output을 뷰에 바인딩시키는 곳입니다.
    }
}