프로젝트/할일목록 앱 (RN)

15. LoginButton 컴포넌트에 소셜 로그인 기능 구현하기

syleemomo 2023. 10. 26. 12:58
728x90

https://github.com/react-native-google-signin/google-signin

 

GitHub - react-native-google-signin/google-signin: Google Sign-in for your React Native applications

Google Sign-in for your React Native applications. Contribute to react-native-google-signin/google-signin development by creating an account on GitHub.

github.com

 

* SettingsScreen 컴포넌트에 구현된 소셜로그인 기능을 LoginButton 컴포넌트로 옮기기

npm install @react-native-async-storage/async-storage

지금 당장은 사용하지 않지만 추후 사용자정보를 저장할 일이 있을수 있으므로 로컬 스토리지를 사용하기 위하여 위 라이브러리를 설치한다. 하지만 로컬 스토리지를 당장 사용하지 않는 이유는 로그인후 사용자 정보를 로컬 스토리지에 저장하고 나서 앱을 메모리에서 지우고 다시 시작하면 로컬스토리지에 저장되어 있던 사용자 정보가 사라진다. 하지만 분명 로그아웃을 하지 않은 상태이므로 로그인 상태이다. 이렇게 로그인 상태인데도 불구하고 사용자 정보가 없는 문제가 있어서 현재는 앱을 시작할때마다 구글 로그인 라이브러리를 이용하여 로그인 상태여부를 체크하고 있다. 

import React, { useEffect } from 'react'
import { View, Button, StyleSheet, Alert } from 'react-native'
import { GoogleSignin, GoogleSigninButton  } from '@react-native-google-signin/google-signin'

function LoginButton({navigation}){
    const googleSigninConfigure = () => { 
        GoogleSignin.configure({
        webClientId:
            '137262950194-gcouccatiffjp4ei8aqfi05uruv5j4dl.apps.googleusercontent.com',
        })
    }

    const signInWithGoogle = async () => {
        try {
            await GoogleSignin.hasPlayServices()
            const userInfoFromGoogle = await GoogleSignin.signIn()

            if(userInfoFromGoogle){
                console.log("사용자 연락처: ", userInfoFromGoogle.user)
                navigation.navigate('App')
            }
        } catch (error) {
            if (error.code === statusCodes.SIGN_IN_CANCELLED) {
                console.log('user cancelled the login flow')
                Alert.alert('user cancelled the login flow')
            } else if (error.code === statusCodes.IN_PROGRESS) {
                console.log('sign in is in progress already')
                Alert.alert('sign in is in progress already')
            } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
                console.log('play services not available or outdated')
                Alert.alert('play services not available or outdated')
            } else {
                console.log('some other error happened')
                Alert.alert('some other error happened')
            }
        }
    }

    useEffect(() => {
        googleSigninConfigure()
    }, [])

    return (
        <View style={styles.buttonWrapper}>
            <GoogleSigninButton
                size={GoogleSigninButton.Size.Wide}
                color={GoogleSigninButton.Color.Dark}
                onPress={signInWithGoogle}
                disabled={false}
                style={styles.signInBtn}
            />
        </View>
    )
}
export default LoginButton

const styles = StyleSheet.create({
    buttonWrapper: {
        position: 'absolute',
        left: 0, right: 0,
        bottom: 100,
    },
    signInBtn: {
        marginTop: 10,
        marginLeft: 'auto',
        marginRight: 'auto'
    },
})

components > LoginButton.js 파일을 위와 같이 수정한다. 

import React, { useEffect } from 'react'

useEffect 함수를 추가로 임포트한다.

import { View, Button, StyleSheet, Alert } from 'react-native'

로그인중 에러가 발생하면 경고창을 띄워 사용자에게 알람을 줄 수 있도록 Alert 컴포넌트를 추가로 임포트한다.

import { GoogleSignin, GoogleSigninButton  } from '@react-native-google-signin/google-signin'

소셜로그인을 위하여 구글 로그인 라이브러리를 이용한다. 

const googleSigninConfigure = () => { 
    GoogleSignin.configure({
    webClientId:
        '137262950194-gcouccatiffjp4ei8aqfi05uruv5j4dl.apps.googleusercontent.com',
    })
}

구글 로그인을 사용하기 위한 초기설정 부분이다. 이 부분은 screens > SettingsScreen.js 파일과 중복되는 코드이므로 추후 리팩토링하기로 한다. 

const signInWithGoogle = async () => {
        try {
            await GoogleSignin.hasPlayServices()
            const userInfoFromGoogle = await GoogleSignin.signIn()

            if(userInfoFromGoogle){
                console.log("사용자 연락처: ", userInfoFromGoogle.user)
                navigation.navigate('App')
            }
        } catch (error) {
            if (error.code === statusCodes.SIGN_IN_CANCELLED) {
                console.log('user cancelled the login flow')
                Alert.alert('user cancelled the login flow')
            } else if (error.code === statusCodes.IN_PROGRESS) {
                console.log('sign in is in progress already')
                Alert.alert('sign in is in progress already')
            } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
                console.log('play services not available or outdated')
                Alert.alert('play services not available or outdated')
            } else {
                console.log('some other error happened')
                Alert.alert('some other error happened')
            }
        }
    }

로그인에 성공하고, 사용자 정보가 존재하면 홈화면(App 컴포넌트)로 이동한다. 만약 로그인에 실패하거나 중간에 에러가 발생하면 사용자에게 경고창을 띄워서 무슨 이유로 로그인에 실패했는지 알려준다. 해당 부분도 screens > SettingsScreen.js 파일의 코드와 유사한 부분이 많으므로 추후 리팩토링하기로 한다. 

useEffect(() => {
    googleSigninConfigure()
}, [])

초기 로딩시 구글로그인 설정을 진행한다. 해당 부분도 screens > SettingsScreen.js 파일의 코드와 중복되므로 추후 리팩토링하기로 한다. 

<GoogleSigninButton
    size={GoogleSigninButton.Size.Wide}
    color={GoogleSigninButton.Color.Dark}
    onPress={signInWithGoogle}
    disabled={false}
    style={styles.signInBtn}
/>

랜딩페이지에서 구글 로그인 버튼을 보여준다. 해당 부분도 screens > SettingsScreen.js 파일의 코드와 중복되므로 추후 리팩토링하기로 한다. 

signInBtn: {
    marginTop: 10,
    marginLeft: 'auto',
    marginRight: 'auto'
},

로그인버튼에 대한 스타일코드이다. 해당 부분도 screens > SettingsScreen.js 파일의 코드와 중복되므로 추후 리팩토링하기로 한다. 

import React, { useState, useEffect } from 'react'
import { View, Text, StyleSheet, ActivityIndicator } from 'react-native'
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { GoogleSignin } from '@react-native-google-signin/google-signin'

import LandingScreen from './screens/LandingScreen';
import App from './App'

const Stack = createNativeStackNavigator()

function stackRouter(){
    const [isLoggedIn, setIsLoggedIn] = useState(null)
    checkLoginState = async () => {
        const isSignedIn = await GoogleSignin.isSignedIn()
        setIsLoggedIn(isSignedIn)
    }
    useEffect(() => {
        checkLoginState()
    }, [])
    return (
        <NavigationContainer>
            <Stack.Navigator 
                initialRouteName="Landing"
                screenOptions={{headerShown: false}} // 탭메뉴 헤더와 겹치지 않도록 함
            >
                {!isLoggedIn && <Stack.Screen name="Landing" component={LandingScreen}/>}
                <Stack.Screen name="App" component={App}/>
            </Stack.Navigator>
        </NavigationContainer>
    )
}
export default stackRouter

루트 디렉토리의 stackRouter 컴포넌트를 위와 같이 수정한다. 

import { GoogleSignin } from '@react-native-google-signin/google-signin'

로그인 여부를 판별하기 위하여 해당 라이브러리를 임포트한다.

const [isLoggedIn, setIsLoggedIn] = useState(null)

로그인 여부에 대한 상태를 저장하기 위하여 state 를 정의한다.

checkLoginState = async () => {
    const isSignedIn = await GoogleSignin.isSignedIn()
    setIsLoggedIn(isSignedIn)
}

GoogleSignin 객체를 이용하여 로그인 여부를 조회한다. 그런 다음 로그인 여부에 대한 상태를 업데이트한다.

useEffect(() => {
    checkLoginState()
}, [])

랜딩페이지 초기 로딩시 사용자의 로그인 여부를 판별한다.

{!isLoggedIn && <Stack.Screen name="Landing" component={LandingScreen}/>}

사용자가 로그인을 하지 않은 경우나 로그아웃한 경우에만 랜딩페이지를 보여준다. 만약 로그인이 된 경우라면 곧바로 홈화면(App 컴포넌트)로 이동한다.

 

* 랜딩페이지에서 로그인 테스트해보기

랜딩페이지에서 로그인하면 홈화면으로 이동한다. 추후 앱을 껐다가 다시 켜면 로그인 여부를 조회해서 이미 로그인이 되어있으면 자동으로 홈화면으로 이동한다. 그렇지 않으면 랜딩페이지 화면을 보여준다. 

 

구글 로그인 테스트

 

728x90