iOS / Tuist를 활용한 iOS 프로젝트 모듈화 전략

iOS 앱개발 공부

목록 보기
29/31

✒️ 도입

iOS 앱의 규모가 커지면 단일 타겟 프로젝트는 한계에 부딪힌다.
수천 개의 파일이 하나의 프로젝트 파일(.xcodeproj)에 얽히게 되면, 작은 수정에도 프로젝트 전체를 다시 인덱싱해야 하며 Git 협업 시 프로젝트 파일의 'Merge Conflict'는 개발자의 정신을 피폐하게 만든다.

이를 해결하기 위한 근본적인 해결책이 바로 모듈화(Modularization)다.
프로젝트를 기능 단위로 쪼개어 독립적인 라이브러리로 관리하는 이 방식은 현대 iOS 개발의 표준이 되고 있다.


🛠️ Tuist란 무엇인가?

Tuist 는 Swift로 Xcode 프로젝트를 정의하고 생성하는 명령행 도구(CLI)다.
기존 방식은 Xcode UI를 통해 설정을 변경하고 그 결과가 바이너리 형태의 .xcodeproj에 저장되었으나, Tuist는 Project.swift라는 Swift 파일을 통해 프로젝트 구조를 기술한다.

Tuist의 주요 이점

  • 프로젝트 파일 제거: .xcodeproj를 깃에 올리지 않아도 된다. tuist generate 명령 한 번이면 언제든 동일한 환경을 재구성할 수 있다.
  • 코드 기반 설정: 모든 설정이 Swift 코드로 관리되므로 리뷰가 쉽고 재사용이 가능하다.
  • 의존성 시각화: tuist graph를 통해 복잡한 모듈 간의 의존성 지도를 한눈에 확인할 수 있다.

🧩 모듈화(Modularization) 아키텍처 설계

효율적인 모듈화를 위해서는 계층 구조(Layering)가 명확해야 한다.
대표적인 Micro-features 아키텍처를 응용한 레이어 설계는 아래와 같다.

  1. App Layer: 최종 앱 타겟. 각 Feature 모듈을 조합하여 실행 가능한 앱을 구성한다.
  2. Feature Layer: 기능 단위 모듈 (예: Login, Home, Search). 비즈니스 로직과 UI를 포함하며, 가급적 독립적으로 실행(Demo App)될 수 있어야 한다.
  3. Core Layer: 앱의 핵심 비즈니스 로직, 네트워킹(NetworkManager), 데이터베이스 모델 등을 포함한다.
  4. Shared Layer: 유틸리티, 익스텐션, 디자인 시스템(DesignSystem) 등 모든 모듈에서 공통으로 쓰이는 자원.
  5. ThirdParty Layer: 외부 라이브러리(Alamofire, SnapKit 등)를 래핑하여 의존성을 한곳으로 모으는 계층.

💻 Tuist로 모듈 정의하기

Tuist에서 모듈은 Target으로 정의된다.
각 타겟 간의 의존성은 .target(name:) 또는 .project(target:path:)를 통해 연결한다.

// Project.swift 예시
let project = Project(
    name: \"HomeFeature\",
    targets: [
        Target(
            name: \"HomeFeature\",
            platform: .iOS,
            product: .staticFramework, // 또는 .framework
            bundleId: \"com.kaguya.home\",
            sources: [\"Sources/**\"],
            dependencies: [
                .project(target: \"Core\", path: \"../Core\"),
                .project(target: \"DesignSystem\", path: \"../Shared/DesignSystem\")
            ]
        )
    ]
)

이렇게 정의된 모듈은 tuist generate 시 자동으로 의존성이 연결된 워크스페이스로 생성된다.


🚀 모듈화가 가져다주는 실질적인 이점

1) 빌드 속도의 비약적 향상

변경이 발생한 모듈과 그에 의존하는 모듈만 다시 빌드하면 된다.
대규모 프로젝트에서 전체 빌드 시간이 10분에서 2분으로 단축되는 마법을 경험할 수 있다.

2) 데모 앱(Demo App) 활용

특정 기능(Feature)만 포함하는 독립적인 타겟을 만들어 실행할 수 있다.
전체 앱을 실행하지 않고 로그인 기능만 빠르게 테스트할 수 있어 개발 생산성이 극대화된다.

3) 코드 격리와 책임 분리

모듈 간의 인터페이스를 명확히 정의해야 하므로 스파게티 코드가 방지된다.
특정 기능을 수정해도 다른 기능에 미치는 영향을 최소화할 수 있다.


💡 마무리

Tuist를 통한 모듈화는 단순한 유행이 아니라 지속 가능한 개발 환경을 위한 필수 선택이다.
물론 초기 설정 비용이 발생하고 Swift 언어에 대한 이해가 깊어야 하지만, 그 보상은 압도적이다.
프로젝트 초기부터 모듈화를 염두에 둔다면, 나중에 감당할 수 없을 정도로 커진 프로젝트를 수술하는 고통을 피할 수 있을 것이다.

참조: Tuist 공식 문서

profile
이유있는 코드를 쓰자!!

0개의 댓글