하루종일 시도해서 드디어 로그인을 구현했습니다.
오늘 오전에는 Android 공식문서를 보며 기본 구성을 조금 공부해봤는데 지금 기억에 남는 것은 액티비티, 서비스, BroadCast Receiver, contentProvier 가 존재한다는 사실 뿐이네요.
솔직히 공부하고 사용할 일이 없어 현재로서는 잘 와닿지 않습니다.
그래도 전혀 모르는 것과는 다른게 FireBase 연동을 경험하며 메니페스트에 대해 접근할 일이 좀 있었고, 전에 보았던 menifest 파일의 내부가 저 요소들로 이루어졌다는 사실을 오늘 새롭게 알게 되었습니다.
모르고 봤을 때는 뭔 태그들인지 관심도 없었는데, 알고 보니 이게 이런 구성들이겠구나~ 하는 생각이 들었습니다.
그래도 나름 App project를 하게 되었으니 열심히 공부해보겠습니다.
FireBase는 분명 쉽고 간편한 Web, App 개발을 도와준다고 했던 것 같은데 이상하게 저는 React-Native에게 아직은 좀 불친절한 것 같습니다.
그래도 혼자 백엔드까지 공부하는 방법 보다는 무조건 편하겠다는 생각이 듭니다.
버전별로 달라지는 사용법은 논외로 치더라도, 문서별로 동일한 기능을 구현하는 데 상이한 방법을 알려주는 것 같습니다.
그래서 구글링을 열심히 해보지만, 해외 고수분들의 글도 최근 버전 기준으로는 크게 없는 것 같긴 합니다.
RN 개발을 위해서라면 m1은 잠시 잊어주시는게 좋아보입니다.
앞으로는 github를 뒤져보는게 차라리 낫지 않을까 하는 생각도 있습니다.
실제로 오늘은 github를 통해 solution을 꽤 찾았습니다.
최근 4일 정도 개발하면서 드는 생각이 있었는데, 확실히 앱을 만들 때 있어 React Native로 시작하는 것은 장단점이 확실한 것 같습니다.
정도가 있습니다.
FireBase는 논외로 하겠습니다.
실행만 되어도 감사한 수준이니까요...😂
아무튼 오늘은 처음으로 Web이 아닌 App을 호스팅하기 위한 한 걸음을 내딛었습니다.
구글 로그인 화면이 켜지는 순간 느껴지던 쾌감은 사실 처음 HTML을 공부할 때와 비슷했던 것 같습니다.
역시 새로운 것에 대한 도전은 늘 재밌는 것 같습니다.
코드도 올리겠지만, 사실 Refactoring을 참고할만한 자료가 많지 않아 제 멋대로 작성해서 부끄러운 마음입니다.
그래도 나름 새로운 시도도 해보고, 앞으로 어떤 방식으로 로그인 데이터와 로직을 관리할지 고민도 해보는 하루였습니다.
pratt이 알려주신 힌트는 class 키워드였는데, class로 다양한 루트의 소셜로그인을 관리하는 것을 한 번 날잡고 고민해봐야겠네요.
blocker는 전반적으로 FireBase 연동과 social signin 에 대한 blocker였고, 오늘은 추후 사용할 realTimeDataBase를 위한 공부 방향을 조금 고민하는 날이기도 했습니다.
그럼 코드를 좀 가져오겠습니다.
먼저 나름 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를 시도했으나 실패했습니다.
다음은 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가 적합한 것인지?
정도가 될 것 같습니다.
중구난방 구성으로 글을 작성하는데, TIL의 경우 어떤 기승전결이 있어야 하는지 아직 감이 없어서 그렇습니다.
이것저것 다 시도해보고, 한창 배울 때라 기승전결을 정하기도 어려운 점 이해해주시면 감사하겠습니다.
그럼 이번 글은 여기서 마치겠습니다. 다들 편안한 밤 되세요.