목표
Flutter에서 TextField와 Form을 사용하여 사용자 입력을 처리하고, 유효성 검사를 구현합니다.
1. 소개
사용자로부터 데이터를 입력받는 것은 대부분의 앱에서 중요한 기능입니다. Flutter는 TextField와 Form 위젯을 사용하여 이러한 기능을 제공합니다. 이번에는 입력을 받아서 처리하고, 유효성 검사를 구현해 보겠습니다.
2. 핵심 내용
1단계: TextField 위젯 사용
TextField는 Flutter의 기본 입력 위젯입니다.
새로운 프로젝트를 생성하거나 이 전 프로젝트를 열어 소스코드를 다음과 같이 작성합니다.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('TextField 예제'),
),
body: const TextFieldExample(),
),
);
}
}
class TextFieldExample extends StatelessWidget {
const TextFieldExample({super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const TextField(
decoration: InputDecoration(
labelText: '사용자 이름',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
print('입력 완료');
},
child: const Text('입력'),
),
],
),
);
}
}


결과
- TextField: 입력 상자가 나타나고, “사용자 이름” 레이블이 표시됩니다.
- 버튼 클릭하면 “입력 완료”가 콘솔에 출력 됩니다.
2단계: 유효성 검사
Form 위젯을 사용하면 TextField를 그룹화하고, 유효성 검사를 쉽게 구현할 수 있습니다. 다음과 같이 코드를 수정 해보세요.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Form Validation')),
body: const FormExample(),
),
);
}
}
class FormExample extends StatefulWidget {
const FormExample({super.key});
@override
State<FormExample> createState() => _FormExampleState();
}
class _FormExampleState extends State<FormExample> {
final _formKey = GlobalKey<FormState>(); // GlobalKey 정의
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey, // Form에 GlobalKey 연결
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
decoration: const InputDecoration(
labelText: '사용자 이름',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '이름을 입력하세요.';
}
return null;
},
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
if (_formKey.currentState?.validate() ?? false) {
print('폼이 유효합니다.');
}
},
child: const Text('제출'),
),
],
),
),
);
}
}



결과
- TextField: 이름 입력 필드가 나타납니다.
- 유효성 검사
- 입력 필드가 비어 있을 경우” 이름을 입력하세요”라는 오류 메시지가 표시됩니다.
- 입력 버튼을 누르면 입력 값이 콘솔에 출력됩니다.
3. 실습
1단계: 필드 추가
- 이메일 입력 필드를 추가하고, 이메일 형식을 검증하세요.
- hint
TextFormField(
decoration: const InputDecoration(
labelText: '이메일 주소',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '이메일을 입력하세요.';
} else if (!value.contains('@') || !value.contains('.')) {
return '유효한 이메일 주소를 입력하세요.';
}
return null;
},
),
2단계: 다중 유효성 검사
- 이름 필드는 최소 3자 이상 입력해야 한다는 조건을 추가하세요.
- hint
TextFormField(
decoration: const InputDecoration(
labelText: '사용자 이름',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '이름을 입력하세요.';
} else if (value.length < 3) {
return '이름은 최소 3자 이상이어야 합니다.';
}
return null;
},
),
3단계: 사용자 입력 저장
- 입력 데이터를 화면에 표시하거나 다른 변수에 저장하세요.
- hint
String _userName = '';
String _userEmail = '';
TextFormField(
decoration: const InputDecoration(
labelText: '사용자 이름',
border: OutlineInputBorder(),
),
onSaved: (value) {
_userName = value ?? '';
},
),
TextFormField(
decoration: const InputDecoration(
labelText: '이메일 주소',
border: OutlineInputBorder(),
),
onSaved: (value) {
_userEmail = value ?? '';
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save(); // 입력 값 저장
setState(() {}); // 화면 갱신
}
},
child: const Text('제출'),
),
Text('이름: $_userName'),
Text('이메일: $_userEmail'),
4. 전체 소스코드
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Form Validation')),
body: const FormExample(),
),
);
}
}
class FormExample extends StatefulWidget {
const FormExample({super.key});
@override
State<FormExample> createState() => _FormExampleState();
}
class _FormExampleState extends State<FormExample> {
final _formKey = GlobalKey<FormState>(); // GlobalKey 정의
String _userName = '';
String _userEmail = '';
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey, // Form에 GlobalKey 연결
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
decoration: const InputDecoration(
labelText: '사용자 이름',
border: OutlineInputBorder(),
),
onSaved: (value) {
_userName = value ?? '';
},
validator: (value) {
if (value == null || value.isEmpty) {
return '이름을 입력하세요.';
} else if (value.length < 3) {
return '이름은 최소 3자 이상이어야 합니다."';
}
return null;
},
),
const SizedBox(height: 10),
TextFormField(
decoration: const InputDecoration(
labelText: '이메일 주소',
border: OutlineInputBorder(),
),
onSaved: (value) {
_userEmail = value ?? '';
},
validator: (value) {
if (value == null || value.isEmpty) {
return '이메일을 입력 하세요';
} else if (!value.contains('@') || !value.contains('.')) {
return '유효한 이메일 주소를 입력하세요';
}
},
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState?.save(); //입력 값 저장
setState(() {
//화면 갱신
});
}
},
child: const Text('입력'),
),
SizedBox(height: 5),
Text('이름: $_userName'),
SizedBox(height: 5),
Text('이메일: $_userEmail'),
],
),
),
);
}
}

5. 결론
이번에는 사용자 입력을 처리고, Form을 사용해 유효성 검사를 구현하는 방법을 알아보았습니다. 이를 통해 사용자가 앱과 상호작용할 수 있는 폼 기반 UI를 구성할 수 있습니다. 다음 단계에서는 Flutter에서 애니메이션 트랜지션 기초를 알아보겠습니다.
6. Q&A
Q: 여러 입력 필드를 하나의 Form에서 처리할 수 있나요?
A: 네, Form 위젯 내부에 여러 TextFormField를 추가하고, 각각의 유효성 검사 및 저장 로직을 정의할 수 있습니다.
Q: 유효성 검사를 강제하지 않고 입력 값을 저장하려면 어떻게 하나요?
A: validator를 사용하지 않고 onSaved만 정의하면 유효성 검사를 생략하고 데이터를 저장할 수 있습니다.
감사합니다.
댓글 남기기