*주의 : 이 강의는 비전공자의 이해를 돕기 위한 강의로 실제내용을 각색했음을 알립니다. 맛보기이니 외우려 하지 마시고 천천히 훑어보기만 하세요!
이어서 MaterialApp에 대해 알아보죠. 지난 시간에 Material이 건축양식이라고 말씀드렸죠? MaterialApp은 그 양식에 맞춰 만든 앱이라는 뜻이 됩니다. 이 양식에 따르면 몇 가지 필요로 하는 정보가 있어요. 예를 들면 건물 이름이, 건물 테마, 인테리어죠.
MaterialApp의 괄호 안에 title이라고 적혀 있는 게 바로 (건물 이름 = 프로젝트 이름)인데요. 어디 다른데에 노출되는 정보는 아닙니다. 그저 여러분의 앱 이름이 무엇인지 적어놓을 뿐이에요. 그 다음에 theme이라고 적힌 게 바로 (건물 테마 = 앱의 테마)입니다. 앱 전체에 사용될 컬러들을 미리 저장해두고 갖다 쓰는거죠. 여러분이 미술 수업을 위해 파레트에 미리 짜놓아서 굳은 물감들 처럼요!
앱은 벽이 유리로 된 투명한 건물입니다. 그래서 건물 내부의 인테리어가 훤히 보이죠. 여러분이 플러터로 코딩을 한다는 건 이 건물 안에 레고 조각(위젯)들로 인테리어 작업을 한다고 보시면 됩니다. 예제에 쓰인 MyHomePage는 여러분의 집이구요. 여러분 집에 title(이름)이 필요하다고 하는데요, 왜 title을 필요로 하는지 알아볼까요?
내 집 MyHomePage가 알고 보니 생각이 있는 아이(StatefulWidget)였다고 하네요! 생각 없는 아이(StatelessWidget)랑 비슷하게 생겼어요. (StatefulWidget의 매운맛을 보려면 오른쪽 링크를 누르세요. https://mingzan.tistory.com/259)
1. const MyHompage = 영원히 바뀌지 않을 내 집이고.
2. Key? key = 이 집에 이름이 있나?
3. : super(key: key) 없으면, 부모님 이름을 그대로 쓰겠다.
근데 자세히 보니까 다른 점이 몇 군데 있죠?
const MyHomePage({Key? key, required this.title}) : super(key: key);
갑자기 , required this.title 가 생겼다.
이 생각 있는 아이는 이 집의 이름이 뭔지 반드시 알아야겠대요. 이유는 모르겠지만 반드시 알아야겠다 싶을땐 required를 써요. 해석하면 (this.title = 이 집의 이름이 필요하다), (required this.title = 이 집의 이름이 반드시 필요하다)는 얘기죠.
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
갑자기 final String title; 가 생겼다.
title(이름)이 반드시 필요한데, 한 번 알려주면 끝까지 그렇게 알고 있겠대요. 끝까지 그렇게 알고 있겠다고 할 때 final을 써요. 이름을 숫자로 지을 사람은 별로 없으니 당연히 문자겠죠? String은 문자를 의미해요. 위에서 저렇게 꼭 required로 알고 싶다고 했을 땐, 의견을 덧붙이지 않고 끝까지 그 문자 그대로 알고 있겠다고 말해주는 거예요. final 끝까지 알고 있겠다. String 문자인 title 집이름을;
{} 괄호처럼 심부름 내용을 설명하는 게 아니라면 ;을 쓰는데요. ;는 선언한다는 뜻입니다.
언제 뭘 써야할지 헷갈리셔도 괜찮아요. Visual Studio Code에서 다 알려주거든요! 아래는 ;를 써야하는데 ;가 안 쓰여있을 때 저렇게 알려줍니다. 저런 메시지를 보면 코드 마지막에 ;를 써주세요.
아래는 {}로 심부름 내용이 쓰여야 하는데 아무것도 안 써져 있을 때 저렇게 알려주죠. 저런 메시지를 보면 괄호를 열고 { 여기에 심부름 내용을 쓰시고 } 괄호를 닫아주세요.
@override
State<MyHomePage> createState() => _MyHomePageState();
뭔지 모르겠는게 하나 생겼는데요. 이 코드를 해석하자면 생각을 새로 만들어주는 겁니다. 왜 새로 만들어줘야 할까요? 여러분이 누군가를 설득할 때 그 사람의 생각만 바꾸면 되지, 그 사람의 유전자부터 하나씩 뜯어서 새로운 사람을 만들 필요는 없기 때문이에요. State는 생각 또는 상태라고 생각하시면 됩니다. 생김새는 생각 없는 아이와 같지만 생각을 만들어주는 걸 이 코드로 하는거죠. _MyHomePageState라는 게 또 새로 생겼는데 이건 뭔지 알아볼까요?
MyHomePage의 생각과 생김새가 써진 코드입니다.
int _counter = 0;
이 아이는 숫자를 세고 있어요. _counter라는 게 숫자 몇 인지 세고 있죠. 0부터 시작하고 있네요. 그외에 다른 걸 생각하고 있지는 않고 있습니다. 생각하는 것들은 보통 build 심부름 위에 써져 있거든요.
void _incrementCounter() {
setState(() {
_counter++;
});
}
여러분이 알고 있는 심부름이 등장했네요! build위에 써져 있으니까 이 심부름을 할 생각을 하고 있는 거예요. void니까 그냥 시키는 건데요. 심부름 이름을 보니까 카운터를 증가시키라네요. 괄호 안의 내용을 볼까요?
setState(() {
_counter++;
});
setState라는 심부름을 다시 시키는데요. setState는 이 아이가 생각을 다시 바꾸는 거예요. 더하기가 2개 이어져있는 ++는 1 더하기와 같은 말이에요. (_counter = _counter + 1;) 이거랑 같은 의미죠. 이 심부름을 한 번 하면 아까 0이었으니까 1을 더해서 1이 되겠네요. 심부름을 한 번 더하면 2가 되겠죠!
아까 나왔던 (build = 건물을 만드는 심부름)이 나왔네요. 이 아이의 겉모습은 여기에 써있는 재료대로 생겼을 거예요. 하나씩 살펴보죠.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
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.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
Scaffold부터 살펴보죠. Scaffold가 심부름 결과로 다시 가져와지는 걸 보니 Scaffold는 위젯(건물)인가 봅니다. 이 건물은 3가지로 구성되어 있는데요. 지붕(appBar), 건물 내부(body), 초인종(floatingActionButton) 이렇게 3가지네요.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(),
floatingActionButton: FloatingActionButton(),
);
}
appBar 지붕부터 살펴보죠. AppBar라는 레고 조각을 이용해서 지붕을 만들었는데요. 이 지붕에는 건물 이름을 쓸 모양인가 봅니다. 이름(title)을 필요로 하고 있어요. 이 이름에는 문자를 바로 쓰지 않고 Text라는 간판 위젯이 필요하네요. 지붕에 그냥 글씨를 쓸 수는 없겠죠.
appBar: AppBar(
title: Text(widget.title),
),
간판 안에는 widget.title이라고 쓰여있는데요. 아까 이 아이가 꼭 필요하다고 했던 이름 기억나세요?
final String title;
아까 물어봤던 이 이름을 쓰는데요. 이건 이 아이가 스스로 생각하고 있던게 아니라 물어봐서 안 거였죠? 물어봐서 안 것들은 앞에 widget. 을 붙여줘야 해요. 아까 알게 된 Flutter Demo Home Page가 지붕에 써있죠?
다음은 지붕 아래의 건물 내부의 모습인데요. 뭐가 많죠? 하나씩 볼게요.
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.headline4,
),
],
),
),
이 Center라는 위젯은 모든 위젯들을 가운데로 모아주는 역할을 해요. 무중력상태로 말이죠. 플러터에서는 그런 일이 가능하답니다!
대부분 위젯들은 child라는 걸 필요로 합니다. 레고 조각을 보시면 하나의 레고 조각을 가지고 완성품이라고 하지 않죠? 부품과 부품들을 연결해서 하나의 자동차가 완성되는 것과 같습니다. 이 Center라는 위젯 안에 또 인테리어를 할 위젯을 필요로 하죠. 그걸 자식 위젯(child)이라고 부릅니다.
Center(
child: Column()
)
이 Column이라는 위젯은 젠가처럼 위젯들을 세로로 쌓아주는 역할을 해요. 웃긴 건 위에서부터 쌓을 수 있다는 점이죠.
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
글자가 위에 써진 순서 그대로 위에서 아래로 쌓이고 있죠?
mainAxisAlignment: MainAxisAlignment.center,
이 말은 위젯들을 세로로 쌓을 건데 풍선처럼 지붕에 붙어 있게 쌓을 건지, 무중력상태로 가운데에 쌓을 건지, 중력 있게 바닥에 쌓을 건지 정하는 거예요. 이 집에서는 무중력처럼 가운데에 쌓게 했네요. 그래서 화면 한 가운데에 문자들이 있는 거랍니다!
여러개의 위젯을 쌓을 땐 children이라는 표현을 쓰는데요. 이 [] 괄호 안에 있는 게 바로 자식 위젯들입니다. Text 위젯 2개가 자식 위젯이 되는거고, Column 위젯은 이 Text위젯 2개의 부모 위젯이 되는 거죠. 이 자식 위젯 2개가 서로 다른 점이 있습니다.
Column(
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
)
하나는 절대 변하지 않는 문자가 쓰여 있습니다. 초인종을 몇 번 눌렀는지 알려주는 안내판 글자인데요. 이 안내판 글자를 굳이 바꿀 필요는 없겠죠. 그래서 영원히 변하지 않는다는 const가 쓰여 있습니다.
const Text(
'You have pushed the button this many times:',
),
근데 다른 하나는 변하는게 있습니다. 바로 $_counter죠. 아까 아이가 0으로 생각하고 있던 그 _counter가 여기 써있습니다. 앞에 $가 붙어있는 이유는 숫자를 문자로 바꿔줄 때는 $돈을 주고 바꿔야합니다. 돈을 주면 숫자가 알아서 문자로 바뀌게끔 일하죠. 그 외에 style은 문자 스타일을 건물 테마에서 정해뒀던 헤드라인4 스타일로 바꾸라는 의미입니다. 사진을 다시 보면 $_counter는 숫자가 변하고, 글자 크기도 더 큰게 보이죠? 두번째 위젯은 숫자가 변하기 때문에 const를 사용할 수 없던 겁니다.
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
마지막으로 초인종을 살펴보죠. 초인종은 오른쪽 아래에 파란색 동그라미입니다. FloatingActionButton이라는 위젯으로 만들죠. 이 위젯도 3가지 필요로 하는게 있네요.
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
onPressed는 초인종을 누르면 뭘 할 건지 정해달라는 겁니다. _incrementCounter는 아까 이 아이가 숫자를 하나씩 더하려고 한다고 했었죠? 이 초인종을 누르면 아이는 숫자를 하나씩 더할겁니다. 실제로 사진을 보면 버튼을 누를때마다 화면 가운데에 있는 숫자가 1씩 늘어나죠.
tooltip은 이 초인종이 뭔지, 무슨 버튼인지 알려주는 레이블이라고 보면 됩니다. 버튼에 +라고만 쓰여 있다보니 모를 수도 있거든요.
child는 아시다시피 자식 위젯입니다. const가 쓰여 있는걸 보니 절대 변하지 않는 조각인가 보군요. Icon은 아이콘을 보여주는 위젯입니다. Icons는 아이콘들을 모아둔 바구니죠. 이 바구니 안에서 add라는 더하기 모양의 아이콘을 골라서 보여주기로 되어있네요.
여러분이 앞으로 앱을 만드는 건 이 정도만 해석할 줄 알면 대부분 만들 수 있습니다. 이걸 오늘 다 외울 필요는 없어요. 시간이 날 때 천천히 다시 훑어보는 정도면 됩니다. 이번 강의 포스팅은 앱 코딩은 이 정도면 된다라는 걸 보여드리려고 했던 거였죠. 다음 강의부터는 실제로 코딩을 실습해보겠습니다. 아래 링크를 눌러 여러분만의 앱을 만들어보죠.
'비전공자를 위한 Flutter > 앱 개발 강의보기' 카테고리의 다른 글
Flutter 앱 만들기 2단계 : 앱 퀄리티 높아보이는 디자인 준비하기 (0) | 2022.05.07 |
---|---|
Flutter 앱 만들기 1단계 : 기획하기 (0) | 2022.05.03 |
Flutter 첫 프로젝트 - my_app 코드 간단 설명 (1/2) (0) | 2022.04.28 |
Xcode 시뮬레이터 실행하는 법 (0) | 2022.04.25 |
Flutter 첫 프로젝트 가상 휴대폰으로 실행시키기 (0) | 2022.04.24 |
댓글