Skip to content

Architecture

jjoonleo edited this page Sep 1, 2025 · 7 revisions

OnTime Flutter Project Architecture

This document provides a comprehensive overview of the OnTime Flutter project's architecture, folder structure, and design patterns.

πŸ—οΈ Architecture Overview

OnTime follows Clean Architecture principles with a clear separation of concerns across three main layers:

  • Presentation Layer: UI components, state management (BLoC/Cubit), and navigation
  • Domain Layer: Business logic, entities, use cases, and repository interfaces
  • Data Layer: Repository implementations, data sources (local/remote), and data models

Architecture Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    PRESENTATION LAYER                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β€’ Screens & Components                                     β”‚
β”‚  β€’ BLoC/Cubit (State Management)                           β”‚
β”‚  β€’ Navigation (GoRouter)                                   β”‚
β”‚  β€’ Theme & Localization                                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     DOMAIN LAYER                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β€’ Entities (Business Objects)                             β”‚
β”‚  β€’ Use Cases (Business Logic)                              β”‚
β”‚  β€’ Repository Interfaces                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      DATA LAYER                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β€’ Repository Implementations                              β”‚
β”‚  β€’ Data Sources (Remote API, Local Database)               β”‚
β”‚  β€’ Data Models (JSON Serialization)                        β”‚
β”‚  β€’ Database Tables & DAOs                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“ Project Structure

lib/
β”œβ”€β”€ πŸ“± presentation/          # UI Layer (Screens, Widgets, State Management)
β”‚   β”œβ”€β”€ alarm/               # Alarm and timer functionality
β”‚   β”œβ”€β”€ app/                 # Main app setup and global BLoC
β”‚   β”œβ”€β”€ calendar/            # Calendar views and components
β”‚   β”œβ”€β”€ early_late/          # Early/late arrival screens
β”‚   β”œβ”€β”€ home/                # Home screen and dashboard
β”‚   β”œβ”€β”€ login/               # Authentication screens
β”‚   β”œβ”€β”€ my_page/             # User profile and settings
β”‚   β”œβ”€β”€ notification_allow/  # Notification permission
β”‚   β”œβ”€β”€ onboarding/          # User onboarding flow
β”‚   β”œβ”€β”€ schedule_create/     # Schedule creation and editing
β”‚   └── shared/              # Shared UI components and utilities
β”‚       β”œβ”€β”€ components/      # Reusable widgets
β”‚       β”œβ”€β”€ router/          # Navigation configuration
β”‚       β”œβ”€β”€ theme/           # App theming
β”‚       └── utils/           # UI utilities
β”‚
β”œβ”€β”€ 🏒 domain/               # Business Logic Layer
β”‚   β”œβ”€β”€ entities/            # Business objects (User, Schedule, etc.)
β”‚   β”œβ”€β”€ repositories/        # Repository interfaces
β”‚   └── use-cases/           # Business logic operations
β”‚
β”œβ”€β”€ πŸ’Ύ data/                 # Data Access Layer
β”‚   β”œβ”€β”€ daos/                # Database Access Objects (Drift)
β”‚   β”œβ”€β”€ data_sources/        # Data source interfaces/implementations
β”‚   β”œβ”€β”€ models/              # API request/response models
β”‚   β”œβ”€β”€ repositories/        # Repository implementations
β”‚   └── tables/              # Database table definitions
β”‚
β”œβ”€β”€ πŸ”§ core/                 # Core Infrastructure
β”‚   β”œβ”€β”€ constants/           # App constants and environment variables
β”‚   β”œβ”€β”€ database/            # Database configuration (Drift)
β”‚   β”œβ”€β”€ di/                  # Dependency injection setup (Injectable)
β”‚   β”œβ”€β”€ dio/                 # HTTP client configuration
β”‚   β”œβ”€β”€ services/            # Core services (navigation, notifications)
β”‚   └── utils/               # Core utilities and converters
β”‚
β”œβ”€β”€ 🌍 l10n/                 # Localization files
β”œβ”€β”€ firebase_options.dart    # Firebase configuration
└── main.dart               # Application entry point

πŸ› οΈ Technology Stack

Core Framework & Language

  • Flutter: Cross-platform mobile framework
  • Dart: Programming language

State Management

  • BLoC/Cubit: Business Logic Component pattern for state management
  • Riverpod: Additional state management for specific use cases
  • Equatable: Value equality for state objects

Dependency Injection

  • Injectable: Code generation for dependency injection
  • GetIt: Service locator pattern

Database & Persistence

  • Drift: Type-safe SQL database library
  • SharedPreferences: Simple key-value storage
  • FlutterSecureStorage: Secure token storage

Networking

  • Dio: HTTP client with interceptors
  • JSON Annotation: JSON serialization code generation

Navigation

  • GoRouter: Declarative routing solution

UI Components

  • Material Design: Google's design system
  • Flutter SVG: SVG asset support
  • TableCalendar: Calendar widget

Authentication

  • Google Sign-In: Google OAuth integration
  • Kakao SDK: Kakao social login
  • Firebase Auth: Authentication backend

Notifications

  • Firebase Messaging: Push notifications
  • Flutter Local Notifications: Local notifications

Development Tools

  • Freezed: Code generation for immutable classes
  • Build Runner: Code generation runner
  • Widgetbook: Component development environment

πŸ“‹ Architecture Patterns

1. Clean Architecture Layers

Presentation Layer

  • Screens: Full-screen widgets representing app pages
  • Components: Reusable UI widgets
  • BLoC/Cubit: State management following BLoC pattern
  • Navigation: Declarative routing with GoRouter

Domain Layer

  • Entities: Core business objects using Freezed for immutability
  • Use Cases: Single-responsibility business logic operations
  • Repository Interfaces: Contracts for data access

Data Layer

  • Repository Implementations: Concrete implementations of domain interfaces
  • Data Sources: Abstraction over remote APIs and local storage
  • Models: Data transfer objects with JSON serialization

2. Dependency Injection

// Injectable annotation for automatic registration
@Injectable()
class UserRepository implements UserRepositoryInterface {
  // Implementation
}

// GetIt service locator configuration
final getIt = GetIt.instance;

@InjectableInit()
void configureDependencies() => getIt.init();

3. State Management with BLoC

// BLoC for handling user authentication state
@Injectable()
class AppBloc extends Bloc<AppEvent, AppState> {
  AppBloc(this._streamUserUseCase, this._signOutUseCase)
      : super(AppState(user: const UserEntity.empty())) {
    on<AppUserSubscriptionRequested>(_onUserSubscriptionRequested);
    on<AppSignOutPressed>(_onSignOutPressed);
  }
}

4. Data Models with JSON Serialization

@JsonSerializable()
class GetUserResponseModel {
  final int userId;
  final String email;
  final String name;

  // Conversion to domain entity
  UserEntity toEntity() {
    return UserEntity(
      id: userId.toString(),
      email: email,
      name: name,
    );
  }
}

5. Database Layer with Drift

@DriftDatabase(tables: [Users, Schedules, Places], daos: [UserDao, ScheduleDao])
class AppDatabase extends _$AppDatabase {
  @override
  int get schemaVersion => 3;

  @override
  MigrationStrategy get migration => MigrationStrategy(
    onCreate: (Migrator m) async => await m.createAll(),
  );
}

πŸ”„ Data Flow

1. User Interaction Flow

User Input β†’ Widget β†’ BLoC Event β†’ Use Case β†’ Repository β†’ Data Source β†’ API/DB
                ↓
Widget ← BLoC State ← Use Case ← Repository ← Data Source ← Response

2. Authentication Flow

Login Screen β†’ AppBloc β†’ SignInUseCase β†’ UserRepository β†’ AuthDataSource β†’ API
      ↓
Navigation ← AppBloc ← UserEntity ← UserRepository ← AuthDataSource ← Token

3. Schedule Management Flow

Schedule Form β†’ ScheduleBloc β†’ CreateScheduleUseCase β†’ ScheduleRepository
                     ↓
Database ← ScheduleDao ← ScheduleRepository ← ScheduleEntity

🎯 Key Features Architecture

1. Authentication System

  • Google OAuth and Kakao Login integration
  • JWT token management with secure storage
  • Stream-based user state management
  • Automatic token refresh via interceptors

2. Schedule Management

  • CRUD operations for schedules
  • Calendar integration with multiple view modes
  • Preparation time calculation and management
  • Real-time synchronization between local and remote data

3. Notification System

  • Firebase push notifications for schedule reminders
  • Local notifications for preparation alerts
  • Permission handling for notification access

4. Offline Support

  • Local database with Drift for offline data access
  • Synchronization strategy for online/offline data consistency
  • Caching mechanisms for improved performance

πŸ§ͺ Testing Strategy

Structure

test/
β”œβ”€β”€ config/              # Test configuration
β”œβ”€β”€ data/               # Data layer tests
└── helpers/            # Test utilities

Testing Approach

  • Unit Tests: Use cases, repositories, and business logic
  • Widget Tests: UI components and screen interactions
  • Integration Tests: End-to-end user flows
  • Mocking: Using Mockito for external dependencies

πŸ“¦ Build & Deployment

Development Environment

  • Flutter SDK: ^3.5.4
  • Dart SDK: Latest stable
  • Build Tools: build_runner for code generation

Code Generation Commands

# Generate all code (models, dependency injection, etc.)
dart run build_runner build

# Watch for changes and regenerate
dart run build_runner watch

Platform Support

  • Android: Native Android build
  • iOS: Native iOS build
  • Web: Progressive Web App support

πŸ”§ Development Guidelines

1. Code Organization

  • Follow Clean Architecture principles
  • Separate concerns across layers
  • Use feature-based folder structure in presentation layer

2. State Management

  • Use BLoC pattern for complex state management
  • Use Cubit for simpler state scenarios
  • Keep business logic in use cases, not in BLoCs

3. Data Handling

  • Always use entities in the domain layer
  • Convert models to entities at repository boundaries
  • Implement proper error handling throughout the layers

4. Naming Conventions

  • Entities: UserEntity, ScheduleEntity
  • Use Cases: GetUserUseCase, CreateScheduleUseCase
  • Repositories: UserRepository, ScheduleRepository
  • BLoCs: UserBloc, ScheduleFormBloc
  • Models: GetUserResponseModel, CreateScheduleRequestModel

5. Dependencies

  • Register all dependencies using @Injectable() annotation
  • Use interfaces for repository contracts
  • Avoid direct dependencies between layers

πŸš€ Getting Started for New Developers

  1. Setup Environment

    • Install Flutter SDK
    • Configure IDE (VS Code/Android Studio)
    • Run flutter pub get to install dependencies
  2. Code Generation

    • Run dart run build_runner build
    • This generates dependency injection, JSON serialization, and Freezed code
  3. Database Setup

    • Database migrations are handled automatically
    • Local database files are created on first run
  4. Understanding the Flow

    • Start with main.dart to understand app initialization
    • Explore presentation/app/ for global app state
    • Check domain/use-cases/ for business logic
    • Review data/repositories/ for data access patterns
  5. Making Changes

    • Create new features following the existing layer structure
    • Add new entities in domain/entities/
    • Implement use cases in domain/use-cases/
    • Create repository interfaces and implementations
    • Build UI components in presentation/

This architecture documentation is maintained alongside the codebase. Please update it when making significant architectural changes.