본문 바로가기

flutter

Flutter 시작하기: 크로스 플랫폼 앱 개발의 첫걸음

반응형

Dart 언어 기초를 배웠다면, 이제 Flutter로 실제 앱 개발을 시작해볼 차례입니다! Flutter가 무엇인지부터 첫 번째 앱 실행까지, 차근차근 따라해보겠습니다.

 

이 글에서 배우는 것

  • Flutter가 무엇이고 왜 사용하는지
  • 크로스 플랫폼 개발의 장점과 단점
  • Flutter 개발환경 완벽 설치 가이드
  • 첫 번째 Flutter 앱 생성과 실행
  • Hot Reload의 마법 체험하기

 

Flutter가 뭔가요?

Flutter는 Google에서 만든 크로스 플랫폼 앱 개발 프레임워크입니다. 하나의 코드로 안드로이드와 iOS 앱을 동시에 만들 수 있어요!

 

크로스 플랫폼이란?

전통적인 앱 개발 방식

  • 안드로이드: Java/Kotlin으로 개발
  • iOS: Swift/Objective-C로 개발
  • 결과: 같은 앱을 두 번 만들어야 함

 

Flutter 방식

  • 하나의 코드: Dart 언어로 작성
  • 두 플랫폼: 안드로이드 + iOS 동시 배포
  • 결과: 개발 시간 50% 단축!

 

네이티브 앱 vs 하이브리드 앱

구분 네이티브 앱 Flutter 앱
성능 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
개발 속도 ⭐⭐ ⭐⭐⭐⭐⭐
유지보수 ⭐⭐ ⭐⭐⭐⭐⭐
플랫폼 특화 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
학습 난이도 ⭐⭐⭐⭐ ⭐⭐⭐

 

Flutter의 장단점

장점

1. 빠른 개발 속도

기존: 안드로이드 개발 3개월 + iOS 개발 3개월 = 6개월
Flutter: 크로스 플랫폼 개발 4개월 = 2개월 단축!

 

2. Hot Reload

  • 코드 수정 → 즉시 화면에 반영 (1초 이내!)
  • 앱을 다시 시작할 필요 없음

 

3. 일관된 UI

  • 안드로이드와 iOS에서 똑같은 모습
  • Material Design과 Cupertino 디자인 모두 지원

 

4. 뛰어난 성능

  • 네이티브에 가까운 성능
  • 60fps 부드러운 애니메이션

 

5. 큰 커뮤니티

  • Google의 지속적인 지원
  • 풍부한 패키지와 라이브러리

 

단점

1. 앱 크기

  • 기본 Flutter 앱도 20MB 이상
  • 네이티브 앱보다 용량이 큼

 

2. 플랫폼별 기능

  • 최신 iOS/안드로이드 기능은 늦게 지원
  • 복잡한 네이티브 기능은 별도 구현 필요

 

3. 학습 곡선

  • Dart 언어 새로 배워야 함
  • Flutter만의 위젯 시스템 적응 필요

 

개발환경 설치 가이드

1단계: Flutter SDK 설치

Windows 사용자

  1. Flutter SDK 다운로드
    • flutter.dev 접속
    • "Get Started" 클릭
    • Windows용 Flutter SDK 다운로드
  2. 압축 해제
  3. C:\src\flutter\ 경로에 압축 해제 (공백이나 특수문자 없는 경로 권장)
  4. 환경변수 설정
    • 시스템 속성 → 고급 → 환경 변수
    • Path에 C:\src\flutter\bin 추가

 

macOS 사용자

  1. Flutter SDK 다운로드
  2. cd ~/development curl -O https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_arm64_3.x.x-stable.zip unzip flutter_macos_arm64_3.x.x-stable.zip
  3. PATH 설정
  4. echo 'export PATH="$PATH:`pwd`/flutter/bin"' >> ~/.zshrc source ~/.zshrc

 

설치 확인

flutter --version

 

성공하면 다음과 같이 출력됩니다.

Flutter 3.x.x • channel stable
Framework • revision xxx
Engine • revision xxx
Tools • Dart 3.x.x

 

2단계: Android Studio 설치

  1. Android Studio 다운로드
  2. Flutter 플러그인 설치
    • Android Studio 실행
    • File → Settings (macOS: Preferences)
    • Plugins → "Flutter" 검색 → 설치
    • Dart 플러그인도 함께 설치됨
  3. Android SDK 설정
    • Tools → SDK Manager
    • Android SDK Command-line Tools 설치
    • Android SDK Build-Tools 설치

 

3단계: 개발 환경 확인

flutter doctor

 

모든 항목이 ✅ 표시되어야 합니다.

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.x.x)
[✓] Android toolchain - develop for Android devices
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.x)
[✓] Connected device (1 available)
[✓] HTTP Host Availability

• No issues found!

 

❌ 표시가 있다면

flutter doctor --android-licenses  # Android 라이선스 동의

 

4단계: 가상기기(에뮬레이터) 설정

Android 에뮬레이터

  1. AVD Manager 실행
    • Android Studio → Tools → AVD Manager
  2. 가상기기 생성
    • "Create Virtual Device" 클릭
    • Phone → Pixel 7 선택 (권장)
    • System Image → 최신 API 레벨 선택
    • "Show Advanced Settings"에서 RAM 4GB 이상 설정
  3. 에뮬레이터 실행
    • 생성된 가상기기 옆 ▶️ 버튼 클릭

 

iOS 시뮬레이터 (macOS만 가능)

open -a Simulator

또는 Xcode → Window → Devices and Simulators

 

첫 번째 Flutter 앱 만들기

1단계: 프로젝트 생성

# 프로젝트 생성
flutter create my_first_app

# 프로젝트 폴더로 이동
cd my_first_app

# 앱 실행
flutter run

 

2단계: 프로젝트 구조 이해

my_first_app/
├── android/              # 안드로이드 네이티브 코드
├── ios/                  # iOS 네이티브 코드
├── lib/                  # 🎯 Dart 코드 (메인 개발 영역)
│   └── main.dart         # 앱의 시작점
├── test/                 # 테스트 코드
├── pubspec.yaml          # 패키지 설정 파일
└── README.md

 

3단계: main.dart 파일 살펴보기

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(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

 

4단계: 코드 구조 이해

1. main() 함수

void main() {
  runApp(const MyApp());  // 앱의 시작점
}

 

2. MyApp 클래스 (앱 전체 설정)

class MyApp extends StatelessWidget {
  // 앱의 테마, 제목, 첫 화면 등 설정
}

 

3. MyHomePage 클래스 (실제 화면)

class MyHomePage extends StatefulWidget {
  // 버튼 클릭으로 숫자가 증가하는 화면
}

 

Hot Reload

Hot Reload는 Flutter의 가장 강력한 기능 중 하나입니다.

 

Hot Reload 체험하기

  1. 앱 실행 상태에서 코드 수정↓ 변경
  2. const Text( '버튼을 누른 횟수:', ),
  3. const Text( 'You have pushed the button this many times:', ),
  4. 저장 (Ctrl+S 또는 Cmd+S)
  5. 1초 안에 화면이 바뀜!

 

Hot Reload vs Hot Restart

구분 Hot Reload Hot Restart
속도 ⚡ 1초 이내 🔄 3-5초
상태 유지 ✅ 유지 ❌ 초기화
사용 시기 UI 수정 구조적 변경
단축키 r R

 

실습: 첫 번째 앱 만들기

기본 카운터 앱을 나만의 스타일로 바꿔봅시다!

 

1단계: 제목 바꾸기

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '나의 첫 Flutter 앱',  // 📱 앱 제목 변경
      home: const MyHomePage(title: '홍길동의 카운터'),  // 🏠 화면 제목 변경
    );
  }
}

 

2단계: 색상 테마 바꾸기

theme: ThemeData(
  colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),  // 🎨 파란색 테마
  useMaterial3: true,
),

 

3단계: 텍스트 내용 바꾸기

const Text(
  '오늘 물 마신 횟수:',  // 💧 의미있는 카운터로 변경
),

 

4단계: 아이콘 바꾸기

floatingActionButton: FloatingActionButton(
  onPressed: _incrementCounter,
  tooltip: '물 마시기',
  child: const Icon(Icons.local_drink),  // 🥤 물 아이콘으로 변경
),

 

완성된 코드

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 앱',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: '홍길동의 물 마시기'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _waterCount = 0;

  void _drinkWater() {
    setState(() {
      _waterCount++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              '오늘 물 마신 횟수:',
              style: TextStyle(fontSize: 20),
            ),
            Text(
              '$_waterCount 잔',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            const SizedBox(height: 20),
            Text(
              _waterCount >= 8 ? '👏 목표 달성!' : '💪 더 마셔요!',
              style: const TextStyle(fontSize: 16),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _drinkWater,
        tooltip: '물 마시기',
        child: const Icon(Icons.local_drink),
      ),
    );
  }
}

 

개발 도구와 유용한 팁

VS Code에서 Flutter 개발

  1. Flutter Extension 설치
    • Flutter 확장 설치 (Dart도 함께 설치됨)
  2. 유용한 단축키
    • Ctrl+Shift+P: 명령어 팔레트
    • Flutter: Hot Reload: 빠른 새로고침
    • Flutter: Hot Restart: 앱 재시작

 

디버깅 도구

  1. Flutter Inspector
    • 위젯 구조를 시각적으로 확인
    • VS Code: View → Command Palette → "Flutter: Open Widget Inspector"
  2. DevTools
  3. flutter pub global activate devtools flutter pub global run devtools
  4. 에러 해결 명령어
  5. flutter clean # 캐시 정리 flutter pub get # 패키지 다시 설치 flutter doctor # 환경 점검

 

자주 만나는 에러와 해결법

1. "No connected devices"

문제: 에뮬레이터나 실제 기기가 연결되지 않음

해결:

# 연결된 기기 확인
flutter devices

# Android 에뮬레이터 실행
flutter emulators
flutter emulators --launch <emulator_id>

 

2. "Gradle build failed"

문제: Android 빌드 오류

해결:

cd android
./gradlew clean
cd ..
flutter clean
flutter pub get

 

3. "CocoaPods not installed" (macOS)

문제: iOS 의존성 관리 도구 없음

해결:

sudo gem install cocoapods
pod setup

 

4. Hot Reload가 안 될 때

원인과 해결:

  • 문법 에러: 빨간 밑줄 에러 먼저 수정
  • 구조적 변경: Hot Restart (R) 사용
  • main() 함수 변경: 앱 완전 재시작

 

Flutter 개발 베스트 프랙티스

1. 프로젝트 구조

lib/
├── main.dart           # 앱 시작점
├── screens/           # 화면들
│   ├── home_screen.dart
│   └── settings_screen.dart
├── widgets/           # 재사용 위젯
│   └── custom_button.dart
└── utils/            # 유틸리티 함수
    └── constants.dart

 

2. 코딩 컨벤션

// ✅ Good: 클래스명은 PascalCase
class MyHomePage extends StatelessWidget {}

// ✅ Good: 변수명은 camelCase
int waterCount = 0;

// ✅ Good: 상수는 lowerCamelCase
const double defaultPadding = 16.0;

// ✅ Good: 파일명은 snake_case
// home_screen.dart, custom_button.dart

 

3. 위젯 분리 습관

// ❌ Bad: 모든 코드를 한 곳에
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          // 100줄의 복잡한 위젯...
        ],
      ),
    );
  }
}

// ✅ Good: 위젯을 분리
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          WaterCountWidget(),
          DrinkButton(),
        ],
      ),
    );
  }
}

 

정리

축하합니다! 이제 Flutter 개발자의 첫걸음을 떼었습니다.

  • Flutter 이해: 크로스 플랫폼 앱 개발 프레임워크
  • 개발환경 구축: SDK 설치부터 에뮬레이터 설정까지
  • 첫 앱 실행: 기본 카운터 앱을 나만의 스타일로 변경
  • Hot Reload: 빠른 개발을 위한 핵심 기능
  • 기본 도구: 디버깅과 개발 효율성 향상

다음 단계에서는 Flutter 위젯의 기초를 배워서 더 다양하고 예쁜 화면을 만들어보겠습니다!

반응형