Flutter | 간단 메모 앱 만들어보고 광고까지 달아서 배포하기 - 1. 기본 설치 및 간단한 위젯
이 내용은 CLASS 101+ 의 커니님이 강의하시는 용돈 벌어주는 나만의 앱 만들기 클래스를 보고 따라한 것입니다. 직접 강의를 보시고 하시면 더 쉽게 하실 수 있습니다.
우선 기본적인 메모앱을 만들어보기 위해서 세팅을 해봅시다.
안드로이드 스튜디오를 설치해 줍니다.
그 후 에뮬레이터를 Play Store 가 가능한 디바이스로 선택해서 설치를 해줍니다. 저는 pixel4를 선택했습니다.
그 후 자신이 원하는 안드로이드 버전을 선택해 줍니다. 저는 현재 최신 버전인 안드로이드 13을 선택했습니다.
설치가 끝난 후, 에뮬레이터를 실행한 뒤, 그대로 사용하셔도 좋지만 언어를 한글로 바꾸셔도 좋습니다. 저는 한글로 설정후 1순위로 바꿨습니다.
자 이제 기본 설정과 설치가 끝났으므로 새 프로젝트를 만들어 주겠습니다. File - New - New Flutter Project를 선택해 줍니다.
그 후 새창이 뜨는데 New Project나 Empty Project가 아닌 Generators에 Flutter를 선택해 준 뒤, Next 버튼을 눌러 줍니다.
우선 바로 앱을 만들기보다 오랜만에 플러터를 다시 만지므로 기본적인 것들을 다뤄보려 합니다.
프로젝트 이름을 자유롭게 설정해주신후 원하는 위치를 선택해서 만들어 주시면 됩니다.
프로젝트가 생성이 된 모습니다. 좌측 상단에 노란부분이 android로 되어있을때도 있는데 Project로 변경해주시면 됩니다.
우선 에뮬레이터를 실행한 후, 상단의 우측화살표를 눌러서 실행을 해봅니다.
해당 코드들의 구조적인 설명은 넘기고 바로 코드 실행으로 넘어가 보겠습니다. 기본적으로 코드의 동작은 아래 버튼을 누르면 1씩 올라가는 것을 확인 할 수 있습니다. 여기서 Scaffold 안에 FloatingActionButton이 있는데 이 안에 onPressed가 버튼이 눌렸을때의 동작을 확인 할 수 있는 부분입니다. 안드로이드 스튜디오에서는 컨트롤 키를 누르고 _incrementCounter을 눌러주면 해당 함수로 갈 수 있습니다. 이동해 보면 함수 안에 setState가 있습니다. setState는 화면의 상태를 변경해주는 부분입니다. 여기서 _counter이 초기에 0인데 _counter를 ++ 해주고 있습니다. _counter++; _conuter = _counter + 1;과 같고 해당 변수가 실행될 때마다 1씩 증가한다는 내용입니다. 이 부분을 한번 변경해 보겠습니다. _counter = _counter + 5;로 변경해주면 됩니다. 여기서 flutter는 상단의 우측화살표 모양을 누를 필요 없이 번개모양을 눌러주면 hot reload라고 해서 바로 에뮬레이터에서 변경된것을 확인 할 수 있습니다. 또는 저장만 해줘도 변경 값들이 적용 되는것을 확인 할 수 있습니다. 물론 모든 상황에서 작동이 되는 것은 아니지만 간단한 변경을 확인할때 빠르게 재실행없이 확인 할 수 있습니다. 실행해보면 5씩 증가하는것을 확인할 수 있습니다.
이제 위젯들을 변경해 보겠습니다. 우선 Text 위젯을 먼저 해보겠습니다.
Scaffold안의 body에 Center안의 Column을 삭제해 주겠습니다. 그 다음 child에 Text('Hello')를 넣어 주겠습니다.
화면의 중간에 Hello가 출력되는것을 확인 할 수 있습니다. 만약 Center가 없었다면 화면 중앙이 아닌 상단 좌측에 붙어서 나왔을 것입니다. 이를 확인하기 위해 Center을 지우고 다시 Text를 넣을 수 있겠지만 여기서 조그마한 팁이 있다면 Center로 가서 Alt + Enter을 해주면 창이 하나 뜨고 하단에 Remove this Widget를 해주시면 Center만 사라지고 Text위젯부분은 body에 남아 있는것을 확인 할 수 있습니다.
이처럼 해당 위젯을 다른 위젯으로 감쌀수도 있습니다. 그래서 긴 코드를 복붙하고 삭제하고 하지 않아도 쉽게 감싸거나 삭제, 교체가 가능합니다. Center를 지워보면 상단 좌측에 있는것을 확인 할 수 있습니다.
이번에는 문장을 길게 해서 화면에 띄워보겠습니다.
자동 줄바꿈이 되면서 여러줄이 작성된것을 볼 수 있습니다. 여기서 문장을 랜덤으로 생성하고 싶을때는 로렘입숨, 한글로렘입숨을 검색하시면 됩니다. 디자인적으로 프론트엔드를 만드실때 여러 상황을 고려해서 문장을 하는것보다 보기 좋아보이는것 같아서 자주 사용합니다. 이때 Text에서 너무 내용이 길어지면 다른 위젯에 영향을 주기 때문에 줄 제한을 할 수 있는 속성이 있는데 maxLines라는 속성입니다. 해당 속성을 3으로 해서 3줄만 만들어 보겠습니다.
여기서 문장이 잘려보이는데, 주로 웹사이트나 문자등에서 해당 문장이 길면 뒤에 ...과 같이 표시해줄때 쓸수있는 속성이 있습니다. overflow 속성에 값을 TextOverflow.ellipsis 줘보겠습니다.
문장 뒤에 가운데 ...을 확인하실 수 있습니다. 또다른 꿀팁을 드리자면 속성을 줄때 ,뒤에 속성을 주고 줄이 옆으로 길어져서 확인이 어려울때는 안드로이드 스튜디오에서는 Ctrl + Alt + L 을 눌러주시면 자동정렬이 됩니다. 또한 속성을 이것저것 넣어보고 싶은데 어떤값이 들어 가는지 모를땐 속성에서 Ctrl + 스페이스를 해주시면 쉽게 볼 수 있고 때론 정확한 값이 나오지 않을때는 Text와 같이 위젯을 Ctrl + 클릭으로 눌러서 들어가신 후 속성값을 다시한번 Ctrl + 클릭으로 가시면 어떤값을 넣어야 하는지 보실 수 있습니다.(대부분 이렇게 확인 할 수 있지만 때론 정 모르겠으면 구글링이 최고입니다.)
body: const Text(
'모든 국민은 법률이 정하는 바에 의하여 국방의 의무를 진다. 법관은 헌법과 법률에 의하여 그 양심에 따라 독립하여 심판한다. 국회의원은 국회에서 직무상 행한 발언과 표결에 관하여 국회외에서 책임을 지지 아니한다. 공개하지 아니한 회의내용의 공표에 관하여는 법률이 정하는 바에 의한다. 대통령은 전시·사변 또는 이에 준하는 국가비상사태에 있어서 병력으로써 군사상의 필요에 응하거나 공공의 안녕질서를 유지할 필요가 있을 때에는 법률이 정하는 바에 의하여 계엄을 선포할 수 있다.',
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
다른 overflow는 여러가지 옵션을 넣어보신 후 직접 확인해 보시면 될 것 같습니다.
다음은 Text에서 정렬 방법의 속성인 textAlign속성을 확인해 보겠습니다. 이를 위해서 짧은 문장으로 확인해 보겠습니다. textAlign의 값을 TextAlign.start로 왼쪽정렬로 해보겠습니다. 처음과 같아서 변하는게 없기 때문에 end로 변경했는데.... 변하지 않는것을 확인할 수 있는데요... 그 이유는, Text 위젯의 글자의 크기만큼 범위를 차지해서 입니다. 이를 확인하기 위해서 안드로이드 스튜디오 우측에 Flutter Inspector을 클릭해줍니다.
이 창에서 상단의 노란색 원안의 버튼을 클릭 해 준뒤 에뮬레이터에서 Text위젯의 글을 쓴 부분을 클릭해줍니다. 그러면 코드상에서 해당되는 부분으로 이동하고 에뮬레이터에서 박스처리가 되는데 이 부분이 현재 Text위젯의 크기입니다.
그렇기 때문에 글자의 정렬이 되지 않았던 것입니다. 그래서 Text의 범위를 넓혀야 하는데 Text위젯에는 해당 부분이 없기때문에 Text위젯위에 다른 위젯을 감싸 주겠습니다. Container 또는 SizedBox 위젯으로 감싼 뒤 width 속성에 숫자를 입력하시면 우측정렬이 된것을 확인 하실 수 있습니다. 여기서 범위를 지정해주지 않고 화면의 전체 width를 해주는 방법이 있는데 Expanded 와 SizedBox.expand 위젯을 사용 하시면 됩니다. 하지만 Expanded는 해당 부분에서 나머지 부분 전체를 사용하는 특성때문에 여기에서는 사용할 수 없어서 SizedBox.expanded를 사용하시면 됩니다. 두가지는 상황에 맞게 사용하시면 됩니다.
다음은 글씨의 스타일을 바꿔보겠습니다. Text안에 style 속성을 바꾸시면 됩니다. Text 위젯의 style속성에서는 주로 TextStyle을 사용합니다. 해당 위젯에 속성에는 여러개의 속성이 있습니다. 간단히만 설명 드리자면 fontSize는 글씨의 크기, fontStyle는 기울기등을 나타내는 스타일, fontWeight는 굵기, fontFamily는 글씨체 입니다. 해당 속성들의 값을 직접 바꿔가시면서 확인해 보시면 더 쉽게 파악하실 수 있습니다. 여기서 fontFamily는 fonts.google.com에서 다운로드 해서 사용하실 수 있습니다. 아무 폰트나 다운로드 하신 후 프로젝트에서 프로젝트 이름에 우클릭 하신 뒤 New에서 Directory를 선택하신뒤 fonts로 생성하시고 그 안에 다운로드 받은 ttf 폰트 파일을 넣어 주시면 됩니다. 그리고 프로젝트에서 사용할 수 있도록 pubspec.yaml에 추가해 주면 되는데 flutter 의 하위에 fonts를 추가해주시면 됩니다. 그리고 fonts를 받은 페이지에서 하단으로 내려가시면 bold의 굵기를 확인 하실 수 있습니다. 이 굵기를 각 글자의 weight에 넣어 주시면 됩니다.
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
fonts:
- family: Noto SansKR
fonts:
- asset: fonts/NotoSansKr-Regular.otf
weight: 400
- asset: fonts/NotoSansKr-Bold.otf
weight: 700
- asset: fonts/NotoSansKr-Light.otf
weight: 300
- asset: fonts/NotoSansKr-Medium.otf
weight: 500
- asset: fonts/NotoSansKr-Black.otf
weight: 900
- asset: fonts/NotoSansKr-Thin.otf
weight: 100
다 넣으신 후 main.dart에 오시면 dependencis가 업데이트 되었기때문에 get 또는 upgrade를 하라고 상단에 알림이 나옵니다. Get dependencies 를 해서 변경사항을 반영해줍니다.
body: const SizedBox.expand(
child: Text(
'안녕하세요',
maxLines: 3,//보이는 줄 갯수
overflow: TextOverflow.ellipsis,//문장이 더 길때 보이는 방법
textAlign: TextAlign.end,//정렬
style: TextStyle(
fontSize: 20,//글씨 크기
fontStyle: FontStyle.italic,//스타일
fontWeight: FontWeight.bold, //굵기, w100,w200등으로 세밀하게 변경 가능
fontFamily: 'Oswald',
),
),
),
폰트가 바뀌었을때는 앱을 완전히 종료후 재실행 해줘야 반영이 되기때문에 재실행을 해줍니다.
글자체가 바뀐것을 알 수 있습니다. 여기까지 Text 위젯에 대해 알아보았고 다음은 FloatingActionButton에 대해 알아보겠습니다. 현재 Scaffold의 속성에 floatingActionButton에 있는것을 확인 할 수 있습니다. FloatingActionButton의 속성을 보면 우선 child가 있습니다. 지금은 Icon 위젯으로 있지만 Text나 다른 위젯을 넣어줄 수도 있습니다. 다음으로 tooltip 속성은 버튼을 길게 눌렀을때 버튼설명같이 보여주는 옵션입니다. onPressed는 위에서 설명한것같이 버튼이 눌렸을때 동작하는 함수를 넣어주는 부분입니다. 다음으로 mini 속성이 있는데 true와 false값을 넣을 수 있는데 true일때는 작아지는 것을 확인할 수 있습니다.
또한 아이콘과 버튼을 같이 사용할 수 있는데, child에 다른 버튼이나 Row등을 사용하면 에러가 날수 있기때문에 FloatingActionButton.extended을 사용하시면 됩니다.
floatingActionButton: FloatingActionButton.extended(
onPressed: _incrementCounter,
tooltip: '버튼이지롱',
icon: const Icon(Icons.add),
label: const Text('ADD'),
),
그런데 FloatingActionButton이 우하단에만 있는걸 옮기고 싶으신 분들도 있으실텐데 이럴땐 Scaffold에 floatingActionButtonLocation 속성을 사용하시면 됩니다. 여기서 좌우로 start, center, end로 좌, 중, 우가 되겠고 상하로는 top, float, docked가 있겠습니다. 상하는 중앙은 없고 float와 docked가 위치가 비슷한데 float는 하단에서 약간 떨어진 형태이고, docked는 하단에 달라붙은 형태가 되겠습니다. mini를 사용하신다면 앞에 mini가 붙은것을 사용하시면 됩니다. 여기서 floatingActionButtonAnimator 속성을 통해 애니메이션도 줄 수 있지만 많이 사용하지 않기에 우선 넘어가도록 하겠습니다. FloatingActionButton에 대해선 여기까지 하고 Container에 대해 배워보겠습니다.
주로 위젯위에 감싸서 사용하면서 SizedBox 도 사용하지만 두개는 사용법이 다르기때문에 익혀보고 자신에게 맞게 사용하면 될것같습니다. 이를 간단히 사용해볼텐데 body를 SizedBox.expand대신 Container을 넣어줍니다. 그리고 child에 여러 위젯을 넣어줄 수 있는데 우선 Text를 넣어주고 color 속성에는 Colors.redAccent를 넣어줍니다. 그리고 padding로 내부 여백을 설정해주는데 EdgeInsets.all(10)으로 상하좌우에 10의 크기만큼 넣어주면 됩니다.
또한 alignment를 통해 자식 속성의 정렬을 설정해줄 수 있는데 Alignment.topRight로 우상단을 설정해줄 수 있습니다.
범위를 설정해주지 않고 정렬을 하면 상위 위젯의 전체 범위를 가져갑니다. 그래서 width와 hight로 범위를 좁혀 원하는 만큼 사용할 수 있습니다.
body: Container(
padding: const EdgeInsets.all(10),
width: 100,
height: 100,
alignment: Alignment.topRight,
color: Colors.redAccent,
child: const Text('Hello'),
),
다음은 Padding 위젯을 알아보겠습니다. 자식 위젯과 padding값만 설정이 가능합니다.
body: const Padding(
padding: EdgeInsets.all(10),
child: Text('Hello'),
)
다음으로는 SizedBox 위젯입니다. SizedBox는 width 와 hight 와 자식 위젯만 지정할 수 있습니다. 다른 값을 주지 않는다면 보이기에는 좌상단에 있어서 Center없이 text 위젯만 사용했을때와 똑같습니다.
body: const SizedBox(
width: 200,
height: 200,
child: Text('Hello'),
),
다음으로는 Row와 Column에 대해서 알아보겠습니다. Row와 Column은 자식들을 수평, 수직으로 여러개 배치할 수 있습니다. 우선 Row부터 알아보겠습니다. 수평방향으로 왼쪽에서 배치합니다. children속성을 사용해서 [] List 형태로 사용합니다.
body: Row(
children: [
Text('Test',),
Text('Test',),
Text('Test',),
Text('Test',),
Text('Test',),
],
),
여기서 속성 mainAxisSize를 사용해 사용하는 공간을 정해줄 수 있습니다. MainAxisSize.max로 수평 전체 공간을 사용할 수도 있고 min을 사용해서 자식위젯의 필요 공간만 사용할 수 있습니다. 또 mainAxisAlignment를 통해서 정렬을 할 수 있습니다. 각 속성별로 같은 거리를 두는 spaceAround나 그 외에 옵션은 직접 사용해보시면 됩니다. 이 정렬도 max로 확인하셔야 합니다. min이면 최소 공간이기 때문에 정렬을 할 범위가 없기 때문입니다.
body: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Test',),
Text('Test',),
Text('Test',),
Text('Test',),
Text('Test',),
],
),
다음으로 Column위젯인데 Row를 Column으로 그대로 바꿔준것으로 수평을 수직으로 변경한것입니다. 옵션도 같지만 방향만 수직으로 바뀌었다 생각해주시면 됩니다.
body: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Test',),
Text('Test',),
Text('Test',),
Text('Test',),
Text('Test',),
],
),
오늘의 마지막으로 ListView 위젯을 알아보겠습니다. 여러개의 자식 위젯을 수직으로 보여줍니다. Column과 같을 수 있겠지만 화면이상의 크기가 되면 Scroll View를 통해 에러가 발생하지않고 사용할 수 있습니다. 물론 다른 방법을 통해 Column도 크기 이상으로 가도 스크롤뷰가 되게 해서 사용할 수 있지만 기본적으로 ListView가 스크롤뷰를 이용해서 사용한다고 생각하시면 되겠습니다. children에 Container로 색과 margin의 크기를 줘서 확인해 보겠습니다.
body: ListView(
children: [
Container(
height: 200,
width: 200,
color: Colors.redAccent,
margin: const EdgeInsets.all(5),
),
Container(
height: 200,
width: 200,
color: Colors.redAccent,
margin: const EdgeInsets.all(5),
),
Container(
height: 200,
width: 200,
color: Colors.redAccent,
margin: const EdgeInsets.all(5),
),
Container(
height: 200,
width: 200,
color: Colors.redAccent,
margin: const EdgeInsets.all(5),
),
Container(
height: 200,
width: 200,
color: Colors.redAccent,
margin: const EdgeInsets.all(5),
),
Container(
height: 200,
width: 200,
color: Colors.redAccent,
margin: const EdgeInsets.all(5),
),
Container(
height: 200,
width: 200,
color: Colors.redAccent,
margin: const EdgeInsets.all(5),
),
],
),
드래그를 해보시면 스크롤이 되는것을 확인 하실 수 있습니다.
위의 위젯을과 속성값들을 확인하고 사용해 보셔서 필요한 상황에 원하는 위젯을 넣으셔서 활용하시면 되겠습니다. 다음에 이제 앱을 만들어 보도록 하겠습니다.