signIn method
소셜 로그인 실행
provider에 따라 해당 소셜 로그인을 실행합니다.
반환값
AuthResult를 반환합니다:
- 성공 시:
result.success == true,result.user사용 가능 - 실패 시:
result.success == false,result.errorMessage확인
사용 예시
기본 사용법 (if-else)
final result = await kAuth.signIn(AuthProvider.kakao);
if (result.success) {
print('환영합니다, ${result.user?.displayName}!');
navigateToHome();
} else {
print('로그인 실패: ${result.errorMessage}');
showErrorDialog(result.errorMessage);
}
함수형 스타일 (fold)
final result = await kAuth.signIn(AuthProvider.kakao);
result.fold(
onSuccess: (user) {
print('환영합니다, ${user.displayName}!');
navigateToHome(user);
},
onFailure: (failure) {
print('실패: ${failure.message}');
showErrorDialog(failure.message);
},
);
상세 처리 (when - 성공/취소/실패 구분)
final result = await kAuth.signIn(AuthProvider.kakao);
result.when(
success: (user) {
print('로그인 성공: ${user.displayName}');
navigateToHome(user);
},
cancelled: () {
print('사용자가 로그인을 취소했습니다');
showSnackBar('로그인이 취소되었습니다');
},
failure: (failure) {
print('로그인 실패: ${failure.message}');
showErrorDialog(failure.message);
},
);
체이닝 스타일
final result = await kAuth.signIn(AuthProvider.kakao);
result
.onSuccess((user) {
saveUserToDatabase(user);
navigateToHome(user);
})
.onFailure((failure) {
logError(failure.code, failure.message);
showError(failure.message);
});
Implementation
Future<AuthResult> signIn(AuthProvider provider) async {
_ensureInitialized();
// 동시 로그인 방지
if (_signInLock != null) {
KAuthLogger.warning('로그인 진행 중 - 대기', provider: provider.name);
return _signInLock!.future;
}
_signInLock = Completer<AuthResult>();
KAuthLogger.info(
'로그인 시작',
provider: provider.name,
);
final providerImpl = _providers[provider];
if (providerImpl == null) {
final error = KAuthError.fromCode(
ErrorCodes.providerNotConfigured,
details: {'provider': provider.name},
);
final result = AuthResult.failure(
provider: provider,
errorMessage: error.message,
errorCode: error.code,
errorHint: error.hint,
);
_signInLock!.complete(result);
_signInLock = null;
return result;
}
final stopwatch = Stopwatch()..start();
try {
// Provider signIn 호출 (다형성 활용)
final result = await providerImpl.signIn();
stopwatch.stop();
if (result.success && result.user != null) {
_lastResult = result;
_emitAuthState(result.user);
// 로그인 콜백 호출
if (onSignIn != null) {
try {
final tokens = AuthTokens(
accessToken: result.accessToken,
refreshToken: result.refreshToken,
idToken: result.idToken,
expiresAt: result.expiresAt,
);
_serverToken = await onSignIn!(provider, tokens, result.user!);
KAuthLogger.debug(
'로그인 콜백 완료',
provider: provider.name,
data: {'hasServerToken': _serverToken != null},
);
} catch (e) {
KAuthLogger.error(
'로그인 콜백 실패',
provider: provider.name,
error: e,
);
}
}
// 세션 저장
await _saveSession(result);
KAuthLogger.info(
'로그인 성공',
provider: provider.name,
data: {
'userId': result.user?.id,
'hasEmail': result.user?.email != null,
'duration': '${stopwatch.elapsedMilliseconds}ms',
},
);
} else if (!result.success) {
KAuthLogger.warning(
'로그인 실패',
provider: provider.name,
data: {
'errorCode': result.errorCode,
'errorMessage': result.errorMessage,
'duration': '${stopwatch.elapsedMilliseconds}ms',
},
);
}
// 동시 로그인 lock 해제
_signInLock?.complete(result);
_signInLock = null;
return result;
} catch (e) {
// 예외 발생 시에도 lock 해제 보장
final errorResult = AuthResult.failure(
provider: provider,
errorMessage: '로그인 중 예기치 않은 오류가 발생했습니다.',
errorCode: ErrorCodes.loginFailed,
);
_signInLock?.complete(errorResult);
_signInLock = null;
return errorResult;
}
}