Flutter Firebase & DDD(4)

김형태·2024년 1월 28일
0

Flutter

목록 보기
5/5

IAuthFacade 추상화는 이전 부분 이후에 적용됩니다. 이 인터페이스를 사용하면 인증이 실제로 어떻게 구현되는지에 대한 단서 없이도 로그인 form 애플리케이션 로직을 작성할 수 있습니다. statesevents를 사용하여 UI가 BLoC와 통신하는 방법을 모델링해 보겠습니다.

BloC overview

다이어그램에 표시된 것처럼 BLoC는 원시(raw) 데이터가 포함된 UI로부터 events를 입력받고 무엇보다도 검증된 데이터가 포함된 sates를 출력합니다. 이제 SignInFormBloc에 대한 클래스를 만들어 보겠습니다.

BLoC 라이브러리에 아직 익숙하지 않다면 먼저 이 튜토리얼을 확인하세요.
파일 생성에 소요되는 시간을 크게 줄이려면 VS Code 또는 IntelliJ용 확장 프로그램을 사용하세요.

flutter_bloc을 종속성으로 추가해 보겠습니다.

dependencies:
  ...
  flutter_bloc: ^3.2.0

application/auth/sign_in_form 경로가 존재하도록 새 디렉터리를 만듭니다. 위에서 언급한 확장 프로그램을 사용하여 "sign_in_form"이라는 이름의 BloC을 만듭니다.

eventsstates프레젠테이션 계층의 일부라는 점을 기억하는 것이 중요합니다. 따라서 Flutter 위젯에서 진행되는 작업과 밀접하게 결합되어 있으면 괜찮습니다.

Events

로그인 form의 UI에서는 어떤 이벤트가 발생할 수 있을까요? 다른 로그인 버튼을 누르는 것 외에도 DDD를 따르지 않는 한 일반적으로 UI에서 직접 처리되는 두 가지 다른 이벤트(이메일 및 비밀번호 입력 변경)도 있습니다. union으로 표현하면 이벤트는 다음과 같습니다.

part of 'sign_in_form_bloc.dart';


abstract class SignInFormEvent with _$SignInFormEvent {
  // Notice that these events take in "raw" unvalidated Strings
  const factory SignInFormEvent.emailChanged(String emailStr) = EmailChanged;
  const factory SignInFormEvent.passwordChanged(String passwordStr) =
      PasswordChanged;
  const factory SignInFormEvent.registerWithEmailAndPasswordPressed() =
      RegisterWithEmailAndPasswordPressed;
  const factory SignInFormEvent.signInWithEmailAndPasswordPressed() =
      SignInWithEmailAndPasswordPressed;
  const factory SignInFormEvent.signInWithGooglePressed() =
      SignInWithGooglePressed;
}

part of 때문에 여기서는 일반적인 part '*.freezed.dart' 문을 지정하지 않습니다.

State

BLoC는 일반적으로 state의 여러 하위 클래스(또는 union cases)를 출력합니다. 이는 단일 상태 클래스만 있는 UI 데이터의 유효성을 검사하는 BLoC와는 다릅니다.

로그인 양식의 UI에 다시 전달하려면 무엇이 필요합니까?

1. Validated values

TextFormFields에 오류 메시지를 표시할 수 있도록 검증된 EmailAddressPassword 값 개체를 다시 전달하고 싶습니다.

2. Auth progress

진행률 인디케이터를 표시하는 것은 당연한 일이므로 bool isSubmitting도 다시 전달해야 합니다.

3. Success or error backend response

백엔드에서 문제가 발생할 때 에러 Snackbar를 표시하려면 IAuthFacade에서 반환된 Either<AuthFailure, Unit>을 다시 전달해야 합니다. 우리는 이를 authFailureOrSuccess라고 부르겠습니다. 인증 백엔드 "response"이라고 생각하면 됩니다.

그러나 처음에는 사용자가 버튼을 누를 때까지 응답이 없습니다. 처음에는 authFailureOrSuccess 필드에 null을 할당할 수 있지만 이것이 좋지 않다는 것을 알고 있습니다.

훨씬 더 나은 옵션은 Option을 사용하는 것입니다. Either와 마찬가지로 SomeNone이라는 두 값의 union입니다. 이는 nullNone union cases로 대체되는 일종의 null을 허용하지 않는 유형입니다. Some union case만이 Either<AuthFailure, Unit>이 될 값을 보유합니다.

4. Whether or not to show input error messages

마지막으로 로그인/등록 버튼을 처음 누른 후에만 TextFormFields 아래에 입력 유효성 검사 오류 메시지를 표시하려고 합니다. 이는 bool showErrorMessages 내부의 UI로 다시 전달됩니다.

part of 'sign_in_form_bloc.dart';


abstract class SignInFormState with _$SignInFormState {
  const factory SignInFormState({
     EmailAddress emailAddress,
     Password password,
     bool showErrorMessages,
     bool isSubmitting,
     Option<Either<AuthFailure, Unit>> authFailureOrSuccessOption,
  }) = _SignInFormState;

  factory SignInFormState.initial() => SignInFormState(
        emailAddress: EmailAddress(''),
        password: Password(''),
        showErrorMessages: false,
        isSubmitting: false,
        authFailureOrSuccessOption: none(),
      );
}

Bloc

eventsstate 데이터 클래스는 프레젠테이션 계층에 있는 뷰 모델로 볼 수 있지만 SignInFormBloc 클래스 자체는 애플리케이션 로직을 수행합니다. 즉, 다른 계층이 함께 작동하도록 조정합니다.

이곳은 원시 String이 검증된 ValueObject로 바뀌고 IAuthFacade의 메서드가 호출되는 곳입니다. 여기서 수행되는 로직은 수신 이벤트를 상태로 변환하는 데 중점을 둡니다.

File & class setup

다음 글을 위해 로직 작성을 남겨두겠지만, 최소한 파일을 설정해 보겠습니다. 확장 프로그램에 의해 생성된 기본 events 및 states에 대한 변경 사항으로 인해 freezed에 대한 part 문을 추가하고 initialState를 변경해야 합니다. 또한, IAuthFacade 종속성을 위한 필드를 추가하겠습니다.

part 'sign_in_form_event.dart';
part 'sign_in_form_state.dart';

part 'sign_in_form_bloc.freezed.dart';

class SignInFormBloc extends Bloc<SignInFormEvent, SignInFormState> {
  final IAuthFacade _authFacade;

  SignInFormBloc(this._authFacade);

  
  SignInFormState get initialState => SignInFormState.initial();

  
  Stream<SignInFormState> mapEventToState(
    SignInFormEvent event,
  ) async* {
    // TODO: Implement
  }
}

이제 마침내 코드 생성을 시작하기 위해 가장 선호하는 명령을 실행할 시간입니다.

flutter pub run build_runner watch --delete-conflicting-outputs

Get ready for the logic

우리는 UI에서 수행할 수 있는 events와 BLoC가 UI에 값을 다시 전달하는 방법인 state를 모델링하여 이 부분에서 중요한 단계를 수행했습니다. 이 모든 것이 준비되면 바로 애플리케이션 로직 작성으로 넘어갈 수 있습니다.

profile
steady

0개의 댓글