[Flutter] First Flutter App !

Juppi·2023년 2월 13일
2

Flutter 개발 일지

목록 보기
3/7
post-thumbnail

플러터 공식 문서 튜토리얼인 코드랩을 따라 수행한 내용을 기술한 글입니다.

오늘 만들어 볼 플러터 앱은 "newstay", "lightstream", "mainbrake", "graypine" 같은 멋진 이름을 자동으로 생성해주는 심플한 어플리케이션이다.

실습을 통해 배우게 될 것

✅ The basics of how Flutter works
✅ Creating layouts in Flutter
✅ Connecting user interactions (like button presses) to app behavior
✅ Keeping your Flutter code organized
✅ Making your app responsive (for different screens)
✅ Achieving a consistent look & feel of your app

1. 플러터 새 프로젝트 만들기 (with VS Code)

명령 팔레트(Shift+Cmd+P) 열고 순서대로 작성 및 선택하기
flutter new 입력 -> Flutter : New Project -> Application 선택

초기 앱 복사 및 붙여넣기

vs code 왼족 창 탐색기에서 pubspec.yaml 파일을 선택해서 아래 내용으로 바꾸기

첫 줄에 name은 설정한 프로젝트 이름으로 바꿔줘야한다❗️
name: namer_app
description: A new Flutter project.

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

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

마지막으로 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});

  
  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 {
  
  Widget build(BuildContext context) {
    var appState = context.watch<MyAppState>();

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

우측 하단에서 대상 장치 선택 후, 디버그 모드로 실행하기


2. 버튼 추가하기

다음으로 두번째 Text 인스턴스 바로 아래에 있는, Column의 하단에 button을 추가한다
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'),
          ),

        ],
      ),
    );

// ...

💡 Flutter 5분 뿌시기

Flutter가 어떻게 작동하는지 이해해보자.

lib/main.dart

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

파일의 상단에는 main() 함수가 있다. 위 코드는 Flutter에게 MyApp에 정의된 앱을 실행하라고 지시하는 역할만 수행한다.

lib/main.dart

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

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

MyApp 클래스는 StatelessWidget을 상속받아서 확장된다. 위젯은 모든 Flutter 앱을 빌드하는데 사용되는 요소이고, 앱 자체도 위젯이다.

나중에 StatelessWidgetStatefulWidget 에 대한 내용을 다룰 예정이다.

MyApp의 코드는 전체 앱을 설정한다. app-wide state를 만들고, 앱 이름을 지정하고, 시각적 테마를 정의하고, 앱의 시작점인 "Home" 위젯을 설정한다.

lib/main.dart

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

다음으로 MyAppState 클래스는 app's...well...state를 정의한다..응..? Flutter에서 앱 상태를 관리하는 방법이 많이 존재한다. 설명하기 가장 쉬운 것 중 하나는 이 앱에서 사용하는 접근 방식인 ChangeNotifier이다.

  • MyAppState 는 앱이 작동하는데 필요한 데이터를 정의한다. 지금은 임의의 단어 쌍이 있는 단일 변수 current 만 포함한다.
  • state class는 ChangeNotifire를 확장한다. 즉, 자신의 변경 사항을 다른 위젯에게 알릴 수 있다. 예를 들어, 현재 단어 쌍이 변경되면 앱의 일부 위젯이 알아야한다.
  • state는 ChangeNotifierProvider를 사용하여 전체 앱에 생성되고 제공된다. 이렇게 하면 앱의 모든 위젯이 state를 유지할 수 있다.

lib/main.dart

// ...
class MyHomePage extends StatelessWidget {
  
  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
      ),
    );
  }
}
// ...

마지막으로, 이미 수정한 위젯인 MyHomePage가 있다. 아래의 번호가 매겨진 각 줄은 위 코드의 줄 번호 주석에 매핑된다.

  1. 모든 위젯은 위젯이 항상 최신 상태를 유지하도록 위젯의 상황이 바뀔 때마다 자동으로 호출되는 build() 메서드를 정의한다.
  2. MyHomePage 는 watch 메서드를 사용해서 앱의 현재 상태에 대한 변경 사항을 추적한다.
  3. 모든 build 메서드는 위젯 또는 중첩된 위젯 트리를 반환해야한다. 이 경우 최상위 위젯은 Scaffold이다.
  4. Column은 Flutter 에서 가장 기본적인 레이아웃 위젯 중 하나이다. 원하는 수의 children을 가져와 위에서 아래로 넣는다. 기본적으로 Column은 시각적으로 하위 항목을 맨 위에 배치한다.
  5. 첫번째 단계에서 해당 Text 위젯을 변경했다.
  6. 이 두 번째 Text 위젯은 appState를 사용하고, 해당 클래스의 유일한 멤버인 current에 액세스한다. WordPairasPascalCase, SnakeCase와 같은 몇가지 유용한 getter를 제공한다.
  7. Flutter 코드가 어떻게 후행 쉼표(trailing commas)를 많이 사용하는지 주목하자. children이 이 특정 Column 매개변수 목록의 마지막 구성원이기 때문에 이 특정 쉼표는 여기에 있을 필요가 없다. 하지만 일반적으로 후행 쉼표는 사용하는 것이 좋다. 쉼표가 더 많은 멤버를 추가하기 좋게 만들고, Dart의 자동 서식 지정 도구가 줄 바꿈을 추가하도록 힌트 역할을 한다. 자세한 내용은 코드 서식을 참고하자

reference

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

profile
잠자면서 돈버는 그날까지

0개의 댓글