---
title: 리액트 네이티브 Parse 사용자 로그인 및 로그아웃 구현 가이드
slug: docs-kr/react-native/parse-sdk/working-with-users/react-native-login
description: 리액트 네이티브에서 Parse 사용자를 로그인/로그아웃하고 내비게이션 설정하는 방법을 기술적 측면에서 상세히 설명합니다.
image: https://www.back4app.com/images/logo-social.png
createdAt: 2024-03-19T14:57:26.605Z
---

# 리액트 네이티브의 사용자 로그인 및 로그아웃

## 소개

지난 가이드에서 Parse에서 사용자 등록을 처리하는 컴포넌트를 구현한 후, 이제 동일한 <font color="#2166ae">`Parse.User`</font> 클래스를 사용하여 사용자를 로그인하고 로그아웃하는 방법을 배우게 됩니다. 또한 <font color="#2166ae">`react-navigation`</font>을 설치하고 구성하는 방법도 배우게 되어, 새로운 화면과 컴포넌트를 통해 사용자를 탐색할 수 있습니다. <font color="#2166ae">`Parse.User.logIn`</font> 메서드는 로컬 스토리지에 유효한 사용자 세션을 저장하므로, <font color="#2166ae">`currentAsync` </font>와 같은 메서드에 대한 향후 호출이 사용자 데이터를 성공적으로 검색할 수 있습니다. 반면에, <font color="#2166ae">`logOut` </font>은 이 세션을 디스크에서 지우고 Parse 서버의 연결된 서비스에서 로그아웃합니다.

::embed[]{url="https://www.youtube.com/embed/NKhzloPrIQw"}

:::hint{type="success"}
언제든지 이 튜토리얼로 구축된 전체 Android 프로젝트에 접근할 수 있습니다. GitHub 저장소에서 확인하세요.

- [코틀린 예제 저장소](https://github.com/templates-back4app/Android-Parse-Sdk-Kotlin)
- [자바 예제 저장소](https://github.com/templates-back4app/Android-Parse-Sdk-Java)
:::

## 전제 조건

:::hint{type="info"}
**이 튜토리얼을 완료하려면 다음이 필요합니다:**

- React Native 앱을 생성하고 [Back4App에 연결](https://www.back4app.com/docs/react-native/parse-sdk/react-native-sdk).
- 이전 가이드를 완료하여 [Parse 사용자 클래스에 대한 이해를 높이세요](https://www.back4app.com/docs/react-native/parse-sdk/working-with-users/react-native-login).
:::

## 목표

React Native 앱에서 Parse를 사용하여 사용자 로그인 및 로그아웃 기능을 구축합니다.

## 1 - 의존성 설치

어떤 시점에서든 모든 React Native 애플리케이션은 화면 탐색이 필요합니다. 이제 이를 위해 React Native에서 가장 많이 사용되는 라이브러리인 <font color="#2166ae">`react-navigation`</font>을 설치하고 구성하는 방법을 배웁니다.

프로젝트 루트 디렉토리로 이동하여 다음 의존성을 설치합니다:

:::BlockQuote
cd yourApp

yarn add @react-navigation/native react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
:::

iOS용으로 개발 중이라면 앱 자동 연결을 완료하기 위해 pods를 설치해야 합니다:

:::BlockQuote
cd ios

npx pod-install
:::

:::hint{type="info"}
**참고:** React Native의 <font color="#2166ae">`0.60+`</font> 버전부터 모든 플랫폼에 대해 자동으로 연결됩니다. 따라서 여전히 이전 버전의 RN을 사용하고 있다면 React Native 문서를 확인하세요 [여기](https://reactnative.dev/docs/linking-libraries-ios).&#x20;
:::

앱 진입 파일(<font color="#2166ae">`App.tsx`</font> 또는 <font color="#2166ae">`App.js`</font>), 파일의 가장 위에 이 import 라인을 추가하세요. 이제 <font color="#2166ae">`react-navigation`</font> 컨테이너 안으로 컴포넌트를 이동해야 합니다. 이 컨테이너는 앱을 <font color="#2166ae">`NavigationContainer`</font> 안에 캡슐화합니다:

:::CodeblockTabs
App.tsx/App.js

```typescript
1	import "react-native-gesture-handler";
2	// Your other imports go here
3	import { NavigationContainer } from "@react-navigation/native";
4	
5	const App = () => {
6	  return <NavigationContainer>{/* Your app code */}</NavigationContainer>;
7	}
8	
9	export default App;
```
:::

핵심 내비게이션 라이브러리는 스택, 탭, 드로어 등 다양한 추가 내비게이션 모듈을 가지고 있습니다. 스택 내비게이터는 가장 간단한 것이며, 이 가이드에서 사용할 것입니다. 설치를 진행하세요:

:::BlockQuote
\# 이것이 당신이 사용할 내비게이터입니다
yarn add @react-navigation/stack
:::

## 2 - 스택 내비게이터 만들기

이제 <font color="#2166ae">`스택 내비게이터`</font>를 생성하고 설정해 보겠습니다. 이 모듈은 앱의 화면 내비게이션을 관리하고 처리합니다. 여기서 <font color="#2166ae">`react-navigation`</font>에 대한 깊은 이해를 제공하는 것이 목표가 아니므로, 더 알고 싶으시면 [공식 문서](https://reactnavigation.org/docs/hello-react-navigation/)를 방문해 주세요.

당신의 <font color="#2166ae">`App.js`</font> (<font color="#2166ae">`App.tsx`</font> TypeScript를 사용하고 있다면) 파일에서, <font color="#2166ae">`StackNavigator`</font>를 가져오고 사용자 등록 화면을 포함하는 함수를 생성한 다음, 앱 내에 <font color="#2166ae">`NavigationContainer`</font>를 삽입하세요. 당신의 주요 파일은 다음과 같아야 합니다:

:::CodeblockTabs
App.tsx/App.js

```typescript
1	import 'react-native-gesture-handler';
2	import React from 'react';
3	import {Image, SafeAreaView, StatusBar, Text, View} from 'react-native';
4	
5	import AsyncStorage from '@react-native-async-storage/async-storage';
6	import Parse from 'parse/react-native';
7	import {NavigationContainer} from '@react-navigation/native';
8	import {createStackNavigator} from '@react-navigation/stack';
9	import {UserRegistration} from './UserRegistration';
10	import Styles from './Styles';
11	
12	// Your Parse initialization configuration goes here
13	Parse.setAsyncStorage(AsyncStorage);
14	const PARSE_APPLICATION_ID: string = 'APPLICATION_ID';
15	const PARSE_HOST_URL: string = 'HOST_URL';
16	const PARSE_JAVASCRIPT_ID: string = 'JAVASCRIPT_ID';
17	Parse.initialize(PARSE_APPLICATION_ID, PARSE_JAVASCRIPT_ID);
18	Parse.serverURL = PARSE_HOST_URL;
19	
20	// Wrap your old app screen in a separate function, so you can create a screen
21	// inside the navigator; you can also declare your screens in a separate file, 
22	// export and import here to reduce some clutter
23	function UserRegistrationScreen() {
24	  return (
25	    <>
26	      <StatusBar />
27	      <SafeAreaView style={Styles.login_container}>
28	        <View style={Styles.login_header}>
29	          <Image
30	            style={Styles.login_header_logo}
31	            source={require('./assets/logo-back4app.png')}
32	          />
33	          <Text style={Styles.login_header_text}>
34	            <Text style={Styles.login_header_text_bold}>
35	              {'React Native on Back4App - '}
36	            </Text>
37	            {' User registration'}
38	          </Text>
39	        </View>
40	        <UserRegistration />
41	      </SafeAreaView>
42	    </>
43	  );
44	}
45	
46	// Create your main navigator here
47	const Stack = createStackNavigator();
48	
49	// Add the stack navigator to your NavigationContainer
50	// and in it you can add all your app screens in the order you need
51	// them on your stack
52	const App = () => {
53	  return (
54	    <NavigationContainer>
55	      <Stack.Navigator>
56	        <Stack.Screen name="Sign Up" component={UserRegistrationScreen} />
57	      </Stack.Navigator>
58	    </NavigationContainer>
59	  );
60	};
61	
62	export default App;
```
:::

지금 앱을 실행하면 화면 상단에 화면 이름이 포함된 헤더가 나타나는 것을 알 수 있습니다:

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/Axy6jQGtw5aTsMPqRiOAG_image.png" size="50" width="358" height="732" position="center" showCaption="false"}

## 3 - 로그인 컴포넌트 만들기

이제 앱에서 <font color="#2166ae">`UserLogIn`</font> 기능 컴포넌트를 만들어 봅시다. 루트 디렉토리에 <font color="#2166ae">`UserLogIn.js`</font>라는 새 파일을 생성하고 (<font color="#2166ae">`UserLogIn.tsx`</font> TypeScript를 사용하고 있다면) 상태 훅을 사용하여 입력 요소를 추가하세요:

:::CodeblockTabs
UserLogIn.js

```javascript
1	import React, {FC, ReactElement, useState} from 'react';
2	import {
3	  Image,
4	  Text,
5	  TextInput,
6	  TouchableOpacity,
7	  View,
8	} from 'react-native';
9	import Parse from 'parse/react-native';
10	import Styles from './Styles';
11	
12	export const UserLogIn = () => {
13	  const [username, setUsername] = useState("");
14	  const [password, setPassword] = useState("");
15	
16	  return (
17	    <View style={Styles.login_wrapper}>
18	      <View style={Styles.form}>
19	        <TextInput
20	          style={Styles.form_input}
21	          value={username}
22	          placeholder={'Username'}
23	          onChangeText={(text) => setUsername(text)}
24	          autoCapitalize={'none'}
25	          keyboardType={'email-address'}
26	        />
27	        <TextInput
28	          style={Styles.form_input}
29	          value={password}
30	          placeholder={'Password'}
31	          secureTextEntry
32	          onChangeText={(text) => setPassword(text)}
33	        />
34	        <TouchableOpacity onPress={() => {}}>
35	          <View style={Styles.button}>
36	            <Text style={Styles.button_label}>{'Sign in'}</Text>
37	          </View>
38	        </TouchableOpacity>
39	      </View>
40	      <View style={Styles.login_social}>
41	        <View style={Styles.login_social_separator}>
42	          <View style={Styles.login_social_separator_line} />
43	          <Text style={Styles.login_social_separator_text}>{'or'}</Text>
44	          <View style={Styles.login_social_separator_line} />
45	        </View>
46	        <View style={Styles.login_social_buttons}>
47	          <TouchableOpacity>
48	            <View
49	              style={[
50	                Styles.login_social_button,
51	                Styles.login_social_facebook,
52	              ]}>
53	              <Image
54	                style={Styles.login_social_icon}
55	                source={require('./assets/icon-facebook.png')}
56	              />
57	            </View>
58	          </TouchableOpacity>
59	          <TouchableOpacity>
60	            <View style={Styles.login_social_button}>
61	              <Image
62	                style={Styles.login_social_icon}
63	                source={require('./assets/icon-google.png')}
64	              />
65	            </View>
66	          </TouchableOpacity>
67	          <TouchableOpacity>
68	            <View style={Styles.login_social_button}>
69	              <Image
70	                style={Styles.login_social_icon}
71	                source={require('./assets/icon-apple.png')}
72	              />
73	            </View>
74	          </TouchableOpacity>
75	        </View>
76	      </View>
77	    </View>
78	  );
79	};
```

UserLogIn.tsx

```typescript
1	import React, {FC, ReactElement, useState} from 'react';
2	import {
3	  Image,
4	  Text,
5	  TextInput,
6	  TouchableOpacity,
7	  View,
8	} from 'react-native';
9	import Parse from 'parse/react-native';
10	import Styles from './Styles';
11	
12	export const UserLogIn: FC<{}> = ({}): ReactElement => {
13	  const [username, setUsername] = useState("");
14	  const [password, setPassword] = useState("");
15	
16	  return (
17	    <View style={Styles.login_wrapper}>
18	      <View style={Styles.form}>
19	        <TextInput
20	          style={Styles.form_input}
21	          value={username}
22	          placeholder={'Username'}
23	          onChangeText={(text) => setUsername(text)}
24	          autoCapitalize={'none'}
25	          keyboardType={'email-address'}
26	        />
27	        <TextInput
28	          style={Styles.form_input}
29	          value={password}
30	          placeholder={'Password'}
31	          secureTextEntry
32	          onChangeText={(text) => setPassword(text)}
33	        />
34	        <TouchableOpacity onPress={() => {}}>
35	          <View style={Styles.button}>
36	            <Text style={Styles.button_label}>{'Sign in'}</Text>
37	          </View>
38	        </TouchableOpacity>
39	      </View>
40	      <View style={Styles.login_social}>
41	        <View style={Styles.login_social_separator}>
42	          <View style={Styles.login_social_separator_line} />
43	          <Text style={Styles.login_social_separator_text}>{'or'}</Text>
44	          <View style={Styles.login_social_separator_line} />
45	        </View>
46	        <View style={Styles.login_social_buttons}>
47	          <TouchableOpacity>
48	            <View
49	              style={[
50	                Styles.login_social_button,
51	                Styles.login_social_facebook,
52	              ]}>
53	              <Image
54	                style={Styles.login_social_icon}
55	                source={require('./assets/icon-facebook.png')}
56	              />
57	            </View>
58	          </TouchableOpacity>
59	          <TouchableOpacity>
60	            <View style={Styles.login_social_button}>
61	              <Image
62	                style={Styles.login_social_icon}
63	                source={require('./assets/icon-google.png')}
64	              />
65	            </View>
66	          </TouchableOpacity>
67	          <TouchableOpacity>
68	            <View style={Styles.login_social_button}>
69	              <Image
70	                style={Styles.login_social_icon}
71	                source={require('./assets/icon-apple.png')}
72	              />
73	            </View>
74	          </TouchableOpacity>
75	        </View>
76	      </View>
77	    </View>
78	  );
79	};
```
:::

이제 상태 변수를 사용하여 호출할 함수를 구현할 수 있습니다.<font color="#2166ae">`Parse.User.logIn`</font>메서드:

:::CodeblockTabs
JavaScript

```javascript
1	const doUserLogIn = async function () {
2	  // Note that these values come from state variables that we've declared before
3	  const usernameValue = username;
4	  const passwordValue = password;
5	  return await Parse.User.logIn(usernameValue, passwordValue)
6	    .then(async (loggedInUser) => {
7	      // logIn returns the corresponding ParseUser object
8	      Alert.alert(
9	        'Success!',
10	        `User ${loggedInUser.get('username')} has successfully signed in!`,
11	      );
12	      // To verify that this is in fact the current user, currentAsync can be used
13	      const currentUser = await Parse.User.currentAsync();
14	      console.log(loggedInUser === currentUser);
15	      return true;
16	    })
17	    .catch((error) => {
18	      // Error can be caused by wrong parameters or lack of Internet connection
19	      Alert.alert('Error!', error.message);
20	      return false;
21	    });
22	};
```

```typescript
1	const doUserLogIn = async function (): Promise<boolean> {
2	  // Note that these values come from state variables that we've declared before
3	  const usernameValue: string = username;
4	  const passwordValue: string = password;
5	  return await Parse.User.logIn(usernameValue, passwordValue)
6	    .then(async (loggedInUser: Parse.User) => {
7	      // logIn returns the corresponding ParseUser object
8	      Alert.alert(
9	        'Success!',
10	        `User ${loggedInUser.get('username')} has successfully signed in!`,
11	      );
12	      // To verify that this is in fact the current user, currentAsync can be used
13	      const currentUser: Parse.User = await Parse.User.currentAsync();
14	      console.log(loggedInUser === currentUser);
15	      return true;
16	    })
17	    .catch((error: object) => {
18	      // Error can be caused by wrong parameters or lack of Internet connection
19	      Alert.alert('Error!', error.message);
20	      return false;
21	    });
22	};
```
:::

이 함수를 <font color="#2166ae">`UserLogIn`</font> 컴포넌트 안에, <font color="#2166ae">`return`</font> 호출 바로 전에 삽입하여 호출하고 테스트할 수 있도록 하세요. 폼의 로그인 버튼 <font color="#2166ae">`onPress`</font> 액션을 <font color="#2166ae">`() => doUserLogIn()`</font>로 업데이트하고 <font color="#2166ae">`Alert`</font>를 <font color="#2166ae">`react-native`</font>. 이제 당신의 컴포넌트는 다음과 같아야 합니다:

:::CodeblockTabs
UserLogIn.js

```javascript
1	import React, {FC, ReactElement, useState} from 'react';
2	import {
3	  Alert,
4	  Image,
5	  Text,
6	  TextInput,
7	  TouchableOpacity,
8	  View,
9	} from 'react-native';
10	import Parse from 'parse/react-native';
11	import Styles from './Styles';
12	
13	export const UserLogIn = () => {
14	  const [username, setUsername] = useState('');
15	  const [password, setPassword] = useState('');
16	
17	  const doUserLogIn = async function () {
18	    // Note that these values come from state variables that we've declared before
19	    const usernameValue = username;
20	    const passwordValue = password;
21	    return await Parse.User.logIn(usernameValue, passwordValue)
22	      .then(async (loggedInUser) => {
23	        // logIn returns the corresponding ParseUser object
24	        Alert.alert(
25	          'Success!',
26	          `User ${loggedInUser.get('username')} has successfully signed in!`,
27	        );
28	        // To verify that this is in fact the current user, currentAsync can be used
29	        const currentUser = await Parse.User.currentAsync();
30	        console.log(loggedInUser === currentUser);
31	        return true;
32	      })
33	      .catch((error) => {
34	        // Error can be caused by wrong parameters or lack of Internet connection
35	        Alert.alert('Error!', error.message);
36	        return false;
37	      });
38	  };
39	
40	  return (
41	    <View style={Styles.login_wrapper}>
42	      <View style={Styles.form}>
43	        <TextInput
44	          style={Styles.form_input}
45	          value={username}
46	          placeholder={'Username'}
47	          onChangeText={(text) => setUsername(text)}
48	          autoCapitalize={'none'}
49	          keyboardType={'email-address'}
50	        />
51	        <TextInput
52	          style={Styles.form_input}
53	          value={password}
54	          placeholder={'Password'}
55	          secureTextEntry
56	          onChangeText={(text) => setPassword(text)}
57	        />
58	        <TouchableOpacity onPress={() => doUserLogIn()}>
59	          <View style={Styles.button}>
60	            <Text style={Styles.button_label}>{'Sign in'}</Text>
61	          </View>
62	        </TouchableOpacity>
63	      </View>
64	      <View style={Styles.login_social}>
65	        <View style={Styles.login_social_separator}>
66	          <View style={Styles.login_social_separator_line} />
67	          <Text style={Styles.login_social_separator_text}>{'or'}</Text>
68	          <View style={Styles.login_social_separator_line} />
69	        </View>
70	        <View style={Styles.login_social_buttons}>
71	          <TouchableOpacity>
72	            <View
73	              style={[
74	                Styles.login_social_button,
75	                Styles.login_social_facebook,
76	              ]}>
77	              <Image
78	                style={Styles.login_social_icon}
79	                source={require('./assets/icon-facebook.png')}
80	              />
81	            </View>
82	          </TouchableOpacity>
83	          <TouchableOpacity>
84	            <View style={Styles.login_social_button}>
85	              <Image
86	                style={Styles.login_social_icon}
87	                source={require('./assets/icon-google.png')}
88	              />
89	            </View>
90	          </TouchableOpacity>
91	          <TouchableOpacity>
92	            <View style={Styles.login_social_button}>
93	              <Image
94	                style={Styles.login_social_icon}
95	                source={require('./assets/icon-apple.png')}
96	              />
97	            </View>
98	          </TouchableOpacity>
99	        </View>
100	      </View>
101	    </View>
102	  );
103	};
```

UserLogIn.tsx

```typescript
1	import React, {FC, ReactElement, useState} from 'react';
2	import {
3	  Alert,
4	  Image,
5	  Text,
6	  TextInput,
7	  TouchableOpacity,
8	  View,
9	} from 'react-native';
10	import Parse from 'parse/react-native';
11	import Styles from './Styles';
12	
13	export const UserLogIn: FC<{}> = ({}): ReactElement => {
14	  const [username, setUsername] = useState('');
15	  const [password, setPassword] = useState('');
16	
17	  const doUserLogIn = async function (): Promise<boolean> {
18	    // Note that these values come from state variables that we've declared before
19	    const usernameValue: string = username;
20	    const passwordValue: string = password;
21	    return await Parse.User.logIn(usernameValue, passwordValue)
22	      .then(async (loggedInUser: Parse.User) => {
23	        // logIn returns the corresponding ParseUser object
24	        Alert.alert(
25	          'Success!',
26	          `User ${loggedInUser.get('username')} has successfully signed in!`,
27	        );
28	        // To verify that this is in fact the current user, currentAsync can be used
29	        const currentUser: Parse.User = await Parse.User.currentAsync();
30	        console.log(loggedInUser === currentUser);
31	        return true;
32	      })
33	      .catch((error: object) => {
34	        // Error can be caused by wrong parameters or lack of Internet connection
35	        Alert.alert('Error!', error.message);
36	        return false;
37	      });
38	  };
39	
40	  return (
41	    <View style={Styles.login_wrapper}>
42	      <View style={Styles.form}>
43	        <TextInput
44	          style={Styles.form_input}
45	          value={username}
46	          placeholder={'Username'}
47	          onChangeText={(text) => setUsername(text)}
48	          autoCapitalize={'none'}
49	          keyboardType={'email-address'}
50	        />
51	        <TextInput
52	          style={Styles.form_input}
53	          value={password}
54	          placeholder={'Password'}
55	          secureTextEntry
56	          onChangeText={(text) => setPassword(text)}
57	        />
58	        <TouchableOpacity onPress={() => doUserLogIn()}>
59	          <View style={Styles.button}>
60	            <Text style={Styles.button_label}>{'Sign in'}</Text>
61	          </View>
62	        </TouchableOpacity>
63	      </View>
64	      <View style={Styles.login_social}>
65	        <View style={Styles.login_social_separator}>
66	          <View style={Styles.login_social_separator_line} />
67	          <Text style={Styles.login_social_separator_text}>{'or'}</Text>
68	          <View style={Styles.login_social_separator_line} />
69	        </View>
70	        <View style={Styles.login_social_buttons}>
71	          <TouchableOpacity>
72	            <View
73	              style={[
74	                Styles.login_social_button,
75	                Styles.login_social_facebook,
76	              ]}>
77	              <Image
78	                style={Styles.login_social_icon}
79	                source={require('./assets/icon-facebook.png')}
80	              />
81	            </View>
82	          </TouchableOpacity>
83	          <TouchableOpacity>
84	            <View style={Styles.login_social_button}>
85	              <Image
86	                style={Styles.login_social_icon}
87	                source={require('./assets/icon-google.png')}
88	              />
89	            </View>
90	          </TouchableOpacity>
91	          <TouchableOpacity>
92	            <View style={Styles.login_social_button}>
93	              <Image
94	                style={Styles.login_social_icon}
95	                source={require('./assets/icon-apple.png')}
96	              />
97	            </View>
98	          </TouchableOpacity>
99	        </View>
100	      </View>
101	    </View>
102	  );
103	};
```
:::

## 4 - 로그인 화면 만들기

이제 앱을 위한 새로운 화면을 만들어 보겠습니다. 이 화면은 당신의 <font color="#2166ae">`UserLogIn`</font> 컴포넌트를 사용할 것입니다. 새로운 화면을 당신의 <font color="#2166ae">`StackNavigator`</font>의 첫 번째(또는 상단) 화면으로 추가하세요:

:::CodeblockTabs
App.tsx/App.js

```typescript
1	// ...
2	
3	// Add this new screen function below the UserRegistrationScreen
4	function UserLogInScreen() {
5	  return (
6	    <>
7	      <StatusBar />
8	      <SafeAreaView style={Styles.login_container}>
9	        <View style={Styles.login_header}>
10	          <Image
11	            style={Styles.login_header_logo}
12	            source={require('./assets/logo-back4app.png')}
13	          />
14	          <Text style={Styles.login_header_text}>
15	            <Text style={Styles.login_header_text_bold}>
16	              {'React Native on Back4App - '}
17	            </Text>
18	            {' User login'}
19	          </Text>
20	        </View>
21	        <UserLogIn />
22	      </SafeAreaView>
23	    </>
24	  );
25	}
26	
27	// ...
28	
29	// Add the screen as the top one at your StackNavigator
30	const App = () => {
31	  return (
32	    <NavigationContainer>
33	      <Stack.Navigator>
34	        <Stack.Screen name="Login" component={UserLogInScreen} />
35	        <Stack.Screen name="Sign Up" component={UserRegistrationScreen} />
36	      </Stack.Navigator>
37	    </NavigationContainer>
38	  );
39	};
40	
41	// ...
```
:::

계속 진행하여 화면과 구성 요소를 테스트하세요. 이제 앱이 사용자 등록 화면 대신 사용자 로그인 화면을 표시하는 것을 알 수 있습니다. 이는 <font color="#2166ae">`StackNavigator`</font> 화면 목록에서의 위치 때문입니다. 로그인 후에는 다음과 같은 메시지를 보게 될 것입니다:

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/cXG_2oVHycVlL5VmR3BjT_image.png" size="50" width="355" height="730" position="center" showCaption="false"}

## 5 - 홈 화면 만들기 및 탐색 처리

로그인 후에는 일반적으로 사용자를 앱의 홈 화면으로 안내하고 싶을 것입니다. 앱의 주요 파일에서 이 화면을 만드세요:

:::CodeblockTabs
App.tsx/App.js

```typescript
1	// ...
2	
3	// Add this new screen function below the UserRegistrationScreen
4	function UserLogInScreen() {
5	  return (
6	    <>
7	      <StatusBar />
8	      <SafeAreaView style={Styles.login_container}>
9	        <View style={Styles.login_header}>
10	          <Image
11	            style={Styles.login_header_logo}
12	            source={require('./assets/logo-back4app.png')}
13	          />
14	          <Text style={Styles.login_header_text}>
15	            <Text style={Styles.login_header_text_bold}>
16	              {'React Native on Back4App - '}
17	            </Text>
18	            {' User login'}
19	          </Text>
20	        </View>
21	        <UserLogIn />
22	      </SafeAreaView>
23	    </>
24	  );
25	}
26	
27	// ...
28	
29	// Add the screen as the top one at your StackNavigator
30	const App = () => {
31	  return (
32	    <NavigationContainer>
33	      <Stack.Navigator>
34	        <Stack.Screen name="Login" component={UserLogInScreen} />
35	        <Stack.Screen name="Sign Up" component={UserRegistrationScreen} />
36	      </Stack.Navigator>
37	    </NavigationContainer>
38	  );
39	};
40	
41	// ...
```
:::

이제 사용자가 로그인한 후에 ‘react-navigation’을 사용하여 사용자를 탐색해야 합니다. 다음 코드를<font color="#2166ae">`UserLogIn`</font> 컴포넌트 안에 추가하세요:

:::CodeblockTabs
UserLogIn.js

```javascript
1	// ...
2	// Add this import
3	import {useNavigation} from '@react-navigation/native';
4	
5	export const UserLogIn = () => {
6	  // Add this to use useNavigation hook
7	  const navigation = useNavigation();
8	  
9	  //...
10	
11	  const doUserLogIn = async function () {
12	    const usernameValue = username;
13	    const passwordValue = password;
14	    return await Parse.User.logIn(usernameValue, passwordValue)
15	      .then(async (loggedInUser) => {
16	        Alert.alert(
17	          'Success!',
18	          `User ${loggedInUser.get('username')} has successfully signed in!`,
19	        );
20	        const currentUser = await Parse.User.currentAsync();
21	        console.log(loggedInUser === currentUser);
22	        // Add this to navigate your home screen; Navigation.navigate takes
23	        // the user to the screen named after the one passed as parameter
24	        navigation.navigate('Home');
25	        return true;
26	      })
27	      .catch((error) => {
28	        Alert.alert('Error!', error.message);
29	        return false;
30	      });
31	  };
32	// ...
```

UserLogIn.tsx

```typescript
1	// ...
2	// Add this import
3	import {useNavigation} from '@react-navigation/native';
4	
5	export const UserLogIn: FC<{}> = ({}): ReactElement => {
6	  // Add this to use useNavigation hook
7	  const navigation = useNavigation();
8	
9	  // ...
10	  
11	  const doUserLogIn = async function (): Promise<boolean> {
12	    const usernameValue: string = username;
13	    const passwordValue: string = password;
14	    return await Parse.User.logIn(usernameValue, passwordValue)
15	      .then(async (loggedInUser: Parse.User) => {
16	        Alert.alert(
17	          'Success!',
18	          `User ${loggedInUser.get('username')} has successfully signed in!`,
19	        );
20	        const currentUser: Parse.User = await Parse.User.currentAsync();
21	        console.log(loggedInUser === currentUser);
22	        // Add this to navigate your home screen; Navigation.navigate takes
23	        // the user to the screen named after the one passed as parameter
24	        navigation.navigate('Home');
25	        return true;
26	      })
27	      .catch((error: object) => {
28	        Alert.alert('Error!', error.message);
29	        return false;
30	      });
31	  };
32	
33	// ...
```
:::

로그인 후 새 <font color="#2166ae">`HomeScreen`</font>으로 리디렉션됩니다. 이 <font color="#2166ae">`HelloUser`</font> 컴포넌트를 추가하여 현재 사용자 이름을 표시할 수 있습니다:

:::CodeblockTabs
HelloUser.js

```javascript
1	import React, {FC, ReactElement, useEffect, useState} from 'react';
2	import {Text} from 'react-native';
3	import Parse from 'parse/react-native';
4	import Styles from './Styles';
5	
6	export const HelloUser = () => {
7	  // State variable that will hold username value
8	  const [username, setUsername] = useState('');
9	
10	  // useEffect is called after the component is initially rendered and
11	  // after every other render
12	  useEffect(() => {
13	    // Since the async method Parse.User.currentAsync is needed to
14	    // retrieve the current user data, you need to declare an async
15	    // function here and call it afterwards
16	    async function getCurrentUser() {
17	      // This condition ensures that username is updated only if needed
18	      if (username === '') {
19	        const currentUser = await Parse.User.currentAsync();
20	        if (currentUser !== null) {
21	          setUsername(currentUser.getUsername());
22	        }
23	      }
24	    }
25	    getCurrentUser();
26	  }, [username]);
27	
28	  // Note the condition operator here, so the "Hello" text is only
29	  // rendered if there is an username value
30	  return (
31	    <View style={Styles.login_wrapper}>
32	      <View style={Styles.form}>
33	        {username !== '' && <Text>{`Hello ${username}!`}</Text>}
34	      </View>
35	    </View>
36	  );
37	};
```

HelloUser.tsx

```typescript
1	import React, {FC, ReactElement, useEffect, useState} from 'react';
2	import {Text} from 'react-native';
3	import Parse from 'parse/react-native';
4	import Styles from './Styles';
5	
6	export const HelloUser: FC<{}> = ({}): ReactElement => {
7	  // State variable that will hold username value
8	  const [username, setUsername] = useState('');
9	
10	  // useEffect is called after the component is initially rendered and
11	  // after every other render
12	  useEffect(() => {
13	    // Since the async method Parse.User.currentAsync is needed to
14	    // retrieve the current user data, you need to declare an async
15	    // function here and call it afterwards
16	    async function getCurrentUser() {
17	      // This condition ensures that username is updated only if needed
18	      if (username === '') {
19	        const currentUser = await Parse.User.currentAsync();
20	        if (currentUser !== null) {
21	          setUsername(currentUser.getUsername());
22	        }
23	      }
24	    }
25	    getCurrentUser();
26	  }, [username]);
27	
28	  // Note the condition operator here, so the "Hello" text is only
29	  // rendered if there is an username value
30	  return (
31	    <View style={Styles.login_wrapper}>
32	      <View style={Styles.form}>
33	        {username !== '' && <Text>{`Hello ${username}!`}</Text>}
34	      </View>
35	    </View>
36	  );
37	};
```
:::

:::hint{type="info"}
**참고:** React의 <font color="#2166ae"> `useEffect`</font> 훅을 더 잘 살펴볼 수 있습니다 [여기](https://reactjs.org/docs/hooks-effect.html).
:::

이 컴포넌트를 HomeScreen 안에서 호출한 후, 당신의 앱은 다음과 같아야 합니다:

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/F1JR7J-5HVh7MjAAdPtgt_image.png" size="50" width="361" height="731" position="center" showCaption="false"}

## 6 - 로그아웃 컴포넌트 만들기

이 <font color="#2166ae">`UserLogOut`</font> 컴포넌트는 로그인보다 간단합니다. 왜냐하면 <font color="#2166ae">`Parse.User.logOut`</font> 메서드는 인수를 받지 않으며, <font color="#2166ae">`currentUser`</font> 데이터를 자동으로 로컬에 저장된 것을 지웁니다. 이 컴포넌트를 앱 루트 디렉토리에 만드세요:

:::CodeblockTabs
UserLogOut.js

```javascript
1	import React, {FC, ReactElement} from 'react';
2	import {Alert, Text, TouchableOpacity, View} from 'react-native';
3	import Parse from 'parse/react-native';
4	import {useNavigation} from '@react-navigation/native';
5	import {StackActions} from '@react-navigation/native';
6	import Styles from './Styles';
7	
8	export const UserLogOut = () => {
9	  const navigation = useNavigation();
10	
11	  const doUserLogOut = async function () {
12	    return await Parse.User.logOut()
13	      .then(async () => {
14	        // To verify that current user is now empty, currentAsync can be used
15	        const currentUser = await Parse.User.currentAsync();
16	        if (currentUser === null) {
17	          Alert.alert('Success!', 'No user is logged in anymore!');
18	        }
19	        // Navigation dispatch calls a navigation action, and popToTop will take
20	        // the user back to the very first screen of the stack
21	        navigation.dispatch(StackActions.popToTop());
22	        return true;
23	      })
24	      .catch((error) => {
25	        Alert.alert('Error!', error.message);
26	        return false;
27	      });
28	  };
29	
30	  return (
31	    <View style={Styles.login_wrapper}>
32	      <View style={Styles.form}>
33	        <TouchableOpacity onPress={() => doUserLogOut()}>
34	          <View style={Styles.button}>
35	            <Text style={Styles.button_label}>{'Logout'}</Text>
36	          </View>
37	        </TouchableOpacity>
38	      </View>
39	    </View>
40	  );
41	};
```

UserLogOut.tsx

```typescript
1	import React, {FC, ReactElement} from 'react';
2	import {Alert, Text, TouchableOpacity, View} from 'react-native';
3	import Parse from 'parse/react-native';
4	import {useNavigation} from '@react-navigation/native';
5	import {StackActions} from '@react-navigation/native';
6	import Styles from './Styles';
7	
8	export const UserLogOut: FC<{}> = ({}): ReactElement => {
9	  const navigation = useNavigation();
10	
11	  const doUserLogOut = async function (): Promise<boolean> {
12	    return await Parse.User.logOut()
13	      .then(async () => {
14	        // To verify that current user is now empty, currentAsync can be used
15	        const currentUser: Parse.User = await Parse.User.currentAsync();
16	        if (currentUser === null) {
17	          Alert.alert('Success!', 'No user is logged in anymore!');
18	        }
19	        // Navigation dispatch calls a navigation action, and popToTop will take
20	        // the user back to the very first screen of the stack
21	        navigation.dispatch(StackActions.popToTop());
22	        return true;
23	      })
24	      .catch((error: object) => {
25	        Alert.alert('Error!', error.message);
26	        return false;
27	      });
28	  };
29	
30	  return (
31	    <View style={Styles.login_wrapper}>
32	      <View style={Styles.form}>
33	        <TouchableOpacity onPress={() => doUserLogOut()}>
34	          <View style={Styles.button}>
35	            <Text style={Styles.button_label}>{'Logout'}</Text>
36	          </View>
37	        </TouchableOpacity>
38	      </View>
39	    </View>
40	  );
41	};
```
:::

이 새로운 컴포넌트를 <font color="#2166ae">`HomeScreen`</font>에 추가하여 로그인 후 테스트할 수 있습니다. 이제 앱의 홈 화면은 다음과 같이 보일 것입니다:

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/onWiS-UCALVmfhSazjE7L_image.png" size="50" width="351" height="728" position="center" showCaption="false"}

성공적으로 로그아웃을 수행하면, 다음과 같은 메시지를 보게 되며 <font color="#2166ae">`UserLogIn`</font> 화면으로 리디렉션됩니다. 이 화면은 내비게이션 스택의 첫 번째 화면입니다:

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/4ncdQ-pdCOArfxivJ-IZF_image.png" size="50" width="374" height="736" position="center" showCaption="false"}

당신의 <font color="#2166ae">`UserRegistration`</font>을 <font color="#2166ae">`UserLogIn`</font> 화면 내의 등록 버튼에 연결하고, <font color="#2166ae">`HomeScreen`</font>으로 리디렉션 패턴을 반복하세요. <font color="#2166ae">`react-navigation`</font>의 문서를 읽어 여러 사용자 정의 옵션을 발견하고 앱 내비게이션의 모든 측면을 제어하는 것을 잊지 마세요.

:::CodeblockTabs
UserLogIn.js

```javascript
1	// ...
2	
3	export const UserLogIn = () => {
4	  const navigation = useNavigation();
5	
6	  const [username, setUsername] = useState('');
7	  const [password, setPassword] = useState('');
8	
9	  const doUserLogIn = async function () {
10	    // Note that these values come from state variables that we've declared before
11	    const usernameValue = username;
12	    const passwordValue = password;
13	    return await Parse.User.logIn(usernameValue, passwordValue)
14	      .then(async (loggedInUser) => {
15	        // logIn returns the corresponding ParseUser object
16	        Alert.alert(
17	          'Success!',
18	          `User ${loggedInUser.get('username')} has successfully signed in!`,
19	        );
20	        // To verify that this is in fact the current user, currentAsync can be used
21	        const currentUser: Parse.User = await Parse.User.currentAsync();
22	        console.log(loggedInUser === currentUser);
23	        // Navigation.navigate takes the user to the screen named after the one
24	        // passed as parameter
25	        navigation.navigate('Home');
26	        return true;
27	      })
28	      .catch((error) => {
29	        // Error can be caused by wrong parameters or lack of Internet connection
30	        Alert.alert('Error!', error.message);
31	        return false;
32	      });
33	  };
34	
35	  return (
36	    <View style={Styles.login_wrapper}>
37	      <View style={Styles.form}>
38	        <TextInput
39	          style={Styles.form_input}
40	          value={username}
41	          placeholder={'Username'}
42	          onChangeText={(text) => setUsername(text)}
43	          autoCapitalize={'none'}
44	          keyboardType={'email-address'}
45	        />
46	        <TextInput
47	          style={Styles.form_input}
48	          value={password}
49	          placeholder={'Password'}
50	          secureTextEntry
51	          onChangeText={(text) => setPassword(text)}
52	        />
53	        <TouchableOpacity onPress={() => doUserLogIn()}>
54	          <View style={Styles.button}>
55	            <Text style={Styles.button_label}>{'Sign in'}</Text>
56	          </View>
57	        </TouchableOpacity>
58	      </View>
59	      <View style={Styles.login_social}>
60	        <View style={Styles.login_social_separator}>
61	          <View style={Styles.login_social_separator_line} />
62	          <Text style={Styles.login_social_separator_text}>{'or'}</Text>
63	          <View style={Styles.login_social_separator_line} />
64	        </View>
65	        <View style={Styles.login_social_buttons}>
66	          <TouchableOpacity>
67	            <View
68	              style={[
69	                Styles.login_social_button,
70	                Styles.login_social_facebook,
71	              ]}>
72	              <Image
73	                style={Styles.login_social_icon}
74	                source={require('./assets/icon-facebook.png')}
75	              />
76	            </View>
77	          </TouchableOpacity>
78	          <TouchableOpacity>
79	            <View style={Styles.login_social_button}>
80	              <Image
81	                style={Styles.login_social_icon}
82	                source={require('./assets/icon-google.png')}
83	              />
84	            </View>
85	          </TouchableOpacity>
86	          <TouchableOpacity>
87	            <View style={Styles.login_social_button}>
88	              <Image
89	                style={Styles.login_social_icon}
90	                source={require('./assets/icon-apple.png')}
91	              />
92	            </View>
93	          </TouchableOpacity>
94	        </View>
95	      </View>
96	      <>
97	        <TouchableOpacity onPress={() => navigation.navigate('Sign Up')}>
98	          <Text style={Styles.login_footer_text}>
99	            {"Don't have an account? "}
100	            <Text style={Styles.login_footer_link}>{'Sign up'}</Text>
101	          </Text>
102	        </TouchableOpacity>
103	      </>
104	    </View>
105	  );
106	};
107	
108	// ...
```

UserLogIn.tsx

```typescript
1	// ...
2	
3	export const UserLogIn: FC<{}> = ({}): ReactElement => {
4	  const navigation = useNavigation();
5	
6	  const [username, setUsername] = useState('');
7	  const [password, setPassword] = useState('');
8	
9	  const doUserLogIn = async function (): Promise<boolean> {
10	    // Note that these values come from state variables that we've declared before
11	    const usernameValue: string = username;
12	    const passwordValue: string = password;
13	    return await Parse.User.logIn(usernameValue, passwordValue)
14	      .then(async (loggedInUser: Parse.User) => {
15	        // logIn returns the corresponding ParseUser object
16	        Alert.alert(
17	          'Success!',
18	          `User ${loggedInUser.get('username')} has successfully signed in!`,
19	        );
20	        // To verify that this is in fact the current user, currentAsync can be used
21	        const currentUser: Parse.User = await Parse.User.currentAsync();
22	        console.log(loggedInUser === currentUser);
23	        // Navigation.navigate takes the user to the screen named after the one
24	        // passed as parameter
25	        navigation.navigate('Home');
26	        return true;
27	      })
28	      .catch((error: object) => {
29	        // Error can be caused by wrong parameters or lack of Internet connection
30	        Alert.alert('Error!', error.message);
31	        return false;
32	      });
33	  };
34	
35	  return (
36	    <View style={Styles.login_wrapper}>
37	      <View style={Styles.form}>
38	        <TextInput
39	          style={Styles.form_input}
40	          value={username}
41	          placeholder={'Username'}
42	          onChangeText={(text) => setUsername(text)}
43	          autoCapitalize={'none'}
44	          keyboardType={'email-address'}
45	        />
46	        <TextInput
47	          style={Styles.form_input}
48	          value={password}
49	          placeholder={'Password'}
50	          secureTextEntry
51	          onChangeText={(text) => setPassword(text)}
52	        />
53	        <TouchableOpacity onPress={() => doUserLogIn()}>
54	          <View style={Styles.button}>
55	            <Text style={Styles.button_label}>{'Sign in'}</Text>
56	          </View>
57	        </TouchableOpacity>
58	      </View>
59	      <View style={Styles.login_social}>
60	        <View style={Styles.login_social_separator}>
61	          <View style={Styles.login_social_separator_line} />
62	          <Text style={Styles.login_social_separator_text}>{'or'}</Text>
63	          <View style={Styles.login_social_separator_line} />
64	        </View>
65	        <View style={Styles.login_social_buttons}>
66	          <TouchableOpacity>
67	            <View
68	              style={[
69	                Styles.login_social_button,
70	                Styles.login_social_facebook,
71	              ]}>
72	              <Image
73	                style={Styles.login_social_icon}
74	                source={require('./assets/icon-facebook.png')}
75	              />
76	            </View>
77	          </TouchableOpacity>
78	          <TouchableOpacity>
79	            <View style={Styles.login_social_button}>
80	              <Image
81	                style={Styles.login_social_icon}
82	                source={require('./assets/icon-google.png')}
83	              />
84	            </View>
85	          </TouchableOpacity>
86	          <TouchableOpacity>
87	            <View style={Styles.login_social_button}>
88	              <Image
89	                style={Styles.login_social_icon}
90	                source={require('./assets/icon-apple.png')}
91	              />
92	            </View>
93	          </TouchableOpacity>
94	        </View>
95	      </View>
96	      <>
97	        <TouchableOpacity onPress={() => navigation.navigate('Sign Up')}>
98	          <Text style={Styles.login_footer_text}>
99	            {"Don't have an account? "}
100	            <Text style={Styles.login_footer_link}>{'Sign up'}</Text>
101	          </Text>
102	        </TouchableOpacity>
103	      </>
104	    </View>
105	  );
106	};
107	
108	// ...
```
:::

:::CodeblockTabs
UserRegistration.js

```javascript
1	export const UserRegistration = () => {
2	  const navigation = useNavigation();
3	
4	  const [username, setUsername] = useState('');
5	  const [password, setPassword] = useState('');
6	
7	  const doUserSignUp = async function () {
8	    // Note that these values come from state variables that we've declared before
9	    const usernameValue = username;
10	    const passwordValue = password;
11	    // Since the signUp method returns a Promise, we need to call it using await
12	    return await Parse.User.signUp(usernameValue, passwordValue)
13	      .then((createdUser) => {
14	        // Parse.User.signUp returns the already created ParseUser object if successful
15	        Alert.alert(
16	          'Success!',
17	          `User ${createdUser.get('username')} was successfully created!`,
18	        );
19	        // Navigation.navigate takes the user to the screen named after the one
20	        // passed as parameter
21	        navigation.navigate('Home');
22	        return true;
23	      })
24	      .catch((error) => {
25	        // signUp can fail if any parameter is blank or failed an uniqueness check on the server
26	        Alert.alert('Error!', error.message);
27	        return false;
28	      });
29	  };
30	
31	  return (
32	    <View style={Styles.login_wrapper}>
33	      <View style={Styles.form}>
34	        <TextInput
35	          style={Styles.form_input}
36	          value={username}
37	          placeholder={'Username'}
38	          onChangeText={(text) => setUsername(text)}
39	          autoCapitalize={'none'}
40	          keyboardType={'email-address'}
41	        />
42	        <TextInput
43	          style={Styles.form_input}
44	          value={password}
45	          placeholder={'Password'}
46	          secureTextEntry
47	          onChangeText={(text) => setPassword(text)}
48	        />
49	        <TouchableOpacity onPress={() => doUserSignUp()}>
50	          <View style={Styles.button}>
51	            <Text style={Styles.button_label}>{'Sign Up'}</Text>
52	          </View>
53	        </TouchableOpacity>
54	      </View>
55	      <View style={Styles.login_social}>
56	        <View style={Styles.login_social_separator}>
57	          <View style={Styles.login_social_separator_line} />
58	          <Text style={Styles.login_social_separator_text}>{'or'}</Text>
59	          <View style={Styles.login_social_separator_line} />
60	        </View>
61	        <View style={Styles.login_social_buttons}>
62	          <TouchableOpacity>
63	            <View
64	              style={[
65	                Styles.login_social_button,
66	                Styles.login_social_facebook,
67	              ]}>
68	              <Image
69	                style={Styles.login_social_icon}
70	                source={require('./assets/icon-facebook.png')}
71	              />
72	            </View>
73	          </TouchableOpacity>
74	          <TouchableOpacity>
75	            <View style={Styles.login_social_button}>
76	              <Image
77	                style={Styles.login_social_icon}
78	                source={require('./assets/icon-google.png')}
79	              />
80	            </View>
81	          </TouchableOpacity>
82	          <TouchableOpacity>
83	            <View style={Styles.login_social_button}>
84	              <Image
85	                style={Styles.login_social_icon}
86	                source={require('./assets/icon-apple.png')}
87	              />
88	            </View>
89	          </TouchableOpacity>
90	        </View>
91	      </View>
92	      <>
93	        <TouchableOpacity onPress={() => navigation.navigate('Login')}>
94	          <Text style={Styles.login_footer_text}>
95	            {'Already have an account? '}
96	            <Text style={Styles.login_footer_link}>{'Log In'}</Text>
97	          </Text>
98	        </TouchableOpacity>
99	      </>
100	    </View>
101	  );
102	};
103	
104	// ...
```

UserRegistration.tsx

```typescript
1	// ...
2	
3	export const UserRegistration: FC<{}> = ({}): ReactElement => {
4	  const navigation = useNavigation();
5	
6	  const [username, setUsername] = useState('');
7	  const [password, setPassword] = useState('');
8	
9	  const doUserSignUp = async function (): Promise<boolean> {
10	    // Note that these values come from state variables that we've declared before
11	    const usernameValue: string = username;
12	    const passwordValue: string = password;
13	    // Since the signUp method returns a Promise, we need to call it using await
14	    return await Parse.User.signUp(usernameValue, passwordValue)
15	      .then((createdUser: Parse.User) => {
16	        // Parse.User.signUp returns the already created ParseUser object if successful
17	        Alert.alert(
18	          'Success!',
19	          `User ${createdUser.get('username')} was successfully created!`,
20	        );
21	        // Navigation.navigate takes the user to the screen named after the one
22	        // passed as parameter
23	        navigation.navigate('Home');
24	        return true;
25	      })
26	      .catch((error: object) => {
27	        // signUp can fail if any parameter is blank or failed an uniqueness check on the server
28	        Alert.alert('Error!', error.message);
29	        return false;
30	      });
31	  };
32	
33	  return (
34	    <View style={Styles.login_wrapper}>
35	      <View style={Styles.form}>
36	        <TextInput
37	          style={Styles.form_input}
38	          value={username}
39	          placeholder={'Username'}
40	          onChangeText={(text) => setUsername(text)}
41	          autoCapitalize={'none'}
42	          keyboardType={'email-address'}
43	        />
44	        <TextInput
45	          style={Styles.form_input}
46	          value={password}
47	          placeholder={'Password'}
48	          secureTextEntry
49	          onChangeText={(text) => setPassword(text)}
50	        />
51	        <TouchableOpacity onPress={() => doUserSignUp()}>
52	          <View style={Styles.button}>
53	            <Text style={Styles.button_label}>{'Sign Up'}</Text>
54	          </View>
55	        </TouchableOpacity>
56	      </View>
57	      <View style={Styles.login_social}>
58	        <View style={Styles.login_social_separator}>
59	          <View style={Styles.login_social_separator_line} />
60	          <Text style={Styles.login_social_separator_text}>{'or'}</Text>
61	          <View style={Styles.login_social_separator_line} />
62	        </View>
63	        <View style={Styles.login_social_buttons}>
64	          <TouchableOpacity>
65	            <View
66	              style={[
67	                Styles.login_social_button,
68	                Styles.login_social_facebook,
69	              ]}>
70	              <Image
71	                style={Styles.login_social_icon}
72	                source={require('./assets/icon-facebook.png')}
73	              />
74	            </View>
75	          </TouchableOpacity>
76	          <TouchableOpacity>
77	            <View style={Styles.login_social_button}>
78	              <Image
79	                style={Styles.login_social_icon}
80	                source={require('./assets/icon-google.png')}
81	              />
82	            </View>
83	          </TouchableOpacity>
84	          <TouchableOpacity>
85	            <View style={Styles.login_social_button}>
86	              <Image
87	                style={Styles.login_social_icon}
88	                source={require('./assets/icon-apple.png')}
89	              />
90	            </View>
91	          </TouchableOpacity>
92	        </View>
93	      </View>
94	      <>
95	        <TouchableOpacity onPress={() => navigation.navigate('Login')}>
96	          <Text style={Styles.login_footer_text}>
97	            {'Already have an account? '}
98	            <Text style={Styles.login_footer_link}>{'Log In'}</Text>
99	          </Text>
100	        </TouchableOpacity>
101	      </>
102	    </View>
103	  );
104	};
105	
106	// ...
```
:::

이제 로그인 및 등록 화면은 다음과 같아야 합니다:

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/EGxclVQlaT1CgqtgpSYoH_image.png" size="50" width="362" height="732" position="center" showCaption="false"}

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/E_IJmJBmL96wTGsmwh5aa_image.png" size="50" width="364" height="730" position="center" showCaption="false"}

## 결론

이 가이드의 끝에서, 당신은 React Native에서 Parse 사용자를 로그인하고 로그아웃하는 방법과 <font color="#2166ae">`react-navigation`</font>을 사용하여 애플리케이션을 통해 사용자를 탐색하는 방법을 배웠습니다. 다음 가이드에서는 유용한 사용자 쿼리를 수행하는 방법을 보여드릴 것입니다.
