Skip to content

Flutter 프로젝트 구조 이해

Flutter 프로젝트는 여러 디렉토리와 파일로 구성되어 있으며, 각각은 프로젝트의 특정 측면을 담당합니다. 이 구조를 이해하면 Flutter 앱을 더 효율적으로 개발하고 관리할 수 있습니다.

기본적인 Flutter 프로젝트 구조는 다음과 같습니다:

  • Directorymy_flutter_app/
    • Directory.dart_tool/ # Dart 도구 관련 파일
    • Directory.idea/ # IDE 설정 (Android Studio)
    • Directoryandroid/ # 안드로이드 특화 코드
    • Directorybuild/ # 빌드 출력 파일
    • Directoryios/ # iOS 특화 코드
    • Directorylib/ # Dart 코드
    • main.dart # 앱의 진입점
    • Directorylinux/ # Linux 특화 코드
    • Directorymacos/ # macOS 특화 코드
    • Directorytest/ # 테스트 코드
    • Directoryweb/ # 웹 특화 코드
    • Directorywindows/ # Windows 특화 코드
    • .gitignore # Git 무시 파일
    • .metadata # Flutter 메타데이터
    • analysis_options.yaml # Dart 분석 설정
    • pubspec.lock # 의존성 버전 잠금 파일
    • pubspec.yaml # 프로젝트 설정 및 의존성
    • README.md # 프로젝트 설명

이제 각 디렉토리와 파일의 역할을 자세히 살펴보겠습니다.

lib/ 디렉토리는 Flutter 프로젝트의 핵심으로, 앱의 Dart 소스 코드가 저장되는 위치입니다.

  • Directorylib/
    • main.dart # 앱의 진입점
    • Directorymodels/ # 데이터 모델
    • Directoryscreens/ # 화면 UI
    • Directorywidgets/ # 재사용 가능한 위젯
    • Directoryservices/ # 비즈니스 로직, API 호출 등
    • Directoryutils/ # 유틸리티 기능

중요: 기본적으로 생성되는 것은 main.dart 파일뿐이며, 나머지 폴더 구조는 개발자가 필요에 따라 생성하고 구성합니다.

main.dart 파일은 앱의 진입점으로, main() 함수와 루트 위젯을 포함합니다:

import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}

test/ 디렉토리는 앱의 자동화된 테스트 코드를 포함합니다. 단위 테스트, 위젯 테스트 등을 이 디렉토리에 작성합니다.

  • Directorytest/
    • widget_test.dart # 위젯 테스트
    • Directoryunit/
      • models_test.dart # 단위 테스트

기본적으로 생성되는 widget_test.dart 파일은 앱의 메인 위젯을 테스트하는 간단한 예제를 포함합니다:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:my_flutter_app/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
await tester.pumpWidget(const MyApp());
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}

android/ 디렉토리는 Android 플랫폼 관련 코드와 설정을 포함합니다.

  • Directoryandroid/
    • Directoryapp/
      • Directorysrc/
        • Directorymain/
          • AndroidManifest.xml # 앱 선언 및 권한
          • Directorykotlin/ # Kotlin 소스 코드
          • Directoryres/ # 리소스 (아이콘, 문자열 등)
        • Directoryprofile/
      • build.gradle # 앱 수준 빌드 설정
    • build.gradle # 프로젝트 수준 빌드 설정
    • Directorygradle/
    • gradle.properties

특히 중요한 파일들:

  • AndroidManifest.xml: 앱의 이름, 아이콘, 필요한 권한 등을 정의합니다.
  • build.gradle: 앱의 버전, 의존성, 빌드 설정 등을 구성합니다.

ios/ 디렉토리는 iOS 플랫폼 관련 코드와 설정을 포함합니다.

  • Directoryios/
    • DirectoryRunner/
      • AppDelegate.swift # iOS 앱 진입점
      • Info.plist # 앱 구성 및 권한
      • DirectoryAssets.xcassets/ # 이미지 에셋
    • DirectoryRunner.xcodeproj/ # Xcode 프로젝트 파일

특히 중요한 파일들:

  • Info.plist: 앱 이름, 버전, 권한 등의 메타데이터를 포함합니다.
  • AppDelegate.swift: iOS 앱의 진입점 및 초기화 로직을 포함합니다.

web/, macos/, linux/, windows/ 디렉토리

Section titled “web/, macos/, linux/, windows/ 디렉토리”

이 디렉토리들은 각각 웹, macOS, 리눅스, 윈도우 플랫폼을 위한 코드와 설정을 포함합니다. 구조는 플랫폼마다 다르지만, 모두 해당 플랫폼의 네이티브 코드와 구성을 담고 있습니다.

pubspec.yaml은 Flutter 프로젝트의 핵심 설정 파일로, 앱의 메타데이터, 의존성, 에셋 등을 정의합니다:

name: my_flutter_app
description: A new Flutter project.
# The following defines the version and build number for your application.
version: 1.0.0+1
environment:
sdk: ">=3.0.0 <4.0.0"
# Dependencies
dependencies:
flutter:
sdk: flutter
http: ^1.0.0
shared_preferences: ^2.1.1
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
# Flutter-specific configurations
flutter:
uses-material-design: true
# Assets
assets:
- assets/images/
- assets/fonts/
# Fonts
fonts:
- family: Roboto
fonts:
- asset: assets/fonts/Roboto-Regular.ttf
- asset: assets/fonts/Roboto-Bold.ttf
weight: 700

주요 항목들:

  • name: 앱의 패키지 이름
  • version: 앱의 버전(버전 코드+빌드 번호 형식)
  • dependencies: 앱이 사용하는 패키지 의존성
  • dev_dependencies: 개발 시에만 필요한 패키지 의존성
  • flutter: Flutter 특화 설정 (에셋, 폰트, 테마 등)

analysis_options.yaml은 Dart 코드 분석기의 설정을 정의하여 코드 품질과 일관성을 유지하는 데 도움을 줍니다:

include: package:flutter_lints/flutter.yaml
linter:
rules:
- avoid_print
- avoid_empty_else
- prefer_const_constructors
- sort_child_properties_last
analyzer:
errors:
missing_required_param: error
missing_return: error

.gitignore 파일은 Git 버전 관리 시스템에서 무시해야 할 파일들을 지정합니다. Flutter 프로젝트에서는 빌드 결과물, 임시 파일, IDE 파일 등이 여기에 포함됩니다.

개발자들은 프로젝트의 규모와 복잡성에 따라 추가 디렉토리를 생성할 수 있습니다:

  • Directoryassets/
    • Directoryimages/ # 이미지 파일
    • Directoryfonts/ # 폰트 파일
    • Directorydata/ # JSON, CSV 등의 데이터 파일

이 디렉토리는 pubspec.yaml에 명시적으로 등록해야 합니다:

flutter:
assets:
- assets/images/
- assets/fonts/
- assets/data/

다국어 지원을 위한 디렉토리:

  • Directoryl10n/
    • app_en.arb # 영어 번역
    • app_ko.arb # 한국어 번역
    • app_ja.arb # 일본어 번역

Flutter 앱의 구조는 프로젝트의 성격과 팀의 선호도에 따라 달라질 수 있습니다. 일반적으로 많이 사용되는 패턴은 다음과 같습니다:

앱의 기능별로 디렉토리를 구성하는 방식:

  • Directorylib/
    • main.dart
    • Directoryfeatures/
      • Directoryauth/
        • Directoryscreens/
        • Directorywidgets/
        • Directorymodels/
        • Directoryservices/
      • Directoryhome/
      • Directoryprofile/
      • Directorysettings/
    • Directoryshared/
      • Directorywidgets/
      • Directoryutils/
      • Directoryconstants/

이 구조는 기능이 많은 대규모 앱에 적합합니다.

앱의 아키텍처 계층별로 디렉토리를 구성하는 방식:

  • Directorylib/
    • main.dart
    • Directoryscreens/ # 모든 화면 UI
    • Directorywidgets/ # 모든 재사용 위젯
    • Directorymodels/ # 모든 데이터 모델
    • Directoryservices/ # 모든 서비스 로직
    • Directoryrepositories/ # 데이터 액세스 로직
    • Directoryutils/ # 유틸리티 함수

이 구조는 작거나 중간 규모의 앱에 적합합니다.

보다 체계적인 아키텍처 패턴을 적용한 구조:

  • Directorylib/
    • main.dart
    • Directoryui/
      • Directoryscreens/
      • Directorywidgets/
    • Directoryviewmodels/
    • Directorymodels/
    • Directoryservices/
    • Directoryrepositories/
    • Directorycore/
      • Directoryutils/
      • Directoryconstants/

이 구조는 코드의 유지 관리성과 테스트 가능성을 높이는 데 도움이 됩니다.

  • 파일 이름: snake_case.dart (예: user_profile.dart)
  • 클래스 이름: PascalCase (예: UserProfile)
  • 변수 및 함수 이름: camelCase (예: userName, getUserInfo())
  • 처음부터 명확한 구조 계획 수립
  • 프로젝트 전체에 동일한 규칙 적용
  • 팀 내 구조 합의 및 문서화
  • 관련된 코드는 함께 위치
  • 너무 깊은 중첩 디렉토리 피하기 (일반적으로 3-4 수준 이내)
  • 디렉토리 이름은 내용을 명확히 반영
  • 파일이 너무 많아지면 관리가 어려울 수 있음
  • 단일 위젯이나 작은 기능을 여러 파일로 나누지 않기
  • 너무 큰 파일도 피하기 (일반적으로 300-500줄 이내)

다양한 환경(개발, 스테이징, 프로덕션)에 대한 구성을 지원하기 위해 다음과 같은 접근 방식을 사용할 수 있습니다:

  • Directorylib/
    • main.dart # 공통 진입점
    • main_dev.dart # 개발 환경 진입점
    • main_staging.dart # 스테이징 환경 진입점
    • main_prod.dart # 프로덕션 환경 진입점
    • Directoryconfig/
      • app_config.dart # 환경 설정 클래스
      • dev_config.dart
      • staging_config.dart
      • prod_config.dart

앱의 화면 전환을 관리하기 위한 라우팅 구성:

  • Directorylib/
    • Directoryrouter/
      • app_router.dart # 라우터 설정
      • routes.dart # 라우트 상수

선택한 상태 관리 솔루션에 따라 구조가 달라질 수 있습니다:

  • Directorylib/
    • Directoryproviders/ # Riverpod/Provider
    • Directoryblocs/ # Flutter_bloc
    • Directorystores/ # MobX
    • Directorystate/ # 기타 상태 관리

Flutter 프로젝트 구조는 규모와 복잡성에 따라 다양하게 적용할 수 있습니다. 중요한 것은 팀이 이해하기 쉽고 유지 관리가 용이한 일관된 구조를 선택하는 것입니다. 프로젝트가 성장함에 따라 구조도 진화할 수 있으므로, 리팩토링과 개선에 열린 자세를 유지하는 것이 좋습니다.

이제 Flutter 개발 환경 설정과 프로젝트 구조에 대한 이해를 바탕으로, 다음 챕터에서 Dart 언어 기초를 배워보겠습니다.