앱을 완전히 껐다가 켰을 때, 다시 로그인해야 하면 참 귀찮아진다. 사용자들의 편의를 위해서 요즘 앱들은 껐다가 다시 켜도 로그인되어 있는 화면을 다시 보여주곤 한다.
그렇게 할 수 있는 것은, 앱이 꺼지기 직전에 사용자가 로그인이 되어 있었는지 체크 한 후, 로그인한 적이 있으면(아직 로그아웃하지 않았다면) 바로 메인 화면으로 보내는 로직을 사용하기 때문이다.
그러기 위해선, 앱이 꺼져도 저장/관리한 데이터는 계속 사용할 수 있는 AsyncStorage를 사용해야 한다.
expo install @react-native-async-storage/async-storage
AsyncStorage는 react-native에서 가져와 사용할 수 있는 라이브러리로, 주로 이럴 때 사용한다.
1) 로그인 후 앱을 껐다 켰다 ⇒ 로그인이 되어 있으면 바로 메인 화면 보여주기
2) 글을 작성하다 페이지를 이탈했다 ⇒ 작성 중이던 글을 가져오기
3) 사용자가 좋아요를 눌렀던 게시글이 있다 ⇒ 매번 서버에서 가져오지 않고, AsyncStorage에서 꺼내 관리하기
이렇게 앱이 꺼져도 보존되면 편리한 데이터들을 AsyncStorage에 담아 관리하곤 한다.
로그인했을 때 AsyncStorage 통에 로그인한 사용자 이메일을 저장한다. 그럼 이 통을 살펴볼 때 사용자 이메일이 있으면 로그인 한 적이 있다는 뜻이고,
로그아웃했을 때 AsyncStorage 통에 든 이메일을 지운다. 그럼 로그아웃 시 이 통을 조사했을 때, 아무것도 안 나오는 것이다.
순서로 살펴보자면,
1) SignInpage에서 화면이 그려진 다음 useEffect가 실행된다
2) useEffect에서 AsyncStorage 속 session 통을 살펴본다
3) 이메일이 들어 있다면 TabNavigator로 보낸다
4) 이메일이 들어 있지 않다면 Loading 화면을 끄고 로그인 화면을 보여준다
간단하쥬~? :)
import * as firebase from 'firebase';
import 'firebase/firestore';
import { Alert, AsyncStorage } from 'react-native';
export async function registration(nickName, email, password, navigation) {
try {
console.log(nickName, email, password);
await firebase.auth().createUserWithEmailAndPassword(email, password);
const currentUser = firebase.auth().currentUser;
const db = firebase.firestore();
db.collection('users').doc(currentUser.uid).set({
email: currentUser.email,
nickName: nickName,
});
Alert.alert('회원가입 성공!');
await AsyncStorage.setItem('session', email);
navigation.push('TabNavigator');
} catch (err) {
Alert.alert('무슨 문제가 있는 것 같아요! => ', err.message);
}
}
export async function signIn(email, password, navigation) {
try {
await firebase.auth().signInWithEmailAndPassword(email, password);
await AsyncStorage.setItem('session', email);
navigation.push('TabNavigator');
} catch (err) {
Alert.alert('로그인에 문제가 있습니다! ', err.message);
}
}
export async function logout(navigation) {
try {
console.log('로그아웃!!');
const currentUser = firebase.auth().currentUser;
await AsyncStorage.removeItem('session');
await firebase.auth().signOut();
navigation.push('SignInPage');
} catch (err) {
Alert.alert('로그 아웃에 문제가 있습니다! ', err.message);
}
}
export async function addDiary(content) {
try {
const db = firebase.firestore();
let userRef = await db.collection('users').doc(content.uid);
let data = await userRef.get().then((doc) => {
return doc.data();
});
console.log(data.nickName);
content.author = data.nickName;
await db
.collection('diary')
.doc(content.date + 'D')
.set(content);
return true;
} catch (err) {
Alert.alert('글 작성에 문제가 있습니다! ', err.message);
return false;
}
}
export async function imageUpload(blob, date) {
const storageRef = firebase
.storage()
.ref()
.child('diary/' + date);
const snapshot = await storageRef.put(blob);
const imageUrl = await snapshot.ref.getDownloadURL();
blob.close();
return imageUrl;
}
export async function getData() {
try {
const db = firebase.firestore();
const snapshot = await db.collection('diary').get();
let data = [];
snapshot.docs.map((doc) => {
data.push(doc.data());
});
return data;
} catch (err) {
console.log(err);
return false;
}
}
import React, { useState, useEffect } from 'react';
import { StyleSheet, ImageBackground, Alert, AsyncStorage } from 'react-native';
import { Container, Content, Text, Form, Button } from 'native-base';
const bImage = require('../assets/background.png');
import ItemInput from '../components/ItemInput';
import { signIn } from '../config/firebaseFunctions';
import * as firebase from 'firebase';
import Loading from '../pages/Loading';
export default function SignInPage({ navigation }) {
const [ready, setReady] = useState(false);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [emailError, setEmailError] = useState('');
const [passwordError, setPasswordError] = useState('');
useEffect(() => {
navigation.addListener('beforeRemove', (e) => {
e.preventDefault();
});
setTimeout(() => {
AsyncStorage.getItem('session', (err, result) => {
console.log('ASYNCSTORAGE');
console.log(result);
if (result) {
navigation.push('TabNavigator');
} else {
setReady(true);
}
});
setReady(true);
}, 1000);
}, []);
const doSignIn = () => {
//Email 로그인 버튼을 누를 때 실행되는 함수
if (email == '') {
setEmailError('이메일을 입력해주세요');
return false;
} else {
setEmailError('');
}
if (password == '') {
setPasswordError('비밀번호를 입력해주세요');
return false;
} else {
setPasswordError('');
}
signIn(email, password, navigation);
};
const setEmailFunc = (itemInputEmail) => {
//이메일 상태값을 관리하는 함수
setEmail(itemInputEmail);
};
const setPasswordFunc = (itemInputPassword) => {
//패스워드 상태값을 관리하는 함수
setPassword(itemInputPassword);
};
const goSignUp = () => {
navigation.navigate('SignUpPage');
};
return ready ? (
<Container style={styles.container}>
<ImageBackground source={bImage} style={styles.backgroundImage}>
<Content contentContainerStyle={styles.content} scrollEnabled={false}>
<Text style={styles.title}>
<Text style={styles.highlite}>we</Text>gram
</Text>
<Form style={styles.form}>
<ItemInput
title={'이메일'}
type={'email'}
setFunc={setEmailFunc}
error={emailError}
/>
<ItemInput
title={'비밀번호'}
type={'password'}
setFunc={setPasswordFunc}
error={passwordError}
/>
</Form>
{/* <Button full style={styles.snsSignUp}>
<Text>Facebook 로그인</Text>
</Button> */}
<Button full style={styles.emailSignIn} onPress={doSignIn}>
<Text>Email 로그인</Text>
</Button>
<Button full style={styles.emailSignUp} onPress={goSignUp}>
<Text style={{ color: '#333' }}>회원가입</Text>
</Button>
</Content>
</ImageBackground>
</Container>
) : (
<Loading />
);
}
const styles = StyleSheet.create({
container: {},
backgroundImage: {
width: '100%',
height: '100%',
},
content: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgba(52, 52, 52, 0.5)',
margin: 20,
borderRadius: 20,
},
title: {
fontSize: 25,
fontWeight: '700',
color: '#fff',
textAlign: 'center',
},
highlite: {
fontSize: 25,
fontWeight: '700',
color: '#9bf6ff',
textAlign: 'center',
},
form: {
width: 250,
borderRadius: 10,
paddingBottom: 20,
paddingRight: 20,
paddingLeft: 20,
marginTop: 10,
},
label: {
color: '#fff',
},
input: {
color: '#fff',
},
snsSignUp: {
alignSelf: 'center',
width: 250,
marginTop: 10,
borderRadius: 10,
backgroundColor: '#4667A5',
},
emailSignIn: {
alignSelf: 'center',
width: 250,
marginTop: 5,
borderRadius: 10,
backgroundColor: '#333',
},
emailSignUp: {
alignSelf: 'center',
width: 250,
marginTop: 5,
borderRadius: 10,
backgroundColor: '#eee',
borderWidth: 1,
borderColor: '#333',
},
});