본문 바로가기
REACT-NATIVE

리액트 네이티브 07 - 파이어베이스 로그인 적용

by 일태찡 2023. 11. 14.

먼저 파이어베이스로 이동하고 다음 순서에 따라 프로젝트를 생성해 줍니다.

 

https://firebase.google.com/?hl=ko

 

Firebase | Google’s Mobile and Web App Development Platform

개발자가 사용자가 좋아할 만한 앱과 게임을 빌드하도록 지원하는 Google의 모바일 및 웹 앱 개발 플랫폼인 Firebase에 대해 알아보세요.

firebase.google.com

 

 

 

프로젝트가 생성되면 다음 순서대로 설정을 시작합니다.

 

 

 

  1. 먼저 터미널에 파이어베이스를 설치하고
  2. 다음 코드 내용을 집어넣을 자바스크립트 파일을 루트 폴더에 만듭니다.

firebase.js

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

import 'firebase/auth'; // 인증을 위한 파이어베이스 사용

// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: "your apiKey",
  authDomain: "your authDomain",
  projectId: "your projectId",
  storageBucket: "your storageBucket",
  messagingSenderId: "your messagingSenderId",
  appId: "your appId"
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);

export default app;

 

App.js 에 다음과 같이 import 해줍니다.

 

import app from "./firebase";

 

이렇게 설정하면 다음과 같은 경고가 하나 뜹니다.

 

WARN  [2023-11-09T12:24:34.011Z]  @firebase/auth: Auth (10.5.2):
You are initializing Firebase Auth for React Native without providing
AsyncStorage. Auth state will default to memory persistence and will not
persist between sessions. In order to persist auth state, install the package
"@react-native-async-storage/async-storage" and provide it to 
initializeAuth:

import { initializeAuth, getReactNativePersistence } from 'firebase/auth';
import ReactNativeAsyncStorage from '@react-native-async-storage/async-storage';
const auth = initializeAuth(app, {
  persistence: getReactNativePersistence(ReactNativeAsyncStorage)
});

 

이는 Firebase Authentication을 초기화할 때 AsyncStorage를 제공하지 않았다는 내용이며 Firebase Authentication은 사용자 인증 상태를 저장하기 위해 로컬 스토리지를 필요로 하는데, AsyncStorage를 사용하여 이를 구현하라고 언급하고 있습니다. 그래서 경고에 표시된 내용만 추가해 주면 됩니다.

 

firebase.js

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { initializeAuth, getReactNativePersistence } from "firebase/auth";
import ReactNativeAsyncStorage from "@react-native-async-storage/async-storage";

// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
import "firebase/auth";
// Your web app's Firebase configuration
const firebaseConfig = {
	apiKey: "your apiKey",
	authDomain: "your authDomain",
	projectId: "your projectId",
	storageBucket: "your storageBucket",
	messagingSenderId: "your messagingSenderId",
	appId: "you appId",
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);

const auth = initializeAuth(app, {
	persistence: getReactNativePersistence(ReactNativeAsyncStorage),
});

export default app;

 

회원가입

LoginScreen.js

import { getAuth, createUserWithEmailAndPassword } from "firebase/auth"; // 1
import Toast from "react-native-toast-message"; // 4
    
    ...
    
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    
    // 2
    const auth = getAuth();
    
    // 3
    const handleSignUp = async () => {
		try {
			const user = await createUserWithEmailAndPassword(auth, email, password);
			console.log(user);
            		// 4
			Toast.show({
				type: "success",
				text1: "회원가입 성공",
				text2: `${email}로 회원가입 성공했습니다`,
			});
			// 입력창 비워주기
			setEmail("");
			setPassword("");
		} catch (error) {
        		// 4
			Alert.alert(
				"회원가입 도중 문제가 발생했습니다.",
				error.message,
				[
					{
						text: "닫기",
						onPress: () => {
							console.log("닫기");
						},
					},
				],
				{ cancelable: true }
			);
		}
	};
    
    ...

 

  1. `getAuth`와 `createUserWithEmailAndPassWord`를 가져오고
  2. auth를 가져옵니다.
  3. handleSignUp 함수를 만들고 이를 제출 버튼에 연결합니다.
  4. Toast와 Alert로 회원가입 성공/실패 상황에 대한 반응도 구현했습니다.

그다음 다시 파이어베이스로 넘어가 다음과 같이 설정해야 합니다.

 

 

다음과 같이 TextInput 태그에 연결했는데 또 에러가 발생했습니다.

 

LoginScreen.js

...
				<TextInput
					placeholder="이메일"
					value={email}
					onChange={setEmail}
					style={styles.input}
				/>
				<TextInput
					placeholder="비밀번호"
					value={password}
					onChange={setPassword}
					style={styles.input}
					secureTextEntry
				/>
...

 

ERROR  Warning: Failed prop type: Invalid prop `value` of type `object` supplied to `TextInput`, expected `string`.
    at TextInput

 

이 오류는 TextInput 컴포넌트의 value prop에 객체(object)가 전달되어 발생한 것이며 TextInputonChange prop을 사용하여 상태를 업데이트할 때, onChange의 콜백 함수가 객체를 반환하고 있을 수 있습니다. 이를 해결하기 위해 onChange에서 콜백 함수가 받는 인자 중에서 event 객체를 통해 nativeEvent.text를 추출하여 사용하면 됩니다.

 

LoginScreen.js

...
                		<TextInput
					placeholder="이메일"
					value={email}
					onChange={(e) => {
						setEmail(e.nativeEvent.text); // 여기
					}}
					style={styles.input}
				/>
				<TextInput
					placeholder="비밀번호"
					value={password}
					onChange={(e) => {
						setPassword(e.nativeEvent.text); // 여기
					}}
					style={styles.input}
					secureTextEntry
				/>
...

 

위와 같이 수정하여 text를 받아오게 확인시킬 수 있으며 iOS는 onChange 이벤트에 대해 e.nativeEvent.text를 포함하는데, Android에서는 기본적으로 이 속성이 없습니다. 그래서 Android에서도 동일한 방식으로 작업하려면 e.nativeEvent.text를 명시적으로 사용하는 것이 Android와 iOS 간의 차이점을 조절할 수도 있습니다.

 

로그인

LoginScreen.js

import { getAuth, signInWithEmailAndPassword, onAuthStateChanged } from "firebase/auth";
import { useNavigation } from "@react-navigation/native";
...

	const auth = getAuth();
    	const navigation = useNavigation();
    
    	// 로그인 상태 확인
	useEffect(() => {
		onAuthStateChanged(auth, (user) => {
			console.log("user", user);
			if (user) {
				navigation.replace("Main");
			}
		});
	}, []);

	const handleLogin = async () => {
		try {
			const user = await signInWithEmailAndPassword(auth, email, password);
			console.log(user);
		} catch (error) {
			Alert.alert(
				"로그인 도중 문제가 발생했습니다.",
				error.message,
				[
					{
						text: "닫기",
						onPress: () => {
							console.log("닫기");
						},
					},
				],
				{ cancelable: true }
			);
		}
	};

 

로그인도 함수를 만들고 `getAuth`와 `signInWithEmailAndPassword`를 가져와 구현하면 됩니다. `cancelable: true` 설정은 에러창을 닫기 버튼 외에 창 바깥쪽을 눌러도 닫히게 만드는 속성입니다. 로그인에 성공하면 Main 스크린으로 넘어갑니다.

 

로그아웃

MainScreen.js

import { signOut, getAuth } from "firebase/auth";
import { useNavigation } from "@react-navigation/native";

...

	const auth = getAuth();
	const navigation = useNavigation();

	const handleLogout = async () => {
		try {
			await signOut(auth);
			navigation.replace("Login");
		} catch (error) {
			console.log(error.message);
		}
	};
    
...

 

`getAuth`와 `signOut`을 가져와 함수를 만들고 버튼에 연결하면 끝입니다. 로그아웃이 되고 Login 스크린으로 넘어갑니다.