5일차 과정에서는 머티리얼 디자인에 대한 내용들을 다뤘고, 이와 관련된 위젯들을 학습했다.
학습한 내용
- Material 디자인
- MaterialApp 위젯과 Scaffold 위젯
- AppBar 위젯
- BottomNavigationBar 위젯
- FloatingActionButton 위젯
머티리얼 디자인이란 플랫 디자인의 장점을 살리면서도 빛에 따른 종이의 그림자 효과를 이용하여 입체감을 살리는 디자인 방식을 의미한다.
2014년 구글이 안드로이드 스마트폰에 적용하면서 사용되기 시작했다.
플랫 디자인과 마찬가지로 최소한의 요소만을 사용하여 대상의 본질을 표현하는 디자인 기법인 미니멀리즘을 추구한다.
머티리얼 디자인의 아이콘들을 아래 링크를 통해 확인할 수 있다.
Material Icons
구글이 만들고 지향하는 디자인인 Material Design을 사용할 수 있게 만들어주는 클래스이다.
IOS 스타일로 만들 수 있는 CupertinoApp
과 함께 주로 안드로이드 스타일에서 대표적으로 쓰이고 있다.
많은 속성들 중에 home
은 필수적이다. home
은 앱을 실행할 때 가장 먼저 나오는 페이지이다.
Scaffold
는 MaterialApp
안에서 뼈대의 역할을 수행하는데 많은 기본 기능들을 제공한다.
서랍, 스낵바, 하단 시트, 플로팅 버튼 등을 보여주는 역할을 한다.
주로 사용하는 속성은 아래와 같다.
- AppBar : 앱바
- Body : 가운데 영역(본문 내용)
- BottomNavigationBar : 하단 네비게이션 바
- FloatingActionButton : 항상 떠있는 버튼
- FloatingActionButtonLocation : FloatingActionButton의 위치를 설정
- MariaDB, MySQL, MongoDB
- Material Design 구현 연습
- BottonNavigationBar UI 구현
- FloatingActionButton UI 구현
- 주어진 페이지 UI 구현
데이터베이스는 직역하면 데이터(자료)의 기반이 되는 것으로 컴퓨터 시스템에서 전자적으로 저장되고 엑세스 되는 체계적인 데이터 모음이다.
데이터 베이스는 체계적으로 구성된 데이터 모음이므로 쉽게 엑세스 하고, 관리할 수 있다.
RDBMS는 Relational Data Base MAnagement System의 약자로 관계형 데이터베이스를 관리하는 시스템이라는 의미로 해석된다. 따라서 RDBMS란 관계형 데이터베이스를 위해 설계된 DBMS이다.
DBMS란 데이터베이스 내의 데이터에 접근하여 데이터를 사용할 수 있도록 도와주는 시스템이다.
즉, RDBMS는 관계형 데이터베이스 내에 접근하여 데이터를 생성하고 관리할 수 있도록 도와주는 시스템이다.
관계형 데이터베이스는 키(Key)와 값(value)들의 간단한 관계를 테이블화 시킨 간단한 원칙의 전산정보 데이터베이스이다.
- 장점
- RDBMS는 정해진 스키마에 따라 데이터를 저장하여야 하므로 명확한 데이터 구조를 보장한다.
- 관계는 각 데이터를 중복없이 한 번만 저장할 수 있습니다.
- 단점
- 테이블끼리 관계를 맺고 있어 시스템이 커질 경우 JOIN문이 많은 복잡한 쿼리가 만들어질 수 있다.
- 성능 향상을 위해서는 서버의 성능을 향상 시켜야하는 Scale-up만을 지원한다. 이로 인해 비용이 기하급수적으로 늘어날 수 있다.
- 스키마로 인해 데이터가 유연하지 않다. 스키마가 변경 될 경우 번거롭고 어렵다.
NoSQL 이란 Not Only SQL의 약자로 RDBMS형태의 관계형 데이터베이스가 아닌 다른 형태의 데이터 저장 기술을 의미한다.
또한 NoSQL에서는 RDBMS와 달리 테이블 간 관계를 정의하지 않는다. 그렇기 때문에 일반적으로 테이블 간 join도 불가능하다.
NoSQL에는 여러 종류가 존재하는데 아래와 같다.
- Key-Value Database
데이터가 Key와 Value의 쌍으로 저장- Document Database
데이터가 Key와 Documnet의 형태로 저장, 값이 계층적인 Document 형태로 저장된다는 점에서 Key-Value Database와 다름- Wide Column Database
Column-family Model 기반의 데이터베이스, 이 모델은 키(Key)에서 필드를 결정함, 키는 Row(키 값)와 Column-family, Column-name을 가짐, 연관된 데이터들은 같은 Column-family에 속해있고 각자의 Column-name을 가짐- Graph Database
데이터를 Node, Edge, Property와 함께 그래프 구조를 사용하여 저장하고 표현, 개체와 관계를 그래프 형태로 표현한 것으로 관계형 모델이라고 할 수 있음
- 장점
- NoSQL에서는 스키마가 없기 때문에 유연하며 자유로운 데이터 구조를 가질 수 있고, 언제든 저장된 데이터를 조정하고 새로운 필드를 추가할 수 있다.
- 데이터 분산이 용이하며 성능 향상을 위한 Saclue-up 뿐만이 아닌 Scale-out 또한 가능하다.
- 단점
- 데이터 중복이 발생할 수 있으며 중복된 데이터가 변경 될 경우 수정을 모든 컬렉션에서 수행을 해야 한다.
- 스키마가 존재하지 않기에 명확한 데이터 구조를 보장하지 않으며 데이터 구조 결정이 어려울 수 있다.
MySQL은 가장 널리 사용되고 있는 RDBMS이다. 1995년 5월에 MySQL AB사에 의해 첫 번째 버전이 발표되었고 1998년 윈도우 버전이 발표되었다.
MySQL은 오픈소스이며, 다중 사용자와 다중 스레드를 지원한다. 또한, C언어, C++, JAVA 등 여러 프로그래밍 언어를 위한 다양한 API를 제공한다.
MySQL은 유닉스, 리눅스, 윈도우 등 다양한 운영체제에서 사용할 수 있다.
- 오픈 소스 라이센스를 따르기 때문에 무료로 사용할 수 있다.
- 다양한 운영체제에서 사용할 수 있으며, 여러 가지의 프로그래밍 언어를 지원한다.
- 크기가 큰 데이터 집합도 아주 빠르고 효과적으로 처리할 수 있다.
- 널리 알려진 표준 SQL 형식을 사용한다.
- MySQL 응용 프로그램을 사용자의 용도에 맞게 수정할 수 있다.
MariaDB는 MariaDB사가 제작한 오픈소스 RDBMS 소프트웨어이다.
MariaDB는 MySQL과 관계가 있는데 MySQL의 창업자 중 한명과 일부 개발자들이 나와 MariaDB사를 설립하여 MariaDB를 개발했다. 또한 MariaDB는 MySQL의 소스코드를 그대로 가져와 개발했기 때문에 거의 모든 기능이 동일하고, 서로간의 호환성이 보장된다.
MariaDB와 MySQL은 거의 100% 호환성을 가지고 있다. 즉, 핵심 바이너리 구조와 사용하는 프로토콜이 같은 구조를 지닌다. 다만 MySQL에서 몇가지 문제점을 보완하기 위해 MariaDB에서는 일부 기능이나 구조가 다르게 설계된 부분이 있다.
MySQL은 상업용으로 사용하기 위해서는 돈을 지불해야 하지만 MariaDB는 무료로 모든 기능을 사용할 수 있다.
MariaDB는 MySQL의 코드 베이스이지만 독립적인 RDBMS이기 때문에 MySQL에서 제공하지 않는 독자적인 기능 및 구문도 지원한다.
MongoDB는 NoSQL 데이터베이스이고, 그 중 대표적인 Document Database이다.
데이터는 Document 기반으로 구성되어있고, 오픈소스이기 때문에 무료로 사용이 가능하다.
MongoDB는 Database > Collection > Document > Field 계층으로 이루어져있는데 Documnet가 RDBMS의 Row에 해당한다. 아래 그림을 보면 계층이 RDBMS와 유사한 것을 알 수 있다.
하지만 Documnet 기반 데이터베이스는 RDBMS와 다르게 데이터 구조를 자유롭게 잡을 수 있다.
MongoDB는 또한 RDBMS와 다르게 ACID 대신 BASE를 택해 선능과 가용성을 우선시하는데 아래는 BASE에 대한 설명이다.
- Basically Avaliable
기본적으로 언제든지 사용할 수 있다는 의미를 가지고 있다.
즉, 가용성이 필요하다는 뜻을 가진다.- Soft state
외부의 개입이 없어도 정보가 변경될 수 있다는 의미를 가지고 있다.
네트워크 파티션 등 문제가 발생되어 일관성(Consistency)이 유지되지 않는 경우 일관성을 위해 데이터를 자동으로 수정한다.- Eventually consistent
일시적으로 일관적이지 않은 상태가 되어도 일정 시간 후 일관적인 상태가 되어야한다는 의미를 가지고 있다.
장애 발생시 일관성을 유지하기 위한 이벤트를 발생시킨다.
이번 포스팅에서는 기본적으로 RDBMS와 NoSQL의 대표적인 소프트웨어들의 특징과 차이점만을 정리했다.
아래 링크는 MongoDB의 데이터 형태, 패턴 등의 자세한 내용이 담겨있다.
MongoDB 이해하기
여러 Material 디자인들의 컴포넌트를 아래 링크를 통해 확인할 수 있다.
Material Design M2 Component
왼쪽 사이드에 드로어가 있는 UI를 구성하고자 한다. Material Design M2를 확인했더니 Navigation drawer
컴포넌트를 사용하는 것이 적합해 보인다.
Scaffold
위젯에서 drawer
속성을 사용하면Navigation drawer
를 구현할 수 있다. 이를 사용해 간단한 UI를 구현해 보았다.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
//Navigation drawer
drawer: Drawer(
child: Column(
children: [
SizedBox(
height: 120,
//드로어 헤더
child: DrawerHeader(
padding: EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
child: ListTile(
title: Text('스나이퍼팩토리'),
subtitle: Text('안녕하세요, 스팩입니다.'),
leading: Image.network(
'https://sniperfactory.com/img/flutter/memoji1.png',
),
),
),
),
//드로어 요소
Expanded(
child: ListView(
children: [
ListTile(
title: Text('홈'),
subtitle: Text('홈으로 이동하기'),
onTap: () {}, //이동 기능 구현
),
ListTile(
title: Text('커뮤니티'),
subtitle: Text('커뮤니티로 이동하기'),
onTap: () {},
),
],
),
),
//로그아웃
ListTile(
title: Text('로그아웃'),
subtitle: Text('로그아웃합니다.'),
trailing: Icon(Icons.logout),
onTap: () {},
),
],
),
),
),
);
}
}
Scaffold
위젯의 drawer
속성에서 Drawer()
를 사용해 Navigation drawer
를 구현했다.
드로어의 전체 요소는 Column
으로 묶어주었다.
DrawerHeader()
를 사용해 헤더를 만들었다.헤더의 크기를 줄이기 위해 SizedBox
로 감싸height
를 설정했다. 내부 요소는 ListTile
로 생성했다.
아래 이동할 수 있는 요소들은 ListView
안에 ListTile
로 생성해 주었는데 크기를 끝까지 확장시기키 위해 Expanded
위젯으로 감싸주었다.
마지막 로그아웃 요소 역시 ListTile
을 사용했다.
각 ListTile
에서 onTap
속성을 작성하면 이동 기능을 적용할 수 있다. 현재는 UI만 구성하기 위해 따로 기능을 추가하지는 않았다.
자세한 Flutter의 Drawer사용법은 아래 링크를 통해 확인할 수 있다.
Add a Drawer to a screen
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
// 바텀 네비게이션 바
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed, //네비게이션 타입
selectedItemColor: Colors.pink,
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: '홈'),
BottomNavigationBarItem(icon: Icon(Icons.people), label: '친구'),
BottomNavigationBarItem(
icon: Icon(Icons.video_call), label: 'Watch'),
BottomNavigationBarItem(
icon: Icon(Icons.verified_user), label: '프로필'),
BottomNavigationBarItem(
icon: Icon(Icons.notifications), label: ' 알림'),
BottomNavigationBarItem(
icon: CircleAvatar(
radius: 14,
backgroundImage: NetworkImage('https://picsum.photos/50/50'),
),
label: '메뉴',
),
],
),
),
);
}
}
Scaffold
위젯에서 bottomNavigationBar
속성을 사용해 바텀 네비게이션을 생성했다.
BottomNavigation
위젯을 사용하는데 items
속성으로 3개까지는 정상적으로 출력되지만 4개 이상부터는 각 요소가 흰색으로 설정되며 잘 보이지 않는다. 그 이유는 아이템이 3개 까지는 type
속성이 BottomNavigationBarType.fixed
로 설정되지만 4개 이상부터는 BottomNavigationBarType.shifting
으로 설정되기 때문이다. shifting
이 적용되면 선택된 항목이 크기가 커지며 레이블이 보이게 된다. 또한 기본이 흰색으로 설정되어 색상을 바꿔줘야 한다. 구현하고자 하는 UI는 fixed
의 형태이므로 type: BottomNavigationBarType.fixed
를 작성해 주었다.
선택된 아이템의 색상을 핑크색으로 설정하기 위해 selectedItemColor
의 색을 Colors.pink
로 설정했다.
items
속성에는 총 6개의 BottomNavigationBarItem
위젯을 생성했으며 마지막 아이템의 아이콘에는 원형 이미지를 삽입해 주었다.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
// 바텀 네비게이션 바
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: '홈'),
BottomNavigationBarItem(icon: Icon(Icons.block), label: '차단'),
BottomNavigationBarItem(icon: Icon(Icons.settings), label: '설정'),
],
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {}, // 기능
backgroundColor: Colors.pink,
label: Text('지금 예약하기'),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
),
);
}
}
Scaffold
에 bottomNavigationBar
속성으로 바텀 네비게이션을 생성하고 3개의 아이템을 생성해 주었다.
floatingActionButton
속성을 사용해 항상 떠있는 버튼을 생성했는데 크기가 확장된 버튼을 사용해기 위해 FloatingActionButton.extended
를 사용했다. FloatingActionButton
의 크기와 관련되서 4개의 위젯이 존재하는데 아래와 같다.
- Small (40*40) :
FloatingActionButton.small()
- Regular (56*56) :
FloatingActionButton()
- Large (96*96) :
FloatingActionButton.large()
- Extended :
FloatingActionButton.extended()
[Flutter] floatingActionButton 플로팅 버튼 크기 설정
위의 방식 이외에 SizedBox
위젯을 사용하여 버튼의 크기를 직접 조정할 수도 있다.
버튼의 배경 색상은 Colors.pink
로 설정하고 label
속성을 사용해 내부의 텍스트를 작성해 주었다.
생성한 FloatingActionButton
이 가운데 아래에 위치하도록 하기 위해 floatingActionButtonLocation
의 속성을 FloatingActionButtonLocation.centerFloat
로 설정했다.
아래와 같은 UI를 구현하고자 한다.
결과 예시
코드
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
extendBodyBehindAppBar: true, //body요소를 앱바 뒤까지 확장
appBar: AppBar(
title: Text('CGB (영화 예매)'),
backgroundColor: Colors.transparent, //앱바 투명
elevation: 0, // 그림자 제거
),
body: Column(
children: [
// 앱바 배경 이미지
Container(
height: 230,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage('https://picsum.photos/400/500'),
),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22,
),
'속초 여행을 떠나면서',
),
),
Icon(Icons.remove_red_eye),
SizedBox(width: 8),
Text('232회')
],
),
),
// 사용자 정보 리스트타일
ListTile(
title: Text('오류동 멋쟁이'),
subtitle: Text('스나이퍼팩토리 누군가'),
leading: ClipOval(
child: Image.network('https://picsum.photos/50/50'),
),
trailing: Text('3시간전'),
),
Divider(), // 구분선
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'노래하며 더운지라 싹이 대고, 뿐이다. 행복스럽고 생생하며, 불어 사막이다. 전인 귀는 가치를 어디 못할 청춘을 사막이다. 소리다.이것은 유소년에게서 대중을 날카로우나 크고 우리 그리하였는가? 이 미인을 찬미를 이것이야말로 타오르고 우리 커다란 있다. 때까지 얼음이 그들을 때문이다. 힘차게 가지에 거선의 우리의 바로 운다. 끝에 따뜻한 별과 이것이다. 동력은 옷을 두기 끝에 굳세게 사막이다. 무엇을 끝까지 피가 그들은 풀밭에 이것이다. 이것은 위하여 대한 뛰노는 석가는 만물은 실현에 우리 것이다.',
),
)
],
),
),
);
}
}
Scaffold
에서 extendBehindAppBar
속성을 true
로 설정하여 앱바 뒤로 본문 내용이 확장되도록 설정했다.
앱바는 배경색을 투명하게 하고 그림자를 제거했다.
본문의 내용이 들어갈 Column
을 생성하고 배경 이미지를 Container
를 사용해 삽입해 주었다.
아래의 '속초 여행을 떠나면서'의 텍스트와 아이콘은 Row
를 사용했고 양쪽 끝으로 정렬되도록 mainAxisAlignment
를 spaceBetween
으로 설정한 뒤 가장 앞쪽 텍스트는 크기가 확장되도록 Expaned
위젯을 사용해 묶어 주었다.
사용자 정보는 ListTile
위젯을 사용해 생성해 주었고, 아래에 Divider
위젯을 넣어 구분선을 추가했다.
마지막으로 로렘입숨으로 생성한 텍스트를 Padding
위젯으로 감싸 Text
위젯으로 추가했다.
앱바의 배경을 이미지로 넣는 방법은 이번에 사용한 앱바를 투명하게 하고 본문에 이미지를 확장하는 방법 말고도 다른 방법이 있는데 AppBar
위젯의 flexibleSpace
속성을 사용하는 것이다. 예를 들면 아래의 코드처럼 사용할 수 있다.
appBar: AppBar(
title: const Text(
"Home Page",
style: TextStyle(color: Colors.white),
),
flexibleSpace: const Image(
image: NetworkImage('https://picsum.photos/400/500),
fit: BoxFit.fill,
),
),
위의 방식으로 배경을 설정하고 앱바의 높이를 키우면 주어진 UI와 같게 만들 수 있지만 title
의 내용이 세로 축의 가운데에 위치하게 되어 첫 번째 방식을 사용해 배경 이미지를 넣어 보았다.
5일차 과제를 끝냈다.ㅎㅎ 지금까지 했던 것 중에서 그래도 가장 오래 걸렸다 ㅠㅠ 코딩할 내용이 많아져서 그런가... 근데 생각보다 데이터베이스 자료조사가 오래 걸렸다. 차이점 조사하기전에 RDBMS랑 NoSQL 먼저 조사해보고, 그 다음에 각각 어떤 데이터베이스인지 조사해보고 차이점 조사해보고 하다 보니까 각 DBMS 별로 특징도 많고, 사용법도 나오고... 어디까지 정리를 해야 될지 고민을 좀 했다 ㅋㅋㅋㅋ 결국에 기본적인 내용과 장점, 단점, 차이 정도만 정리했는데 다음에 각 시스템별로 더 자세하게 패턴이나 사용법, 원리 등도 알아봐야 겠다 ㅠㅠㅠㅠ