바로 앱 아키텍쳐
아키텍쳐에 관하여
바로 앱 서비스 아키텍쳐 소개
소프트웨어 아키텍처란, 소프트웨어 시스템의 구조와 그 구성 요소들이 어떻게 상호작용하는지를 정의한 설계도입니다. 각 구성요소와 책임을 어떻게 나눌 것인지를 결정하는 청사진이라고 할 수 있습니다.
바로 앱 서비스는
- 계속해서 기능이 추가/수정 되며
- Flutter를 처음 접하는 사람이 개발할 수 있고
- 잠시 잊고 있다 돌아와도 구조파악이 빠르게 되어 개발을 바로 시작
을 중점으로 아키텍쳐를 고민하고 있습니다.
소프트웨어를 변화하고 성장해야 하는 생명체에 비유한다면 바로 앱 서비스도 낮잠이나 겨울잠도 견딜 수 있는 녀석이면 좋겠다고 생각했습니다. 복잡하고 거대한 녀석보다는 단순하면서도 유지보수하기 좋은 녀석. 아직 초기 단계이기 때문에 어떤 방향성으로 흘러갈지 예측할수 없습니다.
아직 애벌레단계이지만 어떻게 변할지 모르는 녀석, 바로 앱 서비스
바로 어플리케이션 서비스 는 MVVM과 layered architecture가 혼합된 구조로 되어있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
🖿 barlow-application
├── 🖿 app ← 플랫폼별 빌드를 위한 요소(e.g. Android, IOS, Web)
│ ├── ▶️ main.dart ← 어플리케이션 진입점
│ ├── 🗀 mobile
│ └── 🗀 web
├── 🖿 core ← core 패키지(e.g. 네이티브 브릿지 관련, 의존성, Hive 설정 등)
├── 🖿 features ← feature별로 응집한 어플리케이션 내의 요소(e.g. auth, settings)
│ ├── 🗀 feature_A ← feature내에서는 layerd architecture와 같이 계층별로 나눔
│ │ ├── 🗀 domain
│ │ ├── 🗀 presentation
│ │ └── 🗀 data
│ ├── 🗀 feature_B
...
└── 🖿 design_system ← 폰트, 이미지 등의 에셋
각 패키지는 flutter create --template=package <패키지명>으로 생성된 패키지이며 각각의 pubspec.yaml을 통해 필요한 의존성을 관리합니다.
app은 어플리케이션이 멀티 플랫폼에 대응하기 위한 설정이 위치한 곳입니다. 바로 앱 서비스는 Android, Ios, Web 세가지 플랫폼에 대응 가능하도록 설정 할 수 있습니다. 각 플랫폼의 권한이나 시스템 자원활용 등에 관한 설정이 이곳에 속할 수 있습니다.
core는 어플리케이션 내부에서 재사용 가능한 가장 독립적인 패키지 입니다. 네트워크 설정, Hive와 같은 저장소 설정, util 등이 이곳에 속합니다.
design_system은 전역적으로 사용되는 앱의 에셋을 관리합니다. 폰트, 색상 테마 등이 이곳에 속합니다.
features는 어플리케이션이 사용자에게 제공하는 기능을 중심으로 응집화되어있습니다. 예를들어 ‘설정’, ‘로그인/회원가입’ 등은 각 사용자에게 제공하는 기능으로서 각 feature로 구분될 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
🗀 setting
├── 🗀 domain
│ ├── 🗀 entity
│ ├── 🗀 repository
│ └── 🗀 usecase
├── 🗀 presentation
│ ├── 🗀 screen
│ ├── 🗀 view
│ ├── 🗀 viewmodel
│ └── 🗀 widget
├── 🗀 data
│ └── repository adapters
🗀 auth
...
각 feature는 MVVM에 기반하여 layered architecture처럼 구성되어 있습니다. Java의 멀티 모듈 패키징처럼 강제적으로 의존성의 방향을 제어할 수는 없지만 명시적으로 분리함으로서 효과적으로 의존성을 분리할 수 있습니다.
MVVM구조와 함께 usecase를 통해 logical layer를 분리시켜 관리하는 것을 flutter 공식 문서에서도 권장하고 있습니다. 바로 앱 서비스도 이러한 구조를 차용하여 사용하고 있으며 layered architecture내의 domain 에서 usecase를 관리하는 방식을 통해 구현하고 있습니다.
더 자세한 내용은 flutter 공식 문서를 참고하세요
의존성 관리
바로 앱 서비스는 4-tier의 layerd architecture에 대응하여 다음과 같은 단방향의 의존성을 갖는 구조로 이루어져 있습니다. Hive의 경우 실제로 저장되는 엔티티의 구조, api 호출의 경우 요청/응답 형식및 클라이언트를 core에 정의하고 feature/data에서 이를 참조하여 repository adapter를 구현하는 DIP(의존성 역전)방식을 구현하고 있습니다.
1
2
3
4
5
[data / persistence] [business / presentation] [composition / entry]
core ─────────────▶ features ─────────────▶ app
▲
design_system
Flutter는 기본적으로 모놀리식(Monolithic) 아키텍처를 기반으로 하며, 하나의 엔트리포인트에서 전체 애플리케이션이 단일 바이너리로 빌드됩니다. 이에 따라 멀티 패키지 구조를 도입하더라도, Java/Spring 기반의 MSA처럼 각 패키지를 개별적으로 배포하거나 독립 실행하는 구조는 구현할 수 없습니다. Flutter의 멀티 패키지 구조는 기능별 모듈화나 의존성 분리에는 효과적이지만, 시스템 레벨의 분산 아키텍처를 대체할 수는 없습니다. 따라서 초기 프로젝트 설계 단계에서 패키지 분리를 도입할 경우, 장기적인 확장성에 한계가 있다는 점과, 구조 설계에 소요되는 리소스를 신중히 고려할 필요가 있습니다.
멀티 패키지를 사용해야하는 이유
Flutter는 Dart 기반이며, Dart는 리플렉션 기능이 제한적입니다. 이는 성능 최적화를 위한 선택으로, 코드의 동적 탐색보다는 컴파일 타임에 안정성과 최적화를 보장하는 방식을 택하고 있습니다. 그래서 대부분의 코드 자동화는 @Annotation 기반의 code generator로 처리되며, 이를 실행하기 위해 build_runner 도구가 필수적으로 사용됩니다.
| 주요 용도 | 사용하는 패키지 |
|---|---|
| 모델 직렬화/역직렬화 | json_serializable |
| immutable 데이터 클래스 | freezed, built_value |
| 의존성 주입 설정 | injectable |
| 로컬 DB 모델 | isar, hive_generator |
| 라우팅 자동화 | auto_route |
| GraphQL 쿼리 매핑 | graphql_codegen |
패키지 구조에서는 코드 생성 시 모든 파일을 한 번에 처리하기 때문에, 프로젝트 규모가 커질수록 빌드 시간이 길어지고, 캐시 문제나 충돌도 자주 발생합니다. 반면 멀티 패키지 구조를 사용하면, 각 패키지 단위로 build_runner를 돌릴 수 있어 코드 생성 범위를 좁히고, 속도와 안정성을 높일 수 있습니다. 또한 패키지마다 설정을 나눌 수 있어 충돌 없이 관리가 쉬워지고, 필요한 부분만 빌드할 수 있어 효율적입니다.
즉, build_runner 기반의 개발 환경에서는 멀티 패키지 구조가 단순한 폴더 분리 이상의 실질적인 빌드 최적화 효과를 제공합니다.
바로 앱 서비스를 google play에서 만나보세요


