Skip to content

Project Architecture

Hyun Sik Yoo edited this page Nov 29, 2022 · 2 revisions

1. 아키텍처 패턴

2. 디렉토리 구성

image

  • services: API 통신하는 역할을 하는 서비스들이 모여있는 디렉토리입니다.
  • uilts: 앱에서 사용하는 유틸성 함수들이 모여있는 디렉토리입니다.
  • models: 데이터 클래스입니다. dto 디렉토리와 presentation 디렉토리로 나눠져있습니다.
    • dto: 서버에서 받는 응답 데이터와 1:1 맵핑되는 모델입니다.
    • presentation: 사용자들에게 보여지는 화면에서 사용되는 모델입니다. dto 모델이 presentation으로 변경되어 사용됩니다.
  • managers: Analytics등 서드파티를 연결해주거나 외부에서 관리해주거나 앱 내에서 유틸성 함수들을 하나의 클래스 단위로 묶어 관리하는 매니저들의 집합입니다.
  • resources: 폰트, 이미지, 로띠등의 리소스 파일들이 속한 디렉토리입니다.
  • extensions: 앱 내에서 사용되는 익스텐션들을 별도로 모아둔 디렉토리입니다.
  • domains: 앱에서 사용자들에게 실제로 보여지는 ViewController, Reactor, View 들이 속한 디렉토리입니다. 화면 접근에 따라 디렉토리가 구분되어있습니다.

3. Boilerplate code

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

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

3-1. TemplateView.swift

  • BaseView를 상속받아서 사용합니다.
final class TemplateView: BaseView {
    private let templateLabel = UILabel()    
    // ...
    
    override func setup() {        // 뷰 추가
        self.addSubviews([self.templateLabel])
        // ...        
    }

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

3-2. TemplateCoordinator.swift

  • 프로토콜 형태로 extension으로 확장시켜서 함수를 구현합니다.
  • Coordinator프로토콜을 채택해서 정의합니다.
protocol TemplateCoordinator: AnyObject, Coordinator {
    func pushDetailViewController()
}

extension TemplateCoordinator {
    func pushDetailViewController() {
        // 네비게이팅 코드 작성!
    }
}

3-3. TemplateReactor.swift

  • 비즈니스로직을 Reactor 형식에 맞춰서 정의합니다.
final class TemplateReactor: Reactor {
    enum Action {
        // 액션 정의
    }
    
    enum Mutation {
        // 뮤테이션 정의
    }
    
    struct State {
        // state 정의
    }
    
    let initialState = State()
    
    func mutate(action: Action) -> Observable<Mutation> {
        // mutate 정의
    }
    
    func reduce(state: State, mutation: Mutation) -> State {
        // reduce 정의
    }
}

3-4. TemplateViewController.swift

  • BaseViewController를 상속받아 정의합니다.
  • 위에서 구현한 Coordinator도 채택시켜서 정의합니다.
final class TemplateViewController: BaseViewController, TemplateCoordinator, View {
    private weak var coordinator: TemplateCoordinator?
    private let templateView = TemplateView()
    private let templateReactor = TemplateReactor()
    
    override func loadView() {
        // 뷰 설정
        self.view = self.templateView
    }
    
    override func viewDidLoad() {
        // 코디네이터 할당
        self.coordinator = self
    }
    
    override func bindEvent() {
        // 단순 이벤트 바인딩시키는 곳입니다.
    }
    
    func bind(reactor: TemplateReactor) {
        // 리액터 바인딩 시키는 곳입니다.
    }
}