ram2 ๐Ÿš—

[flutter] ์ƒˆ๋กญ๊ฒŒ ๋ฐ”๋€ codelab (step1-step4) ๋ณธ๋ฌธ

๐Ÿ’ง flutter

[flutter] ์ƒˆ๋กญ๊ฒŒ ๋ฐ”๋€ codelab (step1-step4)

coram22 2023. 2. 7. 15:02
728x90
๋ฐ˜์‘ํ˜•

1. Introduction

ํ•™์Šตํ•  ๋‚ด์šฉ์€!

โœ…  flutter๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€์˜ ๊ธฐ์ดˆ

โœ…  flutter์—์„œ layout ๋งŒ๋“ค๊ธฐ

โœ…  ์•ฑ ๋™์ž‘๊ณผ user interaction์˜ ์—ฐ๊ฒฐ (์ข‹์•„์š” ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋Š” ๊ฒƒ์ด ๊ทธ ์˜ˆ)

โœ…  flutter ์ฝ”๋“œ๋ฅผ ์ •๊ฐˆํ•˜๊ฒŒ ์งœ๋Š” ๊ฒƒ

โœ…  ๋ฐ˜์‘ํ˜• ์•ฑ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ (screen ํฌ๊ธฐ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ๊ฒŒ ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ์Œ !)

โœ…  ์•ฑ์˜ ์ผ๊ด€๋œ ํ˜•ํƒœ์™€ ๋Š๋‚Œ์„ ์ฃผ๋„๋ก 

 

2. Set up your Flutter environment (flutter ํ™˜๊ฒฝ ์„ค์ •)

๐Ÿ“ Visual Studio Code ์‚ฌ์šฉ

codelab ๊ณต์‹ ๋ฌธ์„œ์—์„œ vscode๋ฅผ ๋‹ค์šด๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์—ฐ๊ฒฐํ•ด๋‘์—ˆ๋‹ค!

 

๊ณต์‹๋ฌธ์„œ ๋งํฌ โฌ‡๏ธ 

https://codelabs.developers.google.com/codelabs/flutter-codelab-first#1

 

Your first Flutter app  |  Google Codelabs

In this codelab, you’ll learn how to build a Flutter app that generates random, cool-sounding names.

codelabs.developers.google.com

 

๊ฐœ๋ฐœ ํƒ€๊นƒ ์„ค์ •ํ•˜๊ธฐ (๋‹ค์Œ ์ค‘ ์›ํ•˜๋Š” os๋ฅผ ์„ ํƒํ•˜๋ฉด ๋œ๋‹ค.)

flutter์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์ด์ž ํŠน์ง•์ธ ๋ถ€๋ถ„์ด๋‹ค.

multi-platform toolkit์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ์ฝ”๋“œ๋กœ ์„œ๋กœ ๋‹ค๋ฅธ os๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

os๋Š” ์ฃผ๋กœ ๊ฐœ๋ฐœํ•˜๊ณ  ์‹ถ์€ os๋ฅผ ์„ ํƒํ•˜๋ฉด ๋œ๋‹ค.

  • iOS
  • Android
  • Windows
  • macOS
  • Linux
  • web

์ด๋•Œ ์ง์ ‘ ๊ธฐ๊ธฐ๋ฅผ ์—ฐ๊ฒฐํ•ด์„œ ์‚ฌ์šฉํ•ด๋„ ๋˜๊ณ , simulator๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœํ•ด๋„ ๋œ๋‹ค.

(๋‚˜๋Š” ์•ฝ 80%๋ฅผ simulator๋กœ ๊ฐœ๋ฐœํ•œ๋‹ค!)

 

Flutter ์„ค์น˜ํ•˜๊ธฐ

Flutter SDK ์„ค์น˜๋Š” ๋‹ค์Œ ๊ณต์‹ ๋ฌธ์„œ์— ์ž์„ธํ•˜๊ฒŒ ์„ค๋ช…๋˜์–ด ์žˆ๋‹ค.

https://docs.flutter.dev/

 

Flutter documentation

Get started with Flutter. Widgets, examples, updates, and API docs to help you write your first Flutter app.

docs.flutter.dev

codelab์„ ์ง„ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ์˜ 3๊ฐ€์ง€๋งŒ ์žˆ์œผ๋ฉด ๋œ๋‹ค.

1. Flutter SDK

2. Visual Studio Code (Flutter plugin์ด ์„ค์น˜๋œ)

3. ๊ฐœ๋ฐœ ํƒ€๊นƒ์— ์š”๊ตฌ๋˜๋Š” software (์˜ˆ๋ฅผ ๋“ค์–ด, Visual Studio Code๋Š” Windows, Xcode๋Š” macOS)

 

(์ด ์™ธ์—, flutter SDK ์„ค์น˜๋‚˜ ํ™˜๊ฒฝ ์„ค์ •์— ์–ด๋ ค์›€์ด ์žˆ๋‹ค๋ฉด, codelab 2๋‹จ๊ณ„์—์„œ ๋ณด์—ฌ์ฃผ๋Š” StackOverflow๋ฅผ ์ฐธ๊ณ ํ•˜๊ธธ !)

 

3. Create a project

  • Visual Studio Code๋ฅผ ์‹คํ–‰ํ•˜๊ณ  command palette๋ฅผ Open. (  F1  ๋˜๋Š”  ctrl+Shift+P  ๋˜๋Š”  Shift+Cmd+P  )
  • "flutter new"๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ ๊ฒ€์ƒ‰๋œ Flutter: New Project ๋ฅผ ์„ ํƒํ•œ๋‹ค.
    • ๋งŒ์•ฝ flutter ํ™˜๊ฒฝ ์„ค์ •์ด ์ œ๋Œ€๋กœ ์ด๋ฃจ์–ด์กŒ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž˜ ๋œจ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Flutter: New Project ๋ฅผ ์„ ํƒํ•˜๊ณ  Appliction์„ ์„ ํƒํ•œ๋‹ค.
  • ๋‹ค์Œ์œผ๋กœ ํด๋”๋ฅผ ์ƒ์„ฑํ•˜๊ณ ์ž ํ•˜๋Š” ์œ„์น˜์™€, ํ”„๋กœ์ ํŠธ ์ด๋ฆ„์„ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
  • ๋งŒ์•ฝ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹ ๋ขฐ์™€ ๊ด€๋ จํ•œ ์ฐฝ์ด ๋œฌ๋‹ค๋ฉด Yes~~๋ฅผ ์„ ํƒ !

์ถœ์ฒ˜: https://codelabs.developers.google.com/codelabs/flutter-codelab-first#2

์—ฌ๊ธฐ๊นŒ์ง€ ํ–ˆ๋‹ค๋ฉด ์ด์ œ ๋ฐ”๋กœ Flutter ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค !!

 

codelab์„ ๋”ฐ๋ผํ•˜๊ธฐ ์œ„ํ•ด ์ฃ„์ธก ์ƒ๋‹จ์— ์žˆ๋Š” ์•„์ด์ฝ˜์„ ๋ˆ„๋ฅด๊ณ , pubspec.yaml ํŒŒ์ผ์„ ์„ ํƒํ•œ๋‹ค.

ํ•ด๋‹น ํด๋”์— ์žˆ๋Š” ๋‚ด์šฉ ์ค‘, ๊ฐ€์žฅ ์œ„ ๋‘ ์ค„์„ ์ œ์™ธํ•œ ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ์ง€์šด ๋’ค, ์ด ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•ด์„œ ๋ถ™์—ฌ๋„ฃ์–ด์ค€๋‹ค.

(name๊ณผ description๋ถ€๋ถ„์€ ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค !)

publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 0.0.1+1

environment:
  sdk: '>=2.18.4 <3.0.0'

dependencies:
  flutter:
    sdk: flutter

  english_words: ^4.0.0
  provider: ^6.0.0

dev_dependencies:
  flutter_test:
    sdk: flutter

  flutter_lints: ^2.0.0

flutter:
  uses-material-design: true

์ด pubspec.yaml์€ ์•ฑ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ํŒŒ์ผ์ด๋‹ค. ์ด ์•ฑ์˜ ํ˜„์žฌ ๋ฒ„์ „, dependencies, assets ๋“ฑ์˜ ์ •๋ณด๊ฐ€ ์žˆ๋‹ค.

 

  • ๋‹ค์Œ์€ ๊ฐ™์€ ์•„์ด์ฝ˜ ๋‚ด์— ์žˆ๋Š” analysis_options.yaml ํŒŒ์ผ์„ ๋ฐ”๊ฟ”์ค€๋‹ค.
    • ์•ˆ์— ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ์ง€์šฐ๊ณ , ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋ถ™์—ฌ๋„ฃ์–ด์ค€๋‹ค.
include: package:flutter_lints/flutter.yaml

linter:
  rules:
    prefer_const_constructors: false
    prefer_final_fields: false
    use_key_in_widget_constructors: false
    prefer_const_literals_to_create_immutables: false
    prefer_const_constructors_in_immutables: false
    avoid_print: false

์ด ํŒŒ์ผ์€ ์–ผ๋งˆ๋‚˜ ์—„๊ฒฉํ•˜๊ฒŒ ์šฐ๋ฆฌ๊ฐ€ ์ง  ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด์•ผ ํ•˜๋Š”์ง€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค. ์ด ๋ถ€๋ถ„์€ ์–ธ์ œ๋“ ์ง€ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ˜„์žฌ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ฒ˜์Œ ํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์‰ฝ๊ฒŒ ๋„˜์–ด๊ฐ€์ค˜~ ํ•˜๊ณ  ์ด์•ผ๊ธฐํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

 

- ๋งˆ์ง€๋ง‰์œผ๋กœ main.dart ํŒŒ์ผ์„ ๋ฐ”๊ฟ”์ค€๋‹ค. (์œ„์น˜๋Š” lib/main.dart)

ํŒŒ์ผ์— ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ์ง€์šฐ๊ณ , ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋ถ™์—ฌ๋„ฃ๊ธฐ ํ•œ๋‹ค.

import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => MyAppState(),
      child: MaterialApp(
        title: 'Namer App',
        theme: ThemeData(
          useMaterial3: true,
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
        ),
        home: MyHomePage(),
      ),
    );
  }
}

class MyAppState extends ChangeNotifier {
  var current = WordPair.random();
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var appState = context.watch<MyAppState>();

    return Scaffold(
      body: Column(
        children: [
          Text('A random idea:'),
          Text(appState.current.asLowerCase),
        ],
      ),
    );
  }
}

์ด์ œ ๋ชจ๋“  setting์ด ๋๋‚ฌ๋‹ค !!!!

์˜ค์˜ˆ !! ๐ŸŽ‰

 

๋ณธ๊ฒฉ์ ์œผ๋กœ ๋‹ค์–‘ํ•œ ์œ„์ ฏ๋“ค์„ ์‚ฌ์šฉํ•ด์„œ ์ง์ ‘ ์ฝ”๋“œ๋ฅผ ์งœ๋ณด์ž !!

 

4. Add a button

์ด์ œ Next button์„ ๋งŒ๋“ค์–ด๋ณด์ž !

.

.

๊ทธ ์ „์— ์•ฑ์„ Launchํ•ด๋ด์•ผ ํ•œ๋‹ค. 

๋จผ์ €  lib/main.dart  ๋ฅผ ์—ด์–ด target device๊ฐ€ ์„ ํƒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณธ๋‹ค.

vscode์˜ ์šฐ์ธก ํ•˜๋‹จ์„ ๋ณด๋ฉด ํ˜„์žฌ ์ง€์ •๋œ target device๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค๋ฉด, ์ด๋ฅผ ํด๋ฆญํ•ด์„œ ๋ฐ”๊พธ๋ฉด ๋œ๋‹ค.

๋‚˜๋Š” ๊ธฐ์กด์— ์—ฐ๊ฒฐํ•ด๋‘” ๊ธฐ๊ธฐ๊ฐ€ ์žˆ์–ด ๋ฐ”๋กœ ๊ทธ ๊ธฐ๊ธฐ๋กœ ์„ค์ •์ด ๋˜์–ด์žˆ์—ˆ๋‹ค. ๋งฅ์ด๋ผ๋ฉด ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์—ด์–ด ios ๊ธฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , android studio๋ฅผ ํ†ตํ•ด ์•ˆ๋“œ๋กœ์ด๋“œ ๊ธฐ๊ธฐ๋ฅผ ๋งŒ๋“ค์–ด ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ธฐ๊ธฐ๋ฅผ ์—ฐ๊ฒฐํ–ˆ๋‹ค๋ฉด ! ํ•œ ๋ฒˆ ์‹คํ–‰ํ•ด๋ณด์ž !!

 

์šฐ์ธก ์ƒ๋‹จ์— ์žˆ๋Š” ์‹คํ–‰๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค!

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋œจ๋ฉด ์•„์ฃผ์•„์ฃผ ์ž˜ ๋”ฐ๋ผ์˜จ ๊ฒƒ์ด๋‹ค !!!!

๋งŒ์•ฝ ์ฝ”๋“œ๋ฅผ ๋ฐ”๊พธ์—ˆ๋‹ค๋ฉด, Command+s ๋˜๋Š” Ctrl+s๋ฅผ ํ•˜๋ฉด ๋ฐ”๋กœ๋ฐ”๋กœ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ ‡์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์ฝ”๋“œ๋žฉ์—์„œ ์ œ์‹œํ•œ Hot Reload์— ๋Œ€ํ•œ stack overflow๋ฅผ ์ฐธ๊ณ ํ•˜๊ธธ !

 

์ด์ œ ์ง„์งœ ์ง„์งœ ์ง„์งœ ๋ฒ„ํŠผ์„ ๋งŒ๋“ค์–ด๋ณผ๊ฑฐ๋‹ค !!!

 

lib/main.dart

// ...

    return Scaffold(
      body: Column(
        children: [
          Text('A random AWESOME idea:'),
          Text(appState.current.asLowerCase),

          // ↓ Add this.
          ElevatedButton(
            onPressed: () {
              print('button pressed!');
            },
            child: Text('Next'),
          ),

        ],
      ),
    );

// ...

๋‹ค์Œ๊ณผ ๊ฐ™์ด scaffold ๋‚ด์— ์žˆ๋Š” Column์— ElevatedButton์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

์ด๋•Œ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ฝ˜์†”์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋œจ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด์ œ main.dart๊ฐ€ ์–ด๋–ป๊ฒŒ ์‹คํ–‰๋˜๋Š”์ง€๋ฅผ ์ดํ•ดํ•ด๋ณด์ž

lib/main.dart์˜ ๊ฐ€์žฅ ์ƒ๋‹จ์—์„œ ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ฐพ์•„๋ณผ ์ˆ˜ ์žˆ๋‹ค.

// ...

void main() {
  runApp(MyApp());
}

// ...

์šฐ๋ฆฌ๋Š” main() ์ด๋ผ๋Š” ์ด๋ฆ„์˜ ํ•จ์ˆ˜๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ํ•จ์ˆ˜ ๋‚ด์— ์žˆ๋Š” ์ฝ”๋“œ๋Š” MyApp์— ์ •์˜๋œ ์•ฑ์„ ์‹คํ–‰ํ•˜๋„๋ก Flutter์— ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

MyApp ํด๋ž˜์Šค๋Š” StatelessWidget์„ ํ™•์žฅํ•œ๋‹ค. ์œ„์ ฏ์€ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ๋ชจ๋“  flutter app์˜ ์š”์†Œ๋“ค์ธ๋ฐ, ์•ฑ ๊ทธ ์ž์ฒด๋„ ์œ„์ ฏ์ด๋‹ค.

MyApp์— ์žˆ๋Š” ์ฝ”๋“œ๋Š” ์ „์ฒด ์•ฑ์„ ๊ตฌ์„ฑํ•œ๋‹ค. ์ด๋Š” app-wide state(๋‚˜์ค‘์— ๋‹ค๋ฃฐ ์˜ˆ์ •!) ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์•ฑ์˜ ์ด๋ฆ„์„ ์ง“๊ณ , ์‹œ๊ฐ์  theme์„ ์ •์˜ํ•˜๊ณ , "home" ์œ„์ ฏ(๊ทธ๋Ÿฌ๋‹ˆ๊นŒ, ์•ฑ์˜ ์‹œ์ž‘ ์ง€์ )์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

lib/main.dart

// ...

class MyAppState extends ChangeNotifier {
  var current = WordPair.random();
}

// ...

flutter์—๋Š” app state๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋งŽ์€ ๋ฐฉ๋ฒ•๋“ค์ด ์žˆ๋‹ค. ๊ฐ€์žฅ ์‰ฝ๊ฒŒ ์ด์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š” ChangeNotifier์ด๋‹ค.

MyAppState๋Š” function์— ์•ฑ์ด ํ•„์š”๋กœ ํ•˜๋Š” data๋ฅผ ์ •์˜ํ•œ๋‹ค. 

  • state class๋Š” ๋ณ€ํ™”๋ฅผ ์•Œ๋ฆฌ๋Š” ChangeNotifier๋ฅผ ํ™•์žฅํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋งŒ์•ฝ ํ˜„์žฌ ๋‹จ์–ด๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋‹ค๋ฉด, ์•ฑ์— ์žˆ๋Š” ์–ด๋–ค ์œ„์ ฏ์ด ์ด๋ฅผ ์•Œ ํ•„์š”๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. 
  • MyApp์— ์‚ฌ์šฉํ–ˆ๋“ฏ์ด, ChangeNotifierProvider๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒํƒœ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์•ฑ์— ์ •๋ณด๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ด๋Š” ์•ฑ์— ์žˆ๋Š” ์–ด๋–ค ์œ„์ ฏ์ด๋ผ๋„ ์ด ์ƒํƒœ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.
  • ์ฆ‰, ์‰ฝ๊ฒŒ ์ด์•ผ๊ธฐํ•˜๋ฉด ChangeNotifier๋ฅผ MyAppState์— ์‚ฌ์šฉํ•˜๋ฉด, ์•ฑ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ณ€ํ™”๋“ค์„ ๋‹ค๋ฅธ ์œ„์ ฏ๋“ค์ด ์•Œ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
    • MyApp์ด ๊ฐ€์žฅ ์ƒ์œ„ ์œ„์ ฏ์ด๋ฉฐ, ChangeNotifier๋Š” ๋ณ€ํ™”๋ฅผ ์ธ์ง€ํ•˜๊ณ  ์ด๋ฅผ ์œ„์ ฏ์— ์•Œ๋ฆฌ๋Š” ์—ญํ• ์ž„์„ ์ดํ•ดํ•˜๋ฉด ๋” ์‰ฝ๋‹ค

๋งˆ์ง€๋ง‰์œผ๋กœ MyHomePage์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

์ด ์œ„์ ฏ์€ ์šฐ๋ฆฌ๊ฐ€ ์ด๋ฏธ ์ˆ˜์ •ํ•œ ์œ„์ ฏ์ด๋‹ค. ๊ณต์‹๋ฌธ์„œ์—์„œ ์„ค๋ช…ํ•œ ๋‚ด์šฉ์„ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์™€์„œ ์กฐ๊ธˆ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•  ๊ฒƒ์ด๋‹ค.

// ...

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {           // ← 1
    var appState = context.watch<MyAppState>();  // ← 2

    return Scaffold(   // ← 3
      body: Column(    // ← 4
        children: [
          Text('A random AWESOME idea:'),        // ← 5
          Text(appState.current.asLowerCase),    // ← 6
          ElevatedButton(
            onPressed: () {
              print('button pressed!');
            },
            child: Text('Next'),
          ),
        ],      // ← 7
      ),
    );
  }
}

// ...
  1. ๋ชจ๋“  ์œ„์ ฏ์€ ์œ„์ ฏ์˜ ํ™˜๊ฒฝ์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋˜์–ด ์œ„์ ฏ์ด ํ•ญ์ƒ ์ตœ์‹  ์ƒํƒœ๋ฅผ ๊ฐ–๋„๋ก ํ•˜๋Š” build() method๋ฅผ ์ •์˜ํ•œ๋‹ค.
  2. watch method๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ฑ์˜ ๋ณ€ํ™”๋ฅผ ์ถ”์ ํ•˜๊ณ , ์•ฑ์˜ ํ˜„ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•œ๋‹ค.
  3. ๋ชจ๋“  build ๋ฉ”์„œ๋“œ๋Š” ์œ„์ ฏ ๋˜๋Š” ์ค‘์ฒฉ๋œ ์œ„์ ฏ ํŠธ๋ฆฌ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ด ๊ฒฝ์šฐ ์ตœ์ƒ์œ„ ์œ„์ ฏ์€ Scaffold์ด๋‹ค. Scaffold๋Š” ์‹ค์ œ๋กœ ๊ต‰์žฅํžˆ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋ฉฐ, main.dart์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ๋œ๋‹ค.  return Scaffold(); 
  4. Column์€ ์•„์ฃผ ์ž์ฃผ ์“ฐ์ด๋ฉด์„œ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ layout widget์ด๋‹ค. ์ด ์œ„์ ฏ์€ ๋งŽ์€ ์ˆ˜์˜ children์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์œ„์—์„œ๋ถ€ํ„ฐ ์•„๋ž˜๋กœ ๋ฐฐ์น˜ํ•œ๋‹ค. default๋กœ column์€ ์ขŒ์ธก ์ƒ๋‹จ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š”๋ฐ, ์ด๋ฅผ center๋กœ ๋ฐ”๊ฟ”์ค„ ์ˆ˜ ์žˆ๋‹ค. (๋’ค์—์„œ ๋‹ค๋ฃฐ ์˜ˆ์ •)
  5. Text("")์˜ ํ˜•ํƒœ๋กœ ์“ฐ์ด๋ฉฐ, "" ์•ˆ์— ์›ํ•˜๋Š” ๋ฌธ์ž์—ด์„ ๋„ฃ์œผ๋ฉด ๊ทธ๋Œ€๋กœ ํ™”๋ฉด์— ๊ทธ๋ ค์ง„๋‹ค.
  6. ์ด Text ์œ„์ ฏ์€ appState๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ์ด ํด๋ž˜์Šค์˜ member์—๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. (์—ฌ๊ธฐ์—์„œ๋Š” current). 
    WordPair์€ asPascalCase, asLowerCase ๋˜๋Š” asSnakeCase์™€ ๊ฐ™์ด ์œ ์šฉํ•œ getter๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  7. flutter์—๋Š” ๊ด„ํ˜ธ๊ฐ€ ๊ต‰์žฅํžˆ ๋งŽ์ด ์“ฐ์ด๋Š”๋ฐ, ์‰ผํ‘œ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ํ•˜์ง€๋งŒ, vscode์—์„œ๋Š” ์‰ผํ‘œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ๋ถ„ํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์ž๋™์ •๋ ฌ์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์„ ํƒ์— ๋”ฐ๋ผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ๋‚˜๋Š” ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ๋ฐ, ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง€๋Š”๊ฒŒ ์‹ซ์€ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ๊ตฌ๋ถ„์ด ํ•„์š”ํ•  ๊ฒฝ์šฐ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด๋‹ค.

 

์ง์ ‘ ํ•ด๋ณด์ž

MyAppState๋กœ ๊ฐ€์„œ getNext method๋ฅผ ์ถ”๊ฐ€ํ•ด๋ณด์ž.

lib/main.dart

// ...

class MyAppState extends ChangeNotifier {
  var current = WordPair.random();

  // ↓ Add this.
  void getNext() {
    current = WordPair.random();
    notifyListeners();
  }
}

// ...

getNext() ๋ฉ”์†Œ๋“œ๋Š” current์— ์ƒˆ๋กœ์šด ๋žœ๋ค WordPair๋ฅผ ์žฌํ• ๋‹นํ•ด์ค€๋‹ค. ๋˜ํ•œ ์ด๋ฅผ notifyListeners()๋ผ ๋ถ€๋ฅด๋Š”๋ฐ, (ChangeNotifier์˜ ๋ฉ”์†Œ๋“œ ์ค‘ ํ•˜๋‚˜์ด๋‹ค.)์ด๋Š” MyAppState๋ฅผ ๋ณด๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆผ์„ ์ค€๋‹ค.

 

 

 

lib/main.dart

// ...

    ElevatedButton(
      onPressed: () {
        appState.getNext();  // ← This instead of print().
      },
      child: Text('Next'),
    ),

// ...

์ด์ œ Next ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค ๋‹จ์–ด๊ฐ€ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค !!!

 

์ƒ๊ฐ๋ณด๋‹ค ๋„ˆ๋ฌด ๊ธธ์–ด์ ธ์„œ ๋‹ค์Œ ๋‹จ๊ณ„๋Š” ๋‹ค์Œ ๊ธ€์— ์ ์–ด์•ผ๊ฒ ๋‹ค !!

 

ํ•„์š”ํ•œ ์‚ฌ๋žŒ์ด ์žˆ์„์ง€ ๋ชฐ๋ผ codelab์˜ step1~step4๊นŒ์ง€์˜ lib/main.dart ์ „์ฒด ์ฝ”๋“œ์ด๋‹ค.

import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => MyAppState(),
      child: MaterialApp(
        title: 'Namer App',
        theme: ThemeData(
          useMaterial3: true,
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
        ),
        home: MyHomePage(),
      ),
    );
  }
}

class MyAppState extends ChangeNotifier {
  var current = WordPair.random();

  void getNext() {
    current = WordPair.random();
    notifyListeners();
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var appState = context.watch<MyAppState>();

    return Scaffold(
      body: Column(
        children: [
          Text('A random idea:'),
          Text(appState.current.asLowerCase),
          ElevatedButton(
            onPressed: () {
              appState.getNext(); // ← This instead of print().
            },
            child: Text('Next'),
          ),
        ],
      ),
    );
  }
}
728x90
๋ฐ˜์‘ํ˜•