#05 Flutter 기초 - 로그인 페이지 구현
목차
Ⅱ 로그인 페이지 구성 요소
01. MaterialApp의 속성
initialRoute
- 앱 실행 시 초기 화면을 설정하는 속성
- 초기 페이지를 문자열 경로로 지정
routes
- 앱 내의 화면 경로와 해당 위젯을 매핑
- key-value 쌍으로 구성된 Map 형태
- 각 경로는 문자열 키로 설정, 해당 경로에 표시될 페이지를 위젯 생성 함수로 설정
MaterialApp(
initialRoute: '/home',
routes: {
'/home': (context) => HomePage(),
'/login': (context) => LoginPage(),
},
);
02. Navigator
Navigator
- Flutter에서 화면 간 이동을 관리하는 클래스
- 스택(Stack) 구조를 사용해 페이지를 관리
주요 메서드
- push() : 새로운 화면을 스택에 추가
- pop() : 현재 화면을 스택에서 제거하고 이전 화면으로 돌아감
- pushNamed() : 이름 기반 경로로 화면 이동
- popAndPushNamed() : 현재 화면을 제거하고 새 화면 추가
TextButton(
onPressed: () {
Navigator.pushNamed(context, '/login');
},
child: Text('로그인 페이지로 이동'),
);
03. Form & TextFormField
Form
- 여러 입력 필드를 하나의 Form으로 묶어 관리할 수 있도록 도와주는 위젯
- 유효성 검사, 폼 제출 처리, 입력 값 저장 및 초기화 기능을 제공
Form의 주요 속성
- key : 폼 상태를 관리하기 위한 GlobalKey를 사용
- child : 폼 내부에 포함될 입력 필드 위젯
final _formKey = GlobalKey<FormState>();
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: '이메일'),
),
TextButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
print('폼 제출 성공');
}
},
child: Text('제출'),
),
],
),
);
TextFormField
- 사용자 텍스트 입력을 받는 위젯
- 유효성 검사와 폼 상태 관리가 가능한 위젯
TextFormField의 주요 속성
- decoration : 스타일 지정
- validator : 입력 값의 유효성 검사 함수를 설정
- keyboardType : 키보드 타입 지정
- onSaved : 폼 제출 시 입력 값을 저장할 때 사용
TextFormField(
decoration: InputDecoration(
labelText: '이메일',
hintText: '이메일을 입력하세요',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '이메일을 입력해주세요';
}
return null;
},
onSaved: (value) {
print('저장된 값: $value');
},
);
04. GlobalKey & FormState
GlobalKey
- Flutter의 Key 시스템에서 위젯의 상태에 대한 전역 참조를 제공
- 이를 통해 특정 위젯의 상태에 직접 접근하고 제어할 수 있음
FormState
- Form 위젯의 상태를 나타내는 클래스
- 이를 통해 폼에 입력된 데이터 관리, 유효성 검사 등의 작업 가능
FormState의 주요 메서드
- validate() : 폼의 모든 입력 필드에 대해 유효성 검사를 실행
- save() : 입력 필드의 값을 저장
- reset() : 폼의 상태를 초기화
GlobalKey와 FormState의 작동 원리
- Form 위젯의 key 속성에 GlobalKey<FormState> 등록
- Form 위젯은 key 속성을 통해 자신의 상태를 관리할 수 있는 FormState 객체와 연결
- GlobalKey를 사용해 다른 위젯 계층에서도 상태에 접근할 수 있음
- 런타임 시점에 Form과 그 안에 속한 TextFormField의 상태가 FormState에 저장
- 앱이 실행되면 Form 위젯과 그 안의 모든 TextFormField 위젯들이 FormState 객체에 등록 됨
- 이후 입력 값과 상태가 FormState 객체에서 관리 됨
- Form 위젯의 상태 제어
- FormState 객체에 접근하기 위해 _formKey.currentState를 사용
- 이를 통해 유효성 검사(validate()), 입력값 저장(save()) 등의 작업 수행
Ⅱ 로그인 화면 예제
01. 페이지 생성 및 main 함수 세팅
main 함수
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
initialRoute: '/login',
routes: {
'/login': (context) => LoginPage(),
'/home': (context) => HomePage(),
},
);
}
}
로그인 페이지
class LoginPage extends StatelessWidget {
LoginPage({super.key});
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
children: [
SizedBox(height: 30),
Text('로그인 페이지', style: TextStyle(fontSize: 30)),
],
),
),
);
}
}
홈 페이지
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
SizedBox(height: 30),
Text('홈 페이지', style: TextStyle(fontSize: 30)),
],
),
);
}
}
02. 로그인 페이지 사용자 입력 필드 구현
class LoginPage extends StatelessWidget {
// GlobalKey 선언 - 폼 상태를 관리하기 위한 Key
final _formKey = GlobalKey<FormState>();
// 사용자가 입력한 데이터를 저장하는 멤버 변수 선언
String _email = '';
String _password = '';
LoginPage({super.key});
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
children: [
SizedBox(height: 30),
Text('로그인 페이지', style: TextStyle(fontSize: 30)),
// Form 위젯 선언
Form(
key: _formKey, // Form 상태 관리를 위해 생성한 _formKey
child: Column(
children: [
// email 입력 필드
TextFormField(
decoration: InputDecoration(
label: Text('email'),
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'email을 입력하세요.';
}
return null;
},
onSaved: (value) {
_email = value ?? '';
},
),
SizedBox(height: 20),
// 비밀번호 입력 필드
TextFormField(
decoration: InputDecoration(
label: Text('password'),
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'password를 입력하세요.';
}
return null;
},
onSaved: (value) {
_password = value ?? '';
},
),
],
),
)
],
),
),
);
}
}
코드 설명
- GlobalKey<FormState>()로 폼 위젯의 상태를 관리
- TextFormField 위젯의 validator에서 입력된 값의 유효성 검사
- TextFormField 위젯의 onSaved에서 email과 password필드에 값 삽입
03. 로그인 버튼 구현 및 페이지 이동
로그인 페이지
(...)
body: Column(
children: [
SizedBox(height: 30),
Text('로그인 페이지', style: TextStyle(fontSize: 30)),
Form(
key: _formKey,
child: Column(
children: [
// email 입력 필드
TextFormField(...),
SizedBox(height: 20),
// 비밀번호 입력 필드
TextFormField(...),
// 로그인 버튼
TextButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
// 유효성 검사를 다 통과하면 아래 로직 호출
print('Email : ${_email}');
print('Password : ${_password}');
// 유효성 검사 통과 후 Navigator를 이용한 페이지 이동
Navigator.pushNamed(context, '/home');
}
},
child: Text('LOGIN', style: TextStyle(color: Colors.black)),
)
],
),
)
],
),
코드 설명
- TextButton 위젯의 onPressed에서 유효성 검증 로직 호출
- _formKey.currentState!.validate()
- 현재 Form에 등록된 모든 TextFormField의 validator 속성을 실행
- 모든 validator가 유효하면 true를 반환하고, 그렇지 않으면 false를 반환
- 유효성 검사를 통과하면 Navigator를 이용해 화면 이동
홈 페이지
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
children: [
SizedBox(height: 30),
Text('홈 페이지', style: TextStyle(fontSize: 30)),
TextButton(
onPressed: () {
// 버튼 누르면 Navigator를 이용한 페이지 이동
Navigator.pop(context);
},
child: Text('로그인 페이지로 이동'),
)
],
),
),
);
}
}
'Programming > Flutter' 카테고리의 다른 글
[Flutter] Flutter 기초 #07 - Flutter 비동기 & HTTP 통신 (1) | 2025.01.14 |
---|---|
[Flutter] Flutter 기초 #06 - StatefulWidget (0) | 2025.01.14 |
[Flutter] Flutter 기초 #04 - 탭 네비게이션 (0) | 2025.01.13 |
[Flutter] Flutter 기초 #03 - Flutter 스크롤 위젯 (0) | 2025.01.11 |
[Flutter] Flutter 기초 #02 - Flutter 기본 위젯 (0) | 2025.01.09 |