모바일 개발에서의 모듈성 — 본질, 원칙 및 구성

저자: IT Sectr 게시일: 2026-05-13 읽는 시간: 9 분

모듈성은 애플리케이션이 독립적인 모듈로 조립되고 각 모듈이 하나의 기능을 담당하는 원칙입니다. Android Developers에 따르면 모듈로 분할하면 병렬 컴파일을 통해 빌드가 빨라지고 팀이 애플리케이션의 다른 부분에서 독립적으로 작업할 수 있습니다. 모듈식 아키텍처는 수십 명의 개발자가 있는 대규모 모바일 프로젝트의 표준이 되었습니다.

주요 내용

  • 모듈성 — 명확한 경계와 인터페이스를 가진 독립적인 블록으로 애플리케이션 분할
  • Android의 Gradle 모듈 및 iOS의 Swift Packages — 모듈식 아키텍처의 주요 도구
  • 모듈 내 코드 격리는 관련 없는 기능 간의 우발적 종속성을 방지합니다
  • 모듈의 병렬 빌드는 대규모 프로젝트에서 컴파일 시간을 2~4배 단축합니다
  • Feature-first — 각 화면이나 기능을 별도의 모듈로 분리하는 가장 인기 있는 접근 방식

모바일 개발에서 모듈성이란

모듈성은 애플리케이션이 느슨하게 결합된 모듈로 구성되고 각 모듈이 공개 인터페이스를 통해 엄격하게 정의된 기능을 제공하는 코드 구성 방식입니다. 모든 클래스가 단일 프로젝트에 있는 모놀리식 아키텍처와 달리 모듈식 접근 방식은 코드를 물리적으로 독립적인 빌드 단위로 분할합니다.

모듈성의 주요 목표는 복잡성 관리입니다. 개발자는 전체 코드베이스를 염두에 두지 않고 하나의 모듈에 집중할 수 있습니다. 각 모듈에는 고유한 책임 영역이 있으며 다른 모듈과 독립적으로 개발, 테스트 및 배포할 수 있습니다. 이는 10명 이상의 개발자가 있는 프로젝트에서 특히 중요하며, 모놀리스에서 병렬 작업은 빈번한 병합 충돌로 이어집니다.

모듈성을 계층형 아키텍처와 구분하는 것이 중요합니다. 계층(Presentation, Domain, Data)은 기술적 기준으로 코드를 나누는 반면, 모듈은 기능적 기준으로 나눕니다. “사용자 프로필” 모듈은 내부에 자체 계층을 포함할 수 있습니다. 실제로 모듈식 접근 방식과 계층형 아키텍처는 결합됩니다. 각 모듈은 자체 3계층 구조를 가집니다.

모듈 유형과 목적

기능 모듈은 가장 인기 있는 모듈 유형입니다. 각 화면 또는 관련 화면 그룹은 Onboarding, Profile, Settings, Feed 등 자체 모듈로 분리됩니다. 기능 모듈에는 UI, 비즈니스 로직, 데이터 계층 등 기능 작동에 필요한 모든 것이 포함됩니다. 모듈 경계는 보호되어 다른 기능이 내부 클래스에 액세스할 수 없습니다.

코어 모듈에는 네트워킹, 데이터베이스, 분석, 디자인 시스템 등 공통 인프라가 포함됩니다. 코어 모듈은 기능 모듈에 의존하지 않지만 기능 모듈은 코어 모듈에 의존합니다. 이러한 분리는 분석 SDK 변경이 네트워킹 계층에 영향을 미치지 않고 그 반대도 마찬가지임을 보장합니다. 코어 모듈은 코드 중복 없이 기능 간에 재사용됩니다.

공통 로직을 위한 공유 모듈

공유 모듈에는 여러 기능에서 사용하는 코드(데이터 모델, 유틸리티, 상수, 사용자 정의 뷰)가 포함됩니다. 공유 모듈의 주요 문제는 시간이 지남에 따라 이질적인 코드가 축적되는 “잡동사니 모듈”이 될 위험입니다. 규칙: 공유 모듈은 “shared-ui” 또는 “shared-models”와 같이 명확한 주제가 있어야 합니다.

Android에서 공유 모듈은 종종 lib 접두사가 있는 라이브러리로 분리됩니다: lib-network, lib-database, lib-ui-components. iOS에서는 Workspace 내부의 내부 Swift Packages가 동일한 기능을 수행합니다. 실제로 팀은 빌드를 복잡하게 만드는 과도한 종속성 네트워크를 방지하기 위해 공유 모듈 수를 3~5개로 제한합니다.

테스트 모듈 및 테스트 격리

별도의 테스트 모듈을 사용하면 전체 테스트 스위트를 실행하지 않고 변경된 모듈에 대해서만 테스트를 실행할 수 있습니다. 이렇게 하면 CI/CD 파이프라인 시간이 몇 시간에서 몇 분으로 단축됩니다. 모듈 수준 격리는 빌드 수준에서 SoC를 보장합니다. 네트워킹 계층 모듈은 테스트에서 실수로 UI 라이브러리를 가져올 수 없습니다.

각 모듈에는 명확하게 정의된 공개 API가 있어야 합니다. Android에서는 액세스 한정자와 Gradle의 api 대 implementation을 통해 달성됩니다. iOS에서는 public/internal 액세스 한정자와 Package.swift를 통한 관리 종속성을 통해 달성됩니다. 가시성을 필요한 최소 수준으로 줄이는 것이 모듈식 디자인의 핵심 사례입니다.

Android의 모듈성: Gradle modules

Gradle은 모듈식 아키텍처를 기본적으로 지원합니다. 각 모듈은 자체 build.gradle 파일이 있는 별도의 빌드 단위입니다. Android 프로젝트는 애플리케이션 모듈(app)과 여러 라이브러리 모듈의 조합을 사용합니다. 라이브러리 모듈은 애플리케이션으로 실행할 수 없지만 리포지토리에 AAR로 게시할 수 있습니다.

Gradle의 주요 기능은 독립적인 모듈의 병렬 빌드입니다. 모듈 A, B, C가 서로 의존하지 않는 경우 Gradle은 모든 CPU 코어를 사용하여 동시에 컴파일합니다. 20개 이상의 모듈이 있는 프로젝트에서 전체 빌드 시간이 15분에서 3~5분으로 단축됩니다. 변경된 모듈의 증분 빌드는 몇 초가 걸립니다.

Gradle은 모듈 간에 두 가지 종속성 유형을 제공합니다: api(전이적)와 implementation(비전이적). 이 차이는 모듈성에 매우 중요합니다. implementation은 모듈 소비자로부터 전이적 종속성을 숨깁니다. :profile 모듈이 implementation을 통해 :networking을 사용하는 경우 :profile의 소비자는 :networking에 대해 알지 못하고 액세스할 수 없습니다.

groovy
// settings.gradle — 모듈 선언
include ':app'
include ':feature:profile'
include ':feature:settings'
include ':core:network'
include ':core:database'

// build.gradle feature/profile — 모듈 종속성
dependencies {
    implementation project(':core:network')
    implementation project(':core:database')
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0'
}

코드는 모듈식 Android 프로젝트의 구조를 보여줍니다. Settings.gradle은 모든 모듈을 나열하고 각 기능 모듈의 build.gradle은 필요한 코어 모듈만 지정합니다. 빌드 시스템은 전이적 종속성을 자동으로 해결하고 올바른 순서로 모듈을 빌드합니다.

iOS의 모듈성: Swift Package Manager 및 CocoaPods

Swift Package Manager(SPM)는 2019년부터 iOS의 표준 모듈성 도구입니다. SPM은 애플리케이션을 Swift Packages로 분할할 수 있으며, 각 패키지는 라이브러리 또는 실행 파일이 될 수 있습니다. Package는 Package.swift를 통해 모듈(targets)과 해당 종속성을 정의합니다. SPM은 Xcode에 통합되어 있으며 추가 도구가 필요하지 않습니다.

CocoaPods는 타사 라이브러리를 위한 주요 종속성 관리자로 남아 있습니다. Podfile과 Podspec은 모듈 구조를 정의하고 CocoaPods는 별도의 pod 프로젝트가 있는 작업 공간을 생성합니다. 자체 프로젝트 모듈성의 경우 팀은 Xcode에 내장되어 있고 설치가 필요 없는 SPM을 점점 더 많이 선택하고 있습니다.

iOS 모듈성에서 액세스 제어는 중요한 역할을 합니다: public, package, internal, fileprivate 및 private. 모듈은 다른 모듈이 액세스할 수 있어야 하는 유형만 게시합니다. 내부 구현 세부 정보는 internal 및 private 한정자 뒤에 숨겨집니다. 이는 모듈 간의 숨겨진 종속성을 방지합니다.

swift
// Package.swift — iOS 프로젝트의 모듈식 구조
let package = Package(
    name: "MyApp",
    platforms: [.iOS(SupportedPlatform.iOSVersion.v17)],
    products: [
        .library(name: "ProfileFeature", targets: ["ProfileFeature"]),
        .library(name: "NetworkCore", targets: ["NetworkCore"]),
    ],
    dependencies: [
        .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.9.0")
    ],
    targets: [
        .target(name: "ProfileFeature", dependencies: ["NetworkCore"]),
        .target(name: "NetworkCore", dependencies: ["Alamofire"]),
    ]
)

Package.swift는 두 개의 라이브러리 제품을 선언합니다: ProfileFeature와 NetworkCore. ProfileFeature는 NetworkCore에 의존하지만 Alamofire의 존재를 알지 못합니다. Alamofire는 NetworkCore 내부에 숨겨져 있습니다. 이러한 격리는 모듈 수준에서 SoC를 직접 적용한 것입니다. HTTP 클라이언트의 변경에 ProfileFeature의 재컴파일이 필요하지 않습니다.

모듈식 아키텍처의 장점과 과제

모듈성의 주요 장점은 개발 속도입니다. 팀은 코드 충돌 없이 서로 다른 모듈에서 병렬로 작업합니다. CI/CD 파이프라인은 변경된 모듈만 빌드하고 해당 테스트만 실행합니다. 피드백 시간이 단축되고 릴리스 빈도가 증가합니다. Spotify, Uber, Airbnb는 모듈식 아키텍처로 마이그레이션하여 2~3배의 메트릭 개선을 보여주는 사례 연구를 발표했습니다.

두 번째 장점은 오류 격리입니다. Profile 모듈의 버그는 모듈 간에 직접적인 종속성이 없으면 Payments 모듈에 영향을 주지 않습니다. 이는 결제, 의료 데이터와 같은 고위험 기능이 있는 애플리케이션에서 특히 중요하며, 관련 없는 화면의 오류가 중요한 기능의 릴리스를 차단해서는 안 됩니다.

주요 과제는 종속성 관리입니다. 잘못된 설계로 인해 하나의 모듈 변경이 수십 개의 다른 모듈을 연쇄적으로 재빌드하는 모듈 그래프가 발생합니다. 해결책은 비순환 규칙을 따르는 것입니다. 모듈 종속성 그래프는 방향성 비순환 그래프(DAG)여야 합니다. Gradle Module Graph Assert와 같은 도구는 빌드 시간에 순환을 감지하는 데 도움이 됩니다.

두 번째 과제는 초기 설정 시간 증가입니다. 모듈식 아키텍처를 만드는 데는 프로젝트 초기화 단계에서 더 많은 시간이 필요합니다. 1~3명의 개발자가 있는 소규모 프로젝트는 병렬화의 실제 필요 없이 모듈 경계를 유지하는 데 시간을 소비하여 모듈성의 이점을 얻지 못할 수 있습니다. 해결책은 모놀리스로 시작하고 팀이 성장함에 따라 모듈을 추출하는 것입니다.

Feature-First 대 Layer-First 접근 방식

Feature-first 접근 방식은 기능별로 모듈을 그룹화합니다. 각 화면 또는 화면 그룹이 별도의 모듈이 됩니다. Layer-first 접근 방식은 기술적 기준으로 코드를 나눕니다: UI, 비즈니스 로직 및 데이터를 위한 별도의 모듈. 실제로 대부분의 팀은 코어 모듈과 함께 feature-first를 선택합니다. 이는 더 나은 격리와 명확한 프로젝트 탐색을 제공합니다.

접근 방식 간의 선택은 팀 규모와 기능 예측 가능성에 따라 다릅니다. 프로젝트에 어떤 화면이 있을지 정확히 알고 있다면 feature-first를 통해 각 개발자가 자신의 모듈을 책임질 수 있습니다. 기능이 자주 변경되고 화면 간에 겹치는 경우 layer-first는 다양한 기능 간의 코드 재사용에 더 많은 유연성을 제공합니다.

자주 묻는 질문

애플리케이션에는 몇 개의 모듈이 있어야 하나요?

최적의 수는 프로젝트와 팀 규모에 따라 다릅니다. 5명 팀의 경우 6~10개의 모듈이면 충분합니다. 20명 이상의 개발자의 경우 20~40개의 모듈이 필요합니다. 규칙: 모듈은 한 개발자가 완전히 이해할 수 있을 정도로 작고 과도한 종속성 네트워크를 만들지 않을 정도로 커야 합니다.

모듈성이 빌드를 느리게 하나요?

적절한 모듈성은 병렬 컴파일과 캐싱을 통해 빌드를 가속화합니다. 그러나 밀접한 종속성이 있는 과도한 모듈은 빌드를 느리게 합니다. Gradle과 Xcode는 그래프를 해결하는 데 시간을 소비합니다. 빠른 빌드의 핵심은 전이적 종속성을 최소화하고 비순환성을 유지하는 것입니다.

기존 애플리케이션을 모듈식으로 만들 수 있나요?

, 하지만 반복적으로 진행합니다. 코어 모듈(네트워크, 데이터베이스)을 추출하는 것부터 시작한 다음 하나씩 기능을 추출합니다. 기능 플래그를 사용하여 기존 모놀리식 코드와 함께 새 모듈식 코드를 활성화합니다. 대규모 애플리케이션의 전체 마이그레이션에는 3~12개월이 소요됩니다.

모듈성과 마이크로서비스의 차이점은 무엇인가요?

모듈은 단일 애플리케이션 내의 컴파일 단위입니다. 마이크로서비스는 다른 서버에서 실행되는 별도의 프로세스입니다. 모듈은 코드를 분할하고 마이크로서비스는 런타임을 분할합니다. 모바일 개발에서는 “microapps”라는 용어가 하이브리드로 자주 사용됩니다. 독립 실행형 애플리케이션으로 실행될 수 있는 기능 모듈입니다.

모듈식 애플리케이션을 테스트하는 방법은?

각 모듈에는 독립적으로 실행되는 자체 단위 테스트가 있습니다. 통합 테스트는 모듈 간의 상호 작용을 확인합니다. UI 테스트는 모의 데이터로 기능 모듈을 다룹니다. 모듈식 아키텍처는 테스트를 단순화합니다. 다른 모듈의 종속성을 모의하는 것이 모놀리스의 일부를 모의하는 것보다 쉽습니다.

요약

  • 모듈성 — 명확한 경계를 가진 독립적인 빌드 단위로 애플리케이션 분할
  • 기능 모듈은 기능을 중심으로 코드를 그룹화하고, 코어 모듈은 인프라를 중심으로 그룹화
  • Android의 Gradle과 iOS의 SPM — 모듈식 아키텍처 구현의 주요 도구
  • 병렬 빌드와 코드 격리 — 대규모 프로젝트에서 모듈성의 주요 장점
  • 종속성 그래프는 비순환적이어야 하며, 그렇지 않으면 빌드가 느려지고 순환 참조가 발생합니다
  • 코어 모듈을 사용한 Feature-first 접근 방식이 대규모 모바일 프로젝트에 가장 효과적인 것으로 인정됨
  • 모놀리스로 시작하고 팀과 코드베이스가 성장함에 따라 모듈을 추출하세요

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기