이번 강좌에서는 플러터의 기본 코드에 대해 더 깊이 있는 이해를 목표로 하여, 간단한 예제를 통해 실습을 진행하고, 그 과정에서 중요한 개념들을 설명하겠습니다. 지난 강좌에서 다룬 내용과 연계하여, 플러터와 다트 언어의 기본 문법 및 구조를 점검하면서 추가적인 기능들을 어떻게 사용할 수 있는지 알아보겠습니다.
1. 플러터 기본 코드 구조
플러터는 앱 개발을 위해 다양한 위젯을 조합할 수 있는 프레임워크입니다. 플러터 애플리케이션의 가장 기본적인 구성 요소는 ‘위젯’입니다. 모든 것이 위젯으로 작성되며, 위젯은 화면의 요소들을 구성하는 역할을 합니다. 아래는 간단한 간단한 플러터 애플리케이션의 구조입니다.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('플러터 기본 코드 이해하기 2'),
),
body: Center(
child: Text('안녕하세요, 플러터!'),
),
),
);
}
}
위의 코드에서 ‘main’ 함수는 플러터 애플리케이션의 시작점입니다. ‘runApp()’ 함수를 호출하여 MyApp 클래스를 사용해 애플리케이션을 시작합니다.
2. StatelessWidget과 StatefulWidget
플러터에서 위젯은 크게 StatelessWidget과 StatefulWidget으로 나눌 수 있습니다.
2.1 StatelessWidget
StatelessWidget은 상태를 가지지 않는 위젯입니다. 즉, 이 위젯은 생성 이후에 상태가 변경되지 않습니다. 예를 들어, 아래의 코드는 간단한 StatelessWidget을 설명합니다.
class Greeting extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text('안녕하세요, 사용자님!');
}
}
위의 위젯은 인스턴스를 생성할 때마다 항상 동일한 텍스트를 표시합니다.
2.2 StatefulWidget
StatefulWidget은 상태를 가질 수 있는 위젯입니다. 상태가 변경되면 위젯의 내용도 같이 업데이트됩니다. 다음은 간단한 StatefulWidget의 예제입니다.
class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();
}
class _CounterState extends State {
int _count = 0;
void _incrementCounter() {
setState(() {
_count++;
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('버튼을 $count 번 눌렀습니다.'),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('버튼 클릭!'),
),
],
);
}
}
위의 예제는 버튼을 누를 때마다 카운트를 증가시키고, 화면에 현재 카운트를 보여줍니다. 여기서 중요한 점은 setState() 메서드입니다. 이 메서드를 호출하면 플러터는 위젯의 상태가 변경되었음을 인식하고 UI를 업데이트합니다.
3. 플러터 레이아웃 시스템
플러터에서는 다양한 레이아웃 위젯을 제공하여 복잡한 UI를 쉽게 구성할 수 있도록 합니다. 기본적인 레이아웃 위젯에는 Column, Row, Stack, Container 등이 있습니다.
3.1 Column과 Row
Column 위젯은 자식 위젯들을 수직으로 배치하고, Row 위젯은 자식 위젯들을 수평으로 배치합니다. 아래는 Column과 Row를 사용한 코드 예시입니다.
class LayoutExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
Row(
children: [
Icon(Icons.star),
Text('스타 아이콘'),
],
),
Row(
children: [
Icon(Icons.favorite),
Text('하트 아이콘'),
],
),
],
);
}
}
3.2 Container와 Padding
Container 위젯은 여러 속성을 설정할 수 있는 매우 유연한 위젯입니다. Padding 위젯을 사용하면 자식 위젯 주변에 여백을 추가할 수 있습니다.
class PaddedContainer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
color: Colors.blue,
height: 100,
width: 100,
child: Center(
child: Text(
'컨테이너',
style: TextStyle(color: Colors.white),
),
),
),
);
}
}
4. 상호작용 및 이벤트 처리
플러터에서는 다양한 방식으로 사용자와의 상호작용을 처리할 수 있습니다. 버튼 클릭, 스와이프 등 다양한 제스처를 인식할 수 있습니다. 아래 예제에서는 GestureDetector를 사용해 터치 이벤트를 처리하는 방법을 설명합니다.
class GestureExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print('Tapped!');
},
child: Container(
color: Colors.green,
height: 100,
width: 100,
child: Center(
child: Text('탭해 보세요!'),
),
),
);
}
}
GestureDetector는 다양한 이벤트(탭, 더블탭 등)를 처리할 수 있는데, 위의 예제에서는 탭 이벤트만 처리하고 있습니다. 이벤트가 발생하면 지정된 메서드가 호출됩니다.
5. 플러터 커스터마이징
플러터는 위젯을 간단하게 커스터마이징할 수 있는 방법을 제공합니다. ThemeData를 통해 앱 전반에 걸쳐 동일한 스타일을 적용할 수 있습니다.
class ThemedApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
textTheme: TextTheme(
bodyText2: TextStyle(color: Colors.white, fontSize: 18),
),
),
home: Scaffold(
appBar: AppBar(
title: Text('테마 예제'),
),
body: Center(
child: Text('테마가 적용된 텍스트입니다.'),
),
),
);
}
}
위의 코드는 MaterialApp 내부에서 테마를 지정하여 앱 전반에 걸쳐 텍스트의 색상 및 크기를 설정합니다. 이렇게 하면 코드 중복을 줄이고, 애플리케이션의 일관된 스타일을 유지할 수 있습니다.
6. 실습 프로젝트: 간단한 투두리스트 앱 만들기
이번 섹션에서는 지금까지 배운 내용을 바탕으로 간단한 투두리스트 앱을 만들어 볼 것입니다. 이를 통해 플러터의 기본적인 동작 방식을 체험해 보실 수 있습니다.
6.1 프로젝트 세팅
우선, 새로운 플러터 프로젝트를 생성합니다. 다음 명령어를 입력하여 플러터 프로젝트를 생성합니다.
flutter create todo_list
프로젝트 디렉토리로 이동한 후, lib/main.dart
파일을 열어 기본 템플릿을 삭제하고 아래의 코드를 추가합니다.
import 'package:flutter/material.dart';
void main() {
runApp(TodoListApp());
}
class TodoListApp extends StatefulWidget {
@override
_TodoListAppState createState() => _TodoListAppState();
}
class _TodoListAppState extends State {
List _todos = [];
final TextEditingController _controller = TextEditingController();
void _addTodo() {
setState(() {
_todos.add(_controller.text);
_controller.clear();
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('투두리스트'),
),
body: Column(
children: [
TextField(
controller: _controller,
decoration: InputDecoration(labelText: '할 일 입력'),
),
ElevatedButton(
onPressed: _addTodo,
child: Text('추가'),
),
Expanded(
child: ListView.builder(
itemCount: _todos.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_todos[index]),
);
},
),
),
],
),
),
);
}
}
위의 코드는 투두리스트 앱의 기본적인 부분을 구성합니다. 텍스트 필드와 버튼, 리스트뷰를 사용하여 할 일을 추가하고, 리스트로 보여주는 기능을 구현하였습니다.
6.2 기능 추가 및 테스트
코드를 작성한 후 애플리케이션을 실행해보시면 투두 아이템을 추가할 수 있습니다. 이 과정을 통해 플러터가 빠르고 효율적인 UI를 만드는 데 얼마만큼 효과적인지를 경험할 수 있습니다.
7. 결론 및 다음 강좌 예고
이번 강좌에서는 플러터의 기본 코드를 이해하고, 위젯, 레이아웃, 이벤트 처리 등을 실습하였습니다. 플러터는 매우 유연하고 강력한 프레임워크로, 다양한 앱을 손쉽게 만들 수 있습니다. 다음 강좌에서는 상태 관리 패턴 및 플러터에서의 비동기 프로그래밍을 다루어 보겠습니다.
감사합니다.