728x90
이번 글에서는 Flutter 블로그 회원가입 기능을 구현합니다.
서버 요청, 상태 관리(Riverpod), 예외 처리를 적용하여 안정적인 회원가입 흐름을 만듭니다.
1. 회원가입 기능 설계
회원가입 요청을 보낼 때 어떤 변수가 필요할까요?
뷰모델(SessionGVM)에서 회원가입을 처리하며, 다음과 같은 기능을 수행합니다.
📌 뷰모델의 역할
- 회원 정보 관리
- 회원가입 시 입력된 username, email, **password**를 관리합니다.
- 회원가입 요청 처리
- 서버에 회원가입 요청을 보내고, 성공하면 로그인 페이지로 이동합니다.
- 예외 처리
- 네트워크 오류, 서버 에러 등을 처리하여 사용자에게 알림을 제공합니다.
2. UserRepository에서 회원가입 요청 처리
UserRepository는 서버 API와 통신하는 역할을 담당하며, 회원가입 요청을 처리하기 위해 save() 메서드를 정의합니다.
📌 UserRepository 코드
class UserRepository {
const UserRepository();
// 사용자 등록 요청
Future<Map<String, dynamic>> save(Map<String, dynamic> reqData) async {
Response response = await dio.post('/join', data: reqData);
// 바디 추출
Map<String, dynamic> responseBody = response.data; // header, body 중에 body 만 추출
logger.i(responseBody);
return responseBody;
}
}
📌 설명
- dio.post('/join', data: reqData)를 사용하여 회원가입 요청을 서버로 전송합니다.
- 응답 데이터를 Map<String, dynamic> 형태로 반환하여, 이후 뷰모델(SessionGVM)에서 처리할 수 있도록 합니다.
3. 상태 관리(ViewModel)에서 회원가입 처리
SessionGVM(Global ViewModel)은 앱 전역에서 로그인 상태를 관리할 뿐만 아니라, 회원가입 기능도 담당합니다.
📌 SessionGVM 클래스 (회원가입 기능 추가)
// 회원 등록 행위
// 1. UserRepository 에 회원 등록 API 요청 확인
Future<void> join(String username, String email, String password) async {
try {
// map 구조 만들어서 던지자
final body = {
'username': username,
'email': email,
'password': password,
};
Map<String, dynamic> resBody = await userRepository.save(body);
// 통신은 성공이지만 내부 판별 오류시 방어적 코드 작성
if (!resBody['success']) {
ExceptionHandler.handleException(
resBody['errorMessage'], StackTrace.current);
return; // 실행의 제어권 반납
}
// 성공하면 회원 가입 완료 -> 화면이동 코드
// ExceptionHandler.handleException(
// '회원가입 성공', StackTrace.current);
// 바로 화면 이동 처리
Navigator.pushNamed(mContext, '/login');
} catch (e, stackTrace) {
ExceptionHandler.handleException('서버 연결 실패', stackTrace);
}
}
📌 설명
- 서버 요청
- username, email, password를 포함한 데이터를 서버로 전송합니다.
- 예외 처리
- 서버 응답이 실패한 경우(success: false), ExceptionHandler를 호출하여 오류 메시지를 사용자에게 표시합니다.
- 회원가입 성공 후 이동
- 회원가입이 완료되면 로그인 페이지('/login')로 이동합니다.
4. 로그인 및 회원가입 상태 관리 (Provider 등록)
Riverpod을 활용하여 SessionGVM을 전역적으로 관리합니다.
📌 Provider 선언
// 창고 관리자 선언 (창고 - 뷰모델), 창고 어떤 관리해라 지정 !!
final sessionProvider = NotifierProvider<SessionGVM, SessionUser>(
() => SessionGVM(),
);
📌 설명
- **NotifierProvider**를 사용하여 SessionGVM을 전역적으로 관리합니다.
- UI에서 sessionProvider를 사용하면 회원가입 및 로그인 상태 변경 사항을 자동으로 반영할 수 있습니다.
5. 회원가입 UI (JoinPage & JoinBody) 구현
회원가입 화면에서 사용자가 username, email, password를 입력하고,
회원가입 버튼을 눌러 회원가입 요청을 보낼 수 있도록 UI를 구성합니다.
📌 JoinPage (회원가입 페이지)
class JoinPage extends StatelessWidget {
const JoinPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: JoinBody(),
);
}
}
📌 설명
- 회원가입 화면을 Scaffold에 감싸고 JoinBody를 출력합니다.
📌 JoinBody (회원가입 UI 및 뷰모델 연결)
class JoinBody extends ConsumerWidget {
final _usernameController = TextEditingController();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
JoinBody({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
// 뷰 모델(창고) 자체에 접근
SessionGVM gvm = ref.read(sessionProvider.notifier);
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
children: [
const CustomLogo('f-story'),
CustomAuthTextFormField(
text: 'Username',
controller: _usernameController,
),
const SizedBox(height: mediumGap),
CustomAuthTextFormField(
text: 'Email',
controller: _emailController,
),
const SizedBox(height: mediumGap),
CustomAuthTextFormField(
text: 'Password',
controller: _passwordController,
obscureText: true,
),
const SizedBox(height: largeGap),
CustomElevatedButton(
text: '회원 가입',
click: () {
gvm.join(
_usernameController.text.trim(),
_emailController.text.trim(),
_passwordController.text.trim(),
);
},
),
CustomTextButton(
text: '로그인 페이지로 이동',
click: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => LoginPage()),
);
},
),
],
),
);
}
}
📌 설명
- CustomAuthTextFormField → 회원가입 입력 필드를 추가합니다.
- CustomElevatedButton → 회원가입 버튼을 눌렀을 때 gvm.join()을 호출하여 회원가입 요청을 보냅니다.
- CustomTextButton → 로그인 페이지로 이동하는 버튼을 추가합니다.
✅ 마무리
회원가입 기능 흐름 정리
- 사용자가 Username, Email, Password를 입력합니다.
- 회원가입 버튼 클릭 시, **gvm.join()**을 호출하여 회원가입 요청을 보냅니다.
- SessionGVM이 서버로 회원가입 요청을 전송하고, 성공 시 로그인 페이지로 이동합니다.
- 회원가입 실패 시, **ExceptionHandler**를 통해 오류 메시지를 표시합니다.
다음 글에서는 자동 로그인 UI와 기능 구현을 해보겠습니다. 🚀
로그인 기능구현이 궁금하다면??
2025.02.09 - [Flutter/App] - [Flutter] 블로그 만들기 - 로그인 기능 구현 (상태관리 및 예외처리)
'Flutter > App' 카테고리의 다른 글
[Flutter] 블로그 만들기 - 게시글 관리 및 로그아웃 기능 구현 (0) | 2025.02.10 |
---|---|
[Flutter] 블로그 만들기 -자동 로그인 기능 구현 및 UI (0) | 2025.02.10 |
[Flutter] 블로그 만들기 - 로그인 기능 구현 (상태관리 및 예외처리) (0) | 2025.02.09 |
"[Flutter] 블로그 만들기 - 서버 통신의 모든 것 (Dio 활용) (0) | 2025.02.09 |
[Flutter] 블로그 만들기 - 로그인 UI 구성 (0) | 2025.02.08 |