기업협업 TIL - 09. 디자인패턴 실전 적용...!

확실히 아직 개념이 정확히 정리가 덜 되었나보다.
이론과 실제는 하늘과 땅 차이였다.
오늘은 동기의 멋진 실제 코드를 보며 View, Presenter, UseCase, Repository의 예시를 정리해봐야겠다.
오늘의 예시는 이미 등록된 아이디(이메일)만 소셜로그인 후 메인페이지로 이동할 수 있게 해주는 로직이다.

Repository

export class UsingFirebaseDB {
  getDataFromDB(
    firebaseDBPath: string,
    eventType: EventType,
    successCallback: (a: DataSnapshot, b?: string | null) => any,
  ) {
    return database().ref(firebaseDBPath).once(eventType).then(successCallback);
  }

  setDataToDB(firebaseDBPath: string, value: any) {
    return database().ref(firebaseDBPath).set(value);
  }

  updateDataInDB(firebaseDBPath: string, value: any) {
    return database().ref(firebaseDBPath).update(value);
  }
}

Firebase의 DB에 접근하는 로직이다.

export class SignInRepository extends UsingFirebaseDB {
  async getAccessUserEmailFromDB(): Promise<string[] | null> {
    try {
      const email: string[] = await super.getDataFromDB(
        '/access/email',
        'value',
        snapshot => {
          return [...snapshot.val()];
        },
      );
      return email;
    } catch {
      return null;
    }
  }
}

위의 로직을 이용해 DB로부터 승인된 아이디(이메일) 목록을 가져온다.

UseCase

export class SignInUseCase extends SignInRepository {
  async signInGoogleAuth(): Promise<ISignInUser | null> {
    GoogleSignin.configure({
      webClientId: CLIENT_ID,
    });

    try {
      const userInfo = await GoogleSignin.signIn();
      const {idToken, user} = userInfo;
      const googleCredential = auth.GoogleAuthProvider.credential(idToken);
      await auth().signInWithCredential(googleCredential);
      return user;
    } catch (e) {
      if (e.code === statusCodes.SIGN_IN_CANCELLED) {
        console.log('유저가 로그인 취소');
      } else if (e.code === statusCodes.IN_PROGRESS) {
        console.log('로그인 진행 중');
      } else if (e.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
        console.log('플레이 서비스를 사용할 수 없음');
      } else {
        console.log('그외 에러');
      }
      Alert.alert('다시 로그인 해주세요');
      return null;
    }
  }

  signInValidation(email: string, accessUserEmail: string[] | null): Boolean {
    if (accessUserEmail?.includes(email)) {
      return true;
    } else {
      return false;
    }
  }
}

여기서는 소셜로그인을 위한 로직과 Repository에서 가져왔던 아이디(이메일) 목록이 소셜로그인 된 이메일과 일치하는지 확인하는 로직이 들어간다.

Presenter

const signInLogic = new SignInUseCase();
const {signInValidation, signInGoogleAuth} = signInLogic;

const handleSocialSignIn = (
  setSignInUserInfo: React.Dispatch<React.SetStateAction<ISignInUser | null>>,
): void => {
  signInGoogleAuth().then(userInfoWithoutToken => {
    setSignInUserInfo(userInfoWithoutToken);
  });
};

export const SignInPresenter = ({navigation}: any) => {
  const {navigate} = navigation;

  const [accessUserEmail, accessUserLoading] = useAccessUserEmail();
  const [signInUserInfo, setSignInUserInfo] = useState<ISignInUser | null>(
    null,
  );

  useEffect(() => {
    if (!accessUserLoading) {
      if (signInUserInfo?.email) {
        if (signInValidation(signInUserInfo.email, accessUserEmail)) {
          navigate('Main');
        }
      }
    }
  }, [accessUserEmail, signInUserInfo]);

  return (
    <SignIn
      handleSocialSignIn={() => {
        handleSocialSignIn(setSignInUserInfo);
      }}
    />
  );
};

사실 제일 이해가 안되고 어려웠던 부분..!
소셜로그인 된 아이디와 등록된 아이디가 일치한다면 메인페이지로 넘어가는 로직이 포함되어있다.
이런 로직을 props를 통해 View에게 전달하고 View와 소통하는 역할을 한다.

View

export const SignIn = ({handleSocialSignIn}: ISignInProps) => {
  const {googleButton} = style;

  return (
    <VStack flex={1} bg="white" justifyContent="center" alignItems="center">
      <Image
        source={require('../../../../data/images/soomgo_logo_rgb.png')}
        alt="Logo"
        w="70%"
        resizeMode="contain"
        marginBottom={75}
      />
      <GoogleSigninButton
        style={googleButton}
        size={GoogleSigninButton.Size.Wide}
        color={GoogleSigninButton.Color.Light}
        onPress={handleSocialSignIn}
      />
    </VStack>
  );
};

const style = StyleSheet.create({
  googleButton: {
    position: 'absolute',
    bottom: 90,
  },
});

가장 명료하고 이해하기 쉬웠던 View!!

사실 이렇게 정리는 해놨지만 아직 완벽히 이해하지는 못했다..!
정리하고 이걸 응용해서 다른 로직을 몇 번 더 짜봐야 이해가 될 듯 하다.
기업협업도 날짜로 보면 몇 일 안남은 상황에서 당장 구현에만 매달려도 될까 말까 한 시간이라 마음이 조급하긴 하지만......
'당장의 결과물'과 '완벽히 내 것으로 만들고 이해하는 것' 둘 다 잃지 않고 얻어갈 수 있도록 남은 기간 더 힘내야겠다🥲

좋은 웹페이지 즐겨찾기