전편에 이어서 다 했다면
위 사진처럼 잘 뜰 것이다. 핫로딩이 되는 모습을 볼 수 있다.
이제 Hello Flutter를 출력해보자.
만들었던 Flutter 초기 단계에서 main()
빼고 지우고, 새로 시작하자.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
그러면 위처럼 남을 것이다.
일단 runApp()
이란 아래 사진과 같다.
runApp
은 Widget이라는 것을 argument로 받는다. 여기서 Widget은 리액트의 컴포넌트라고 생각하면 된다.
리액트가 CDD 방식으로 컴포넌트를 조합해서 만든다면, 플러터는 위젯이라는 레고 블럭을 가지고 만든다. 쉽지않는가? 플러터 공식문서나 다른 플러터 커뮤니티에서 만든 위젯을 또 가져올 수도 있다. 리액트의 재사용성을 활용한 셈.
즉, 위젯은 사용자 인터페이스를 구성하는 기본적인 빌딩 블록이다. 위젯은 UI 요소의 불변성을 나타내며, 위젯 트리를 구성하기 위해 조합하여 사용된다. 위젯은 화면에 그려지고 레이아웃에 배치되며, 사용자와의 상호 작용을 처리하기 위해 이벤트를 처리할 수 있다.
여기서 Stateful과 Stateless한 위젯으로 나뉘게 된다.
상태를 가지지 않고 정적으로 변하지 않는 위젯이다. 한 번 생성된 후에는 내부 상태가 변경되지 않으며, 외부에서 전달된 속성에 따라 UI를 렌더링한다. 단순하게 무언가를 화면에 띄워주기만 하는 역할.
예를 들어, 레이블 또는 아이콘과 같은 단순한 UI 요소는 StatelessWidget으로 구현될 수 있다.
상태를 가지고 동적으로 변할 수 있는 위젯이다. 사용자의 상호 작용이나 시간에 따른 변화에 따라 내부 상태가 변경되고 UI가 업데이트된다.
예를 들어, 사용자 입력에 따라 상태가 변경되는 폼이나 인터랙티브한 위젯은 StatefulWidget으로 구현될 수 있다.
또한, 위젯은 계층적으로 구성될 수 있고, 상위 위젯과 하위 위젯 사이의 관계를 형성한다. 이 계층 구조를 사용하여 복잡한 UI를 구성할 수 있다.
App
만들기즉, 우리가 화면 상 보이는 요소를 렌더링을 하려면 그냥 클래스가 아닌 위젯을 받은 클래스를 만들어야한다는 것이다.
이제 차이를 알았으니 상태가 없는 정적 클래스 App
을 만들어보자.
그랬더니 이렇게 나오네? StatelessWidget.build
메소드를 구현하지 않았다는 것이다.
즉, StatelessWidget
은 추상클래스이며 우리는 이 것을 상속 받았기에 꼭꼭 bulid
메소드를 구현해야한다는 것이다.
자주 쓰는 메소드이기에 VSC가 자동완성으로 알아서 해준다.
...
class App extends StatelessWidget {
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
build
가 정의됨.@override
이 사용StatelessWidget
의 build
를 우선하게끔 재정의abstract class StatelessWidget extends Widget {
const StatelessWidget({ super.key });
StatelessElement createElement() => StatelessElement(this);
Widget build(BuildContext context);
}
위 코드는 StatelessWidget
가 정의된 코드이다. build
가 있기 때문에 상속받은 App
도 만들어야한다.
이제 됐고, 우리가 쓴 클래스 App
이 이것은 애플리케이션의 시작점이 되는 Root 위젯이 됐다. 이 위젯이 뭘 return
해서 화면에 렌더링 할 것이냐가 중요하다.
또한 루트 위젯은 2가지 선택을 리턴해야하는데
즉, 구글이냐 애플이냐의 어떤 Family 스타일로 사용할 건지 플러터에게 말해주는 것이다.
class App extends StatelessWidget {
Widget build(BuildContext context) {
// 1.
return MaterialApp();
// 2.
return CupertinoApp();
}
}
이렇게 말이다. 중요한 점이 우리만의 UI 디자인을 가지고 싶다고 해도 시작점을 정해주고, 재료를 줘야한다는 것이다. 스타팅 포인트를 지정해주는 것과 같다.
플러터는 구글에서 만들었기에 당연히 Material 디자인이 훨씬 이쁘고 많이 쓰인다! 활용도도 높기에 구글 느낌을 빼고 커스텀도 보다 쉽게 가능하다.
나도 Material로 정했다.
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp();
}
}
이제 MaterialApp()
의 소속된 멤버에 맞춰서 개발해야한다.
class MaterialApp extends StatefulWidget {
/// Creates a MaterialApp.
const MaterialApp({
super.key,
this.navigatorKey,
this.scaffoldMessengerKey,
// home이 중요!
this.home,
Map<String, WidgetBuilder> this.routes = const <String, WidgetBuilder>{},
this.initialRoute,
this.onGenerateRoute,
this.onGenerateInitialRoutes,
this.onUnknownRoute,
List<NavigatorObserver> this.navigatorObservers = const <NavigatorObserver>[],
this.builder,
this.title = '',
this.onGenerateTitle,
this.color,
this.theme,
this.darkTheme,
this.highContrastTheme,
...
겁나 많다. 그 중 home
을 가져와서 출력을 해볼 것이다.
class App extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: ,
);
}
}
위 같이 써주니 아래와 같이 에러가 뜬다.
home
은 위젯이고 위젯이니 또 그 안에 무안 갈 넣어줘야한다.
class App extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Text('Hello Flutter!'),
);
// return CupertinoApp();
}
}
이렇게 Text를 넣어줬다! 결과를 보자.
겁나 못생겼다. 그 이유는 또다른 플러터 규칙인 Scaffold
가 필수이고, 지금은 없기 때문이다.
Scaffold
는 건축 비계를 뜻하는데 기초 건설을 의미한다.
위 사진이 건축 비계, Scaffold
다.
한마디로 Scaffold
는 화면의 구성 및 구조에 관한 것들을 가지고 있는 아주 멋진 위젯이다.
건축처럼 플러터에서 모바일 앱 화면에 보여지는 모든 요소, 위젯은 Scaffold
가 필수다.
Scaffold
는 클래스로서 애플리케이션의 기본적인 구조와 일반적인 머티리얼 디자인 요소를 제공하며, 앱의 상단 바, 하단 탐색 바, 드로어어, 플로팅 액션 버튼 등을 구성할 수 있다.
AppBar
: AppBar
는 상단 바를 나타내는 위젯으로, 타이틀, 액션 버튼, 백 버튼 등을 포함.Body
: Body
는 애플리케이션의 주요 콘텐츠를 표시하는 위젯. 일반적으로 ListView
, Column
, Container
등과 같은 다른 레이아웃 위젯과 함께 사용.BottomNavigationBar
: BottomNavigationBar
는 하단 탐색 바를 나타내는 위젯으로, 여러 개의 탭을 가질 수 있음. 사용자가 탭을 선택할 때마다 해당 탭의 콘텐츠가 표시.Drawer
: Drawer
는 앱의 왼쪽에서 오른쪽으로 슬라이드되는 사이드 메뉴를 나타내는 위젯. 주로 앱의 설정이나 추가 메뉴 옵션을 표시하는 데 사용.FloatingActionButton
: FloatingActionButton
은 주로 하단 탐색 바 위에 위치하며, 빠른 작업을 수행하기 위한 원형 아이콘 버튼을 나타냄.Scaffold
위젯은 이러한 구성 요소들을 조합하여 애플리케이션의 기본적인 레이아웃을 구성한다. 이를 통해 일반적인 앱 구조와 사용자 인터페이스 요소를 쉽게 구현할 수 있다.
그러면 이제 추가해보자!
class App extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My Flutter'),
),
body: Center(
child: Text('Hello Flutter!'),
),
),
);
}
}
벌써 괄호 줄세우기로 어질어질 한데 일단 보자.
home
위젯에 Scaffold
클래스이자 위젯 추가appBar
라는 위젯을 불러오고, AppBar
라는 클래스(위젯) 추가AppBar
요소인 title
에 Text 추가body
속성 추가 Center
위젯 추가child
속성 추가 및 Text 추가이렇게 해서 결과물은!?
짠! 이뻐졌다! 이렇게 간단하고 쉽게 만들 수 있다.
그 안에 어떤 요소가 있고 어떻게 사용해야하는지는 전체 암기를 안해도 되지만 자주 쓰이는 것들은 숙지해놓자.
flutter create toolfix
App
선언App
을 루트 위젯으로 만들기 위해 StatelessWidget
상속build
메소드를 만들어야하기에 build
자동완성 작성App
위젯이 루트 위젯이기 때문에 Family 스타일 return : MaterialApp()
MaterialApp()
의 멤버를 살펴보고 속성 home
을 작성해 렌더링home
작성 뒤 화면에 보여줄 때 필수인 Scaffold
작성Scaffold
의 하위 속성들을 작성하여 appBar
및 body
작성AppBar
: appBar
속성에 작성, 상단바를 만들 수 있는 위젯title
: 상단바의 제목Center
: 메인 콘텐츠를 작성하는 곳인 body
에 작성, 가운데 정렬 가능한 위젯child
: Center
에 포함될 위젯 작성Text
: String
등을 받는 텍스트 위젯처음으로 플러터에서 출력을 해봤는데 ㄹㅇ 파면 팔수록 미친 겁나 많은 위젯들이 나온다. OOP의 정수 플러터 답다.
심지어 만든 개발자가 변태인지 위젯, 클래스들을 넣고 마우스 오버를 하면 넣을 수 있는 속성들은 물론이고 설명을 일일이 다 해놨다. 이래서 플러터의 DX가 최고 수준이라고 하는구나 생각했다. 다양한 걸 활용하니 재밌어지겠다 ㅎㅎ
또 알아둬야할 것이 우리는 위젯이니, 위젯의 속성을 가져오느니 이런 얘기들을 했지만 핵심은 전부 클래스를 사용하는 것이다.
저렇게 사용하는 것이 Named 클래스를 사용하는 것과 똑같기에 겁먹지말고 그 클래스들의 Constructure를 잘 사용해보자.
고생하셨네요 플러터 dart 어렵네요 ㅠ