티스토리 뷰
플러터 앱 아키텍처 가이드
아키텍처란?
소프트웨어 시스템의 구조와 설계 원칙을 의미함
소프트웨어를 어떻게 구성하고, 각 구성 요소가 어떻게 상호작용할지에 대한 큰 그림
아키텍처의 구성 요소
- 계층 구조
- 컴포넌트 간의 책임 분리 (예: 컨트롤러는 요청 처리, 모델은 데이터 처리)
- 데이트 흐름 (어디서 데이터가 생성되고, 어떻게 전달되는지)
- 모듈 간의 관계 및 의존성
- 설계 원칙 (예: SOLID 원칙, 의존성 역전 등)
왜 사용하는가?
- 유지보수 용이성 : 기능 추가 / 변경 / 수정이 수워짐
- 재사용성 증가 : 잘 나눈 모듈은 다른 프로젝트에서도 재사용할 수 있음
- 협업 효율 증가 : 역할이 명확해서 여러 명이 동시에 작업해도 충돌이 적음
- 테스트 용이성 : 각 구성 요소를 개별적으로 테스트하기 쉬움
- 확장성 확보 : 서비스 규모가 커져도 구조적으로 잘 대응할 수 있음
흔히 쓰는 아키텍처 패턴
- MVC (Model-View-Controller)
- MVVM (Model-View-ViewModel)
- Clean Architecture (클린 아키텍처)
- Layered Architecture (계층형 아키텍처)
- Hexagonal Architecture (육각형 아키텍처)
- Microservices Architecture (마이크로서비스)
가이드에서 다루는 주요 내용
- 의도적인 아키텍처의 이점
- 공통 아키텍처 원칙
- 플러터 팁의 권장 구조
- MVVM, 상태 관리, 의존성 주입
- 안정적인 앱을 위한 디자인 패턴
관심사의 분리 (Sepration of Concerns)
- 앱 기능을 모듈화하여 관리성과 유지보수성을 높이는 원칙
- UI 로직과 비즈니스 로직을 분리하는 것을 의미함
- 이를 계층형 아키텍처라고 함
- 플러터에서는 위젯을 UI 계층으로 적용함
- 재사용 가능하고, 최소한의 로직만을 포함한 간결한 위젯으로 작성해야 함
계층형 아키텍처(Layered architecture)
앱을 역할에 따라 2~3개 계층으로 나눠 구성함
- 데이터 계층 - 데이터 베이스와 같은 데이터 소스와의 상호작용을 관리한다. 로직 계층에 데이터와 메서드를 제공한다.
- 로직 계층 - 핵심 비즈니스 로직을 구현하고, 데이터 계층과 UI 계층 간의 상호작용을 조율한다. '도메인 계층'이라고도 한다. 이 계층은 선택 사항이며, 복잡한 비즈니스 로직이 필요한 경우에만 사용된다. 많은 앱들이 단순히 사용자에게 데이터를 보여주고, 그 데이터를 수정할 수 있도록 하는 기능만을 제공한다. 이런 앱들은 이 계층이 필요하지 않을 수도 있다.
- UI 계층 - 사용자에게 데이터를 표시하고, 사용자 상호 작용을 처리한다. '프로젠테이션 계층'이라고도 한다.
'계층'이라고 불리는 이유는, 각 계층이 바로 위 또는 아래 계층하고만 통신할 수 있기 때문이다. 근접하지 않는 계층은 알아서도 안되고, 알 필요도 없어야 한다.
로직 계층이 필요한 경우
1. 비즈니스 로직이 복잡할 때
- 예: 여러 조건에 따라 데이터 필터링, 가공, 상태 업데이트가 반복되는 경우
- View에서 직접 처리하면 UI와 로직이 뒤섞여 유지보수가 어려워짐.
2. UI와 독립된 상태 관리를 할 때 - 앱 전역에서 공통적으로 사용되는 상태
- 예: 로그인 상태, 테마 상태, 네트워크 상태 등을 앱 전체에서 공유해야 할 때.
- 상태를 전역에서 관리할 로직 계층이 필요.
3. 하나의 데이터가 여러 UI에서 사용될 때 - 하나의 데이터가 여러 화면에서 재사용되는 경우
- 예: 장바구니, 유저 프로필 정보 등
- 서버나 로컬 DB에서 가져온 도메인 데이터
- 로직 계층이 없으면 중복된 데이터 로딩/처리 발생.
4. 테스트를 위해 비즈니스 로직을 분리하고 싶을 때
- 로직을 UI와 분리하면 단위 테스트(Unit Test)가 훨씬 쉬워짐.
5. 비동기 처리와 상태 변화를 추적해야 할 때
- 로딩, 성공, 실패 상태 관리 등
- 예: API 호출 시 loading → success → error 상태 전환.
로직 계층이 필요하지 않는 경우
1. 매우 단순한 화면
- 예: 정적인 정보만 보여주는 페이지 (설정 안내 페이지, 앱 정보 페이지 등)
- 별도의 상태 관리 없이 UI에서 직접 데이터 표시 가능
2. 상태 변화가 거의 없거나, 국지적인 상태만 있을 때
- 예: 텍스트 입력값, 토글 버튼 상태처럼 한 화면 안에서만 쓰이는 간단한 상태
- StatefulWidget으로 처리하면 충분함
3. 프로토타입이나 MVP 단계
- 개발 속도를 우선시할 때, 초기 단계에서 복잡한 구조보다 빠른 구현이 중요할 수 있음
단일 진실의 공급원 (SSOT: Single Source of Truth)
앱의 모든 데이터는 하나의 진실된 공급원(SSOT)을 가져야 하며, 이 SSOT는 해당 데이터의 유일한 수정 권한을 가지는 객체여야 한다.
- SSOT는 일반적으로 데이터 계층의 Repository나, 로직 계층의 상태 관리 클래스에서 정의
- SSOT를 통해 버그를 줄이고, 데이터 일관성을 유지하며, 코드를 단순화함
- 데이터 수정은 SSOT만 가능하고, 다른 계층이나 클래스는 SSOT의 데이터를 읽거나 구독, 또는 SSOT에게 수정 요청만 해야 한다.
이 원칙은 앱 전체의 계층뿐 아니라 개별 클래스 내에서도 적용 가능하다.
- 예를 들어 Dart 클래스에서 DateTime _createdAt 하나만 SSOT로 두고
- year, month, day 등은 이 값을 기반으로 계산하는 getter를 통해 제공할 수 있음
단방향 데이터 흐름 (UDF: Unidirectional Data Flow)
흐름 구조
- 상태 흐름 : 데이터 계층 → 로직 계층 → UI 계층
- 이벤트 흐름 : UI 계층 → 로직 계층 → 데이터 계층
이러한 흐름을 통해 UI와 상태를 분리하고, 코드의 예측 가능성, 안정성을 높일 수 있다.
사용자 상호작용 시 흐름
UDF에서 사용자 상호작용으로 UI에 다시 렌더링되는 과정은 다음과 같다.
1. UI 계층 - 사용자가 버튼을 눌러서 이벤트 발생
2. 로직 계층 - 로직 클래스가 데이터 변경을 요청하기 위해 Repository의 메서드 호출
3. 데이터 계층 - 저장소가 실제 데이터를 업데이트하고, 새로운 값을 로직 계층에 전달
4. 로직 계층 - 새로운 상태를 저장하고 UI에 전달
5. UI 계층 - 새로운 상태를 기반으로 UI 렌더링
저장소가 HTTP 서버에서 새 데이터를 가져 오는 경우에는 1, 2 과정이 생략될 수 있다.
핵심 원칙
모든 데이터 변경은 반드시 SSOT에서만 발생해야 한다.
- 이렇게 하면:
- 코드가 예측 가능해 지고
- 디버깅이 쉬워지며
- 잘못되거나 충돌을 방지할 수 있음
UI는 (불변) 상태의 함수다
- Flutter는 선언형 UI 프레임워크이다.
- 앱의 현재 상태에 따라 UI가 자동으로 구성된다.
- 상태가 변경되면, 해당 상태에 의존하는 UI가 자동으로 구성된다.
- 이를 플러터의 "UI는 상태의 함수이다"라고 표현
주요 원칙
- 데이터가 UI를 구동해야 하며, 그 반대로 UI가 직접 데이터를 수정해서는 안 됨
- 데이터는 불변(immutable)이고 영속적이어야 함
- 뷰는 가능한 적은 로직만 포함해야 함
효과
- 앱 종료 시 데이터 손실 위험 감소
- 테스트 및 유지보수 용이
- UI 구성과 상태 흐름이 예측 가능해짐
확장성 (Extensibility)
- 아키텍처의 각 구성 요소는 명확한 입력과 출력 인터페이스를 가져야 함
- 내부 구현은 외부와 분리되어야 함
- 예: 뷰모델은 저장소와 같은 데이터 소스만 입력으로 받고, 뷰에는 필요한 명령과 데이터만 노출해야 함
- 이런 인터페이스 기반 설계를 통해 새로운 기능을 추가하거나 구현을 교체할 때
- 다른 계층에 영향을 주지 않고 쉽게 확장할 수 있음
테스트 용이성 (Testability)
- 확장성 원칙은 동시에 테스트도 쉽게 만들어 줌
- 예: 저장소를 모킹하여 뷰 모델의 로직만 단위 테스트할 수 있음
- 예: 뷰모텔 테스트는 위젯과는 별도로 수행되므로 UI에 영향을 받지 않음
- 새로운 기능 추가 시 기존 로직에 영향을 주지 않음 → 유연하고 안전한 구조를 유지
'Flutter > 아키텍처' 카테고리의 다른 글
플러터 앱 아키텍처 _ 6. 아키텍처 예제 _ 계층간 통신(의존성 주입) (0) | 2025.04.15 |
---|---|
플러터 앱 아키텍처 _ 5. 아키텍처 예제 _ 데이터 계층 (0) | 2025.04.15 |
플러터 앱 아키텍처 _ 4. 아키텍처 예제 _ UI 계층 (0) | 2025.04.15 |
플러터 앱 아키텍처 _ 3. 아키텍처 예제 _ 개요 (0) | 2025.04.15 |
플러터 앱 아키텍처 _ 2. 앱 아키텍처 가이드 (0) | 2025.04.15 |