(TIL) 4. React-Native & FireBase : Google-Login

dongwu-kim·2021년 9월 2일
0

React-Native

목록 보기
4/17
post-thumbnail

하루종일 시도해서 드디어 로그인을 구현했습니다.

0.

오늘 오전에는 Android 공식문서를 보며 기본 구성을 조금 공부해봤는데 지금 기억에 남는 것은 액티비티, 서비스, BroadCast Receiver, contentProvier 가 존재한다는 사실 뿐이네요.

솔직히 공부하고 사용할 일이 없어 현재로서는 잘 와닿지 않습니다.

그래도 전혀 모르는 것과는 다른게 FireBase 연동을 경험하며 메니페스트에 대해 접근할 일이 좀 있었고, 전에 보았던 menifest 파일의 내부가 저 요소들로 이루어졌다는 사실을 오늘 새롭게 알게 되었습니다.

모르고 봤을 때는 뭔 태그들인지 관심도 없었는데, 알고 보니 이게 이런 구성들이겠구나~ 하는 생각이 들었습니다.

그래도 나름 App project를 하게 되었으니 열심히 공부해보겠습니다.

1.

FireBase는 분명 쉽고 간편한 Web, App 개발을 도와준다고 했던 것 같은데 이상하게 저는 React-Native에게 아직은 좀 불친절한 것 같습니다.

그래도 혼자 백엔드까지 공부하는 방법 보다는 무조건 편하겠다는 생각이 듭니다.

버전별로 달라지는 사용법은 논외로 치더라도, 문서별로 동일한 기능을 구현하는 데 상이한 방법을 알려주는 것 같습니다.

그래서 구글링을 열심히 해보지만, 해외 고수분들의 글도 최근 버전 기준으로는 크게 없는 것 같긴 합니다.

RN 개발을 위해서라면 m1은 잠시 잊어주시는게 좋아보입니다.

앞으로는 github를 뒤져보는게 차라리 낫지 않을까 하는 생각도 있습니다.

실제로 오늘은 github를 통해 solution을 꽤 찾았습니다.

2.

최근 4일 정도 개발하면서 드는 생각이 있었는데, 확실히 앱을 만들 때 있어 React Native로 시작하는 것은 장단점이 확실한 것 같습니다.

  • 장점
  1. ios, android 둘을 한번에 개발할 수 있다.
  2. 기존 TS 문법과 tsx, jsx, React 등을 바로 사용할 수 있어 Web을 배우던 사람도 빠르게 서비스를 제공할 수 있는 App에 도전할 수 있겠다.
  • 단점
  1. ios, android 둘을 한번에 개발할 수 있다.
  2. 설계 및 작성 단계에서 ios, android의 동작 원리를 따로 공부하지 않는 이상 자연스럽게 체득할 수 없다.

정도가 있습니다.

FireBase는 논외로 하겠습니다.

실행만 되어도 감사한 수준이니까요...😂

3.

아무튼 오늘은 처음으로 Web이 아닌 App을 호스팅하기 위한 한 걸음을 내딛었습니다.

구글 로그인 화면이 켜지는 순간 느껴지던 쾌감은 사실 처음 HTML을 공부할 때와 비슷했던 것 같습니다.

역시 새로운 것에 대한 도전은 늘 재밌는 것 같습니다.

코드도 올리겠지만, 사실 Refactoring을 참고할만한 자료가 많지 않아 제 멋대로 작성해서 부끄러운 마음입니다.

그래도 나름 새로운 시도도 해보고, 앞으로 어떤 방식으로 로그인 데이터와 로직을 관리할지 고민도 해보는 하루였습니다.

pratt이 알려주신 힌트는 class 키워드였는데, class로 다양한 루트의 소셜로그인을 관리하는 것을 한 번 날잡고 고민해봐야겠네요.

blocker는 전반적으로 FireBase 연동과 social signin 에 대한 blocker였고, 오늘은 추후 사용할 realTimeDataBase를 위한 공부 방향을 조금 고민하는 날이기도 했습니다.

그럼 코드를 좀 가져오겠습니다.

4.

먼저 나름 utils와 비슷한데, 특정 기능과 선언만을 가지고 있는 googleSignIn file입니다.

import {
  GoogleSignin,
  statusCodes,
} from '@react-native-google-signin/google-signin';
import {WEB_CLIENT_ID} from '../config';
import auth from '@react-native-firebase/auth';

interface GoogleSignIn {
  googleLogInConfigure: Function;
  signIn: Function;
  signOut: Function;
}

export interface GoogleUserInfo {
  userInfo: {
    idToken: string;
    serverAuthCode: string;
    scopes: string[];
    user: {
      email: string;
      id: string;
      givenName: string;
      familyName: string;
      photo: string;
      name: string;
    };
  };
}

export const googleSignInLogic: GoogleSignIn = {
  googleLogInConfigure: () => {
    GoogleSignin.configure({
      webClientId: WEB_CLIENT_ID,
    });
  },

  signIn: async (setUser: Function) => {
    try {
      await GoogleSignin.hasPlayServices();
      const userInfo = await GoogleSignin.signIn();
      const {idToken} = userInfo;
      const googleCredential = auth.GoogleAuthProvider.credential(idToken);
      auth().signInWithCredential(googleCredential);
      setUser(userInfo);
    } catch (error) {
      if (error.code === statusCodes.SIGN_IN_CANCELLED) {
      } else if (error.code === statusCodes.IN_PROGRESS) {
      } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
      }
    }
  },

  signOut: async (setUser: Function) => {
    try {
      await GoogleSignin.signOut();
      setUser(null);
    } catch (error) {
      console.log(error);
    }
  },
};

실제 google SignIn module을 제공하는 github repo에 가시면 response data의 type이 잘 명시되어 있는 json? 구조를 볼 수 있습니다.

따라서 로직 부분이나 interface 등을 유심히 보실 필요는 없을 것 같습니다.

.env 등으로 key를 관리하려고 했는데, RN도 React와 동일한 방식이 적용될까 궁금해서 시도해보려다 포기했었습니다.

그래서 급한대로 config.js를 만들어 ignore에 추가하는 것으로 타협했는데, react-native-dotEnv를 사용해야 하나 고민이 됩니다.

사실 오늘 react-native-dotEnv를 시도했으나 실패했습니다.

5.

다음은 Login이 실제로 이루어지는 screen component입니다.

navigation 개념을 사용해서 props로는 navigation을 가져왔습니다.

해당 개념은 저보다 더 좋은 글이 많으니, 적지 않겠습니다.

import React, {useState} from 'react';
import {StyleSheet, SafeAreaView, View, Text, Button} from 'react-native';
import {GoogleSigninButton} from '@react-native-google-signin/google-signin';
import {googleSignInLogic, GoogleUserInfo} from '../../utils/googleSignin';

export const Login = ({navigation}) => {
  const {googleLogInConfigure, signIn, signOut} = googleSignInLogic;
  googleLogInConfigure();

  const [userInfo, setUserInfo] = useState<GoogleUserInfo | null>(null);

  const {navigate} = navigation;
  if (userInfo) {
    navigate('ToDoList');
  }

  const {loginContainer} = styles;

  return (
    <SafeAreaView style={loginContainer}>
      <View>
        {userInfo && <Text>Hi</Text>}
        <GoogleSigninButton
          size={GoogleSigninButton.Size.Wide}
          color={GoogleSigninButton.Color.Dark}
          onPress={() => {
            signIn(setUserInfo);
          }}
        />
        <Button
          title="SignOut"
          onPress={() => {
            signOut(setUserInfo);
          }}
        />
      </View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  loginContainer: {
    flex: 1,
    backgroundColor: 'blue',
  },
});

위 googleSignIn 파일에서 대부분의 로직을 관리하기 때문에 해당 컴포넌트는 스타일만 신경써주면 됩니다.

그래도 React를 하긴 해서 컴포넌트 블럭 내부가 생각보다 깨끗해서 다행입니다.

해당 로직과 컴포넌트에 남은 과제가 있다면,

  • SignIn을 class로 관리해보고, class를 사용했을 때 객체 메서드 정의보다 어떤 점이 좋은지

  • 다양한 방식의 로그인이 하나의 결과를 도출하기에 class가 적합한 것인지?

정도가 될 것 같습니다.

6.

중구난방 구성으로 글을 작성하는데, TIL의 경우 어떤 기승전결이 있어야 하는지 아직 감이 없어서 그렇습니다.

이것저것 다 시도해보고, 한창 배울 때라 기승전결을 정하기도 어려운 점 이해해주시면 감사하겠습니다.

그럼 이번 글은 여기서 마치겠습니다. 다들 편안한 밤 되세요.

0개의 댓글