[아키텍처] Modular(1)

한지민·2022년 3월 31일
0

아키텍처

목록 보기
6/7
post-thumbnail

프로젝트 구성

Package Manager

CocoaPods, Carthage, SPM 등 종속성 관리를 위한 툴들로
각 기능들을 모듈로 분리 시 관리가 필요해 사용할 예정이다.

여기서는 모듈들을 Swift Package로 구성하고,
이를 SPM을 활용해 로컬에서 불러와 사용하는 형태로 구성하고자 한다.

Swift Package에 대한 자세한 사항은 여기를 확인해주세요.

구조

대략적으로 다음과 같이 구성될 예정이다.

APP - 프로젝트
Search, SearchDetail - 각 기능 모듈
Core, Network, Entity - 그 외 공통 모듈

구현

프로젝트 및 모듈 생성

프로젝트를 생성하고 SPM을 통해 local 모듈들을 추가하면 다음과 같은 구조가 된다.

모듈들은 Packages라고 하는 그룹 아래에 속하고, 프로젝트에서 직접 수정이 가능하다.
또한 SPM에서 각 모듈의 의존성을 확인하고 관리하게 된다.

APP

AppDelegate와 같은 앱 기본 구현사항과 각 모듈의 Navigator 구현을 기본 프로젝트에서 담당하게 된다.
Navigator는 각 모듈에서 정의된 Step에 따라 다른 모듈로 이동하게 된다.

//  GithubSearchNavigator.swift
class GithubSearchNavigator: NavigatorProtocol {
    var navigationViewController: UINavigationController?
    func navigateTo(navigation: Step) {
        let navigation: GithubSearchStep = navigation as! GithubSearchStep
        switch navigation {
        case .Detail(let repository):
            let navigator = GithubSearchDetailNavigator()
            let rootViewController = navigationViewController
            navigator.navigationViewController = rootViewController
            let  viewController = GithubSearchDetailInitializer().start(with: navigator, repository: repository)
            rootViewController?.pushViewController(viewController, animated: true)
            break
        }
    }
}

Core

코어에서 구현해야 할 것은 각 Scene마다 가져야할 기본적인 형태에 대한 정의이다.

모듈로 구분시에 각 기능 모듈은 서로 존재를 모르기 때문에 Navigation에 대한 주입이 필요하고,
이를 위한 Navigator Protocol을 정의한다.

//  NavigatorProtocol.swift
public protocol Step {}
public protocol NavigatorProtocol {
    var navigationViewController: UINavigationController? { get set }
    func navigateTo(navigation: Step)
}
//  BaseViewModel.swift
public protocol BaseViewModelProtocol {
    var navigator: NavigatorProtocol? { get }
}

Network

네트워크 통신에 필요한 기초를 담당하는 모듈로 여기선 Moya를 활용해 provider를 미리 생성해두었다.

//  Network.swift
import Moya

public class Network {
    public static let sharedInstance = Network()
    private init() {}
    public var provider = MoyaProvider<MultiTarget>()
}

Entity

모듈 간 공통적으로 사용하는 Entity에 대한 모듈이다.

기능 모듈

기본 MVVM 구조에 네트워크를 위한 API와 Modular 구조에 필요한 Navigation, Initailzer를 추가했다.
또한 Swift Package에서 인식을 하기 위해 Resources 폴더에 리소스들을 모아놓았다.

  • Model
  • View
  • ViewModel
  • API
  • Navigation
  • Resources
  • Initializer

Model & ViewModel & View

모듈에서 필요한 MVVM 구조를 작성한다.

API

Moya를 기반으로 해당 기능에서 사용하는 API들을 정의한다.

//  GithubSearchAPI.swift
enum GithubSearchAPI {
    case fetchRepositories(text: String)
}

extension GithubSearchAPI: TargetType {
...
}

모듈에서 필요한 Step을 정의한다.

//  GithubSearchStep.swift
public enum GithubSearchStep: Step {
    case Detail(repository: Repository)
}

Initializer

외부에서 모듈을 사용하기 위한 시작점이다.
해당 모듈에 필요한 정보를 이곳에서 받아 처리한다.

//  GithubSearchInitializer.swift
public struct GithubSearchInitializer {
    public init() {}
    public func start(with navigator: NavigatorProtocol) -> UIViewController {
        let viewController = UIStoryboard(name: "GithubSearch", bundle: Bundle.module).instantiateViewController(withIdentifier: "SearchViewController") as! SearchViewController
        let viewModel = SearchViewModel()
        viewModel.navigator = navigator
        viewController.viewModel = viewModel
        return viewController
    }
}

결과

전체 코드는 깃허브에 있습니다.

profile
IOS Developer

1개의 댓글

comment-user-thumbnail
2022년 4월 1일

좋은 정보 감사합니다.

답글 달기