---
title: React Native에서 Parse와 Apple 로그인 구현하기
slug: docs-kr/react-native/parse-sdk/working-with-users/react-native-sign-in-with-apple
description: Apple 로그인 사용하는 Parse 사용자 인증을 React Native로 구축하는 방법.
image: https://www.back4app.com/images/logo-social.png
createdAt: 2024-03-19T16:17:31.267Z
---

# React Native용 Apple로 로그인하기

## 소개

지난 튜토리얼에서는 <font color="#2166ae">`Parse.User`</font> 클래스를 사용하여 앱에 사용자 로그인/로그아웃 기능을 추가했습니다. 이제 Apple Sign-in을 사용하여 Apple에서 사용자 데이터를 검색하고 로그인, 가입 또는 기존 사용자와 연결하는 방법을 배울 것입니다. 또한 이를 달성하기 위해 <font color="#2166ae">`react-native-apple-authentication`</font> 라이브러리를 설치하고 구성할 것입니다.

&#x20;<font color="#2166ae">`Parse.User.linkWith`</font> 메서드는 각기 다른 제공자가 요청하는 올바른 매개변수만 전달하면 모든 서드파티 인증 방법을 사용하여 사용자를 가입시키고 로그인하는 역할을 합니다. 사용자 데이터를 새 또는 기존 <font color="#2166ae">`Parse.User`</font>에 연결한 후, Parse는 장치에 유효한 사용자 세션을 저장합니다. 이후 <font color="#2166ae">`currentAsync`</font>와 같은 메서드를 호출하면 일반 로그인과 마찬가지로 사용자 데이터를 성공적으로 검색할 수 있습니다.

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

- [Kotlin 예제 리포지토리](https://github.com/templates-back4app/Android-Parse-Sdk-Kotlin)
- [Java 예제 리포지토리](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를 사용하여 Apple Sign-in을 통한 사용자 로그인 기능을 구축합니다.

## 1 - 의존성 설치

React Native에서 Apple Sign-in을 활성화하는 가장 인기 있는 방법은 <font color="#2166ae">`react-native-apple-authentication`</font> 라이브러리를 사용하는 것입니다. 이 라이브러리의 구성은 개발 환경, 대상 플랫폼 및 선호도에 따라 다르므로, [공식 문서](https://github.com/invertase/react-native-apple-authentication)를 따라 설정하세요.

Android용으로 개발하는 경우, Apple JWT 토큰을 디코딩하기 위해 [<font color="#2166ae">`jwt-decode`</font>](https://github.com/auth0/jwt-decode) 라이브러리를 설치해야 합니다.

:::hint{type="info"}
**참고:** Xcode 환경의 초기 설정, 앱 ID, 키 및 Apple Developer 포털에서 서비스 ID를 만드는 지침을 철저히 따르세요.
:::

## 2 - Parse와 함께 Apple Sign-in 사용하기

이제 Apple Sign-in 인증 모달을 호출하는 <font color="#2166ae">`UserLogIn`</font> 컴포넌트 내에 새로운 메서드를 생성해 보겠습니다. <font color="#2166ae">`react-native-apple-authentication`</font> 라이브러리는 사용자 플랫폼에 따라 이 호출을 처리하기 위해 두 개의 별도 모듈을 가지고 있으므로, <font color="#2166ae">`appleAuth.performRequest`</font>를 iOS에서 사용하고, <font color="#2166ae">`appleAuthAndroid.signIn`</font>을 Android에서 사용해야 합니다. 사용자가 Apple로 로그인하면, 이 호출은 Apple로부터 사용자 데이터를 검색하고, <font color="#2166ae">`id`</font>, <font color="#2166ae">`token`</font>, 그리고 나중에 사용할 Apple 이메일을 저장해야 합니다.

:::CodeblockTabs
JavaScript

```javascript
1	const doUserLogInApple = async function (): Promise<boolean> {
2	  try {
3	    let response = {};
4	    let appleId = '';
5	    let appleToken = '';
6	    let appleEmail = '';
7	    if (Platform.OS === 'ios') {
8	      // Performs login request requesting user email
9	      response = await appleAuth.performRequest({
10	        requestedOperation: appleAuth.Operation.LOGIN,
11	        requestedScopes: [appleAuth.Scope.EMAIL],
12	      });
13	      // On iOS, user ID and email are easily retrieved from request
14	      appleId = response.user;
15	      appleToken = response.identityToken;
16	      appleEmail = response.email;
17	    } else if (Platform.OS === 'android') {
18	      // Configure the request
19	      appleAuthAndroid.configure({
20	        // The Service ID you registered with Apple
21	        clientId: 'YOUR_SERVICE_ID',
22	        // Return URL added to your Apple dev console
23	        redirectUri: 'YOUR_REDIRECT_URL',
24	        responseType: appleAuthAndroid.ResponseType.ALL,
25	        scope: appleAuthAndroid.Scope.ALL,
26	      });
27	      response = await appleAuthAndroid.signIn();
28	      // Decode user ID and email from token returned from Apple,
29	      // this is a common workaround for Apple sign-in via web API
30	      const decodedIdToken = jwt_decode(response.id_token);
31	      appleId = decodedIdToken.sub;
32	      appleToken = response.id_token;
33	      appleEmail = decodedIdToken.email;
34	    }
35	    // Format authData to provide correctly for Apple linkWith on Parse
36	    const authData = {
37	      id: appleId,
38	      token: appleToken,
39	    };
40	  } catch (error) {
41	    // Error can be caused by wrong parameters or lack of Internet connection
42	    Alert.alert('Error!', error);
43	    return false;
44	  }
45	};
```

```typescript
1	const doUserLogInApple = async function (): Promise<boolean> {
2	  try {
3	    let response: object = {};
4	    let appleId: string = '';
5	    let appleToken: string = '';
6	    let appleEmail: string = '';
7	    if (Platform.OS === 'ios') {
8	      // Performs login request requesting user email
9	      response = await appleAuth.performRequest({
10	        requestedOperation: appleAuth.Operation.LOGIN,
11	        requestedScopes: [appleAuth.Scope.EMAIL],
12	      });
13	      // On iOS, user ID and email are easily retrieved from request
14	      appleId = response.user;
15	      appleToken = response.identityToken;
16	      appleEmail = response.email;
17	    } else if (Platform.OS === 'android') {
18	      // Configure the request
19	      appleAuthAndroid.configure({
20	        // The Service ID you registered with Apple
21	        clientId: 'YOUR_SERVICE_ID',
22	        // Return URL added to your Apple dev console
23	        redirectUri: 'YOUR_SERVICE_URL',
24	        responseType: appleAuthAndroid.ResponseType.ALL,
25	        scope: appleAuthAndroid.Scope.ALL,
26	      });
27	      response = await appleAuthAndroid.signIn();
28	      // Decode user ID and email from token returned from Apple,
29	      // this is a common workaround for Apple sign-in via web API
30	      const decodedIdToken: object = jwt_decode(response.id_token);
31	      appleId = decodedIdToken.sub;
32	      appleToken = response.id_token;
33	      appleEmail = decodedIdToken.email;
34	    }
35	    // Format authData to provide correctly for Apple linkWith on Parse
36	    const authData: object = {
37	      id: appleId,
38	      token: appleToken,
39	    };
40	  } catch (error: any) {
41	    // Error can be caused by wrong parameters or lack of Internet connection
42	    Alert.alert('Error!', error);
43	    return false;
44	  }
45	};
```
:::

Android의 경우 Apple에서 반환된 토큰을 디코딩해야 한다는 점에 유의하세요. 왜냐하면 라이브러리 <font color="#2166ae">`react-native-apple-authentication`</font>은 인증을 위해 Apple Sign-in 웹 API를 사용하기 때문입니다. 이 방법을 사용할 때 데이터 접근에 대한 제한이 있으므로, 사용자 ID와 이메일을 가져오는 일반적인 우회 방법은 이 디코딩 과정을 통해 이루어집니다. 이는 공식 Parse 가이드에서 [여기](https://docs.parseplatform.org/parse-server/guide/#apple-authdata)에 명시되어 있습니다.

그 후, 새로운 <font color="#2166ae">`Parse.User.linkWith`</font>를 사용하여 새로운 사용자 등록 및 로그인을 할 수 있습니다. 사용자가 이미 이 Apple 인증을 사용하여 가입한 경우, <font color="#2166ae">`linkWith`</font>는 기존 계정을 사용하여 그를 로그인 시킵니다.

:::CodeblockTabs
JavaScript

```javascript
1	const doUserLogInApple = async function (): Promise<boolean> {
2	  try {
3	    let response = {};
4	    let appleId = '';
5	    let appleToken = '';
6	    let appleEmail = '';
7	    if (Platform.OS === 'ios') {
8	      // Performs login request requesting user email
9	      response = await appleAuth.performRequest({
10	        requestedOperation: appleAuth.Operation.LOGIN,
11	        requestedScopes: [appleAuth.Scope.EMAIL],
12	      });
13	      // On iOS, user ID and email are easily retrieved from request
14	      appleId = response.user;
15	      appleToken = response.identityToken;
16	      appleEmail = response.email;
17	    } else if (Platform.OS === 'android') {
18	      // Configure the request
19	      appleAuthAndroid.configure({
20	        // The Service ID you registered with Apple
21	        clientId: 'YOUR_SERVICE_IO',
22	        // Return URL added to your Apple dev console
23	        redirectUri: 'YOUR_SERVICE_URL',
24	        responseType: appleAuthAndroid.ResponseType.ALL,
25	        scope: appleAuthAndroid.Scope.ALL,
26	      });
27	      response = await appleAuthAndroid.signIn();
28	      // Decode user ID and email from token returned from Apple,
29	      // this is a common workaround for Apple sign-in via web API
30	      const decodedIdToken = jwt_decode(response.id_token);
31	      appleId = decodedIdToken.sub;
32	      appleToken = response.id_token;
33	      appleEmail = decodedIdToken.email;
34	    }
35	    // Format authData to provide correctly for Apple linkWith on Parse
36	    const authData = {
37	      id: appleId,
38	      token: appleToken,
39	    };
40	    // Log in or sign up on Parse using this Apple credentials
41	    let userToLogin = new Parse.User();
42	    // Set username and email to match provider email
43	    userToLogin.set('username', appleEmail);
44	    userToLogin.set('email', appleEmail);
45	    return await userToLogin
46	      .linkWith('apple', {
47	        authData: authData,
48	      })
49	      .then(async (loggedInUser) => {
50	        // logIn returns the corresponding ParseUser object
51	        Alert.alert(
52	          'Success!',
53	          `User ${loggedInUser.get('username')} has successfully signed in!`,
54	        );
55	        // To verify that this is in fact the current user, currentAsync can be used
56	        const currentUser = await Parse.User.currentAsync();
57	        console.log(loggedInUser === currentUser);
58	        // Navigation.navigate takes the user to the screen named after the one
59	        // passed as parameter
60	        navigation.navigate('Home');
61	        return true;
62	      })
63	      .catch(async (error) => {
64	        // Error can be caused by wrong parameters or lack of Internet connection
65	        Alert.alert('Error!', error.message);
66	        return false;
67	      });
68	  } catch (error) {
69	    // Error can be caused by wrong parameters or lack of Internet connection
70	    Alert.alert('Error!', error);
71	    return false;
72	  }
73	};
```

```typescript
1	const doUserLogInApple = async function (): Promise<boolean> {
2	  try {
3	    let response: object = {};
4	    let appleId: string = '';
5	    let appleToken: string = '';
6	    let appleEmail: string = '';
7	    if (Platform.OS === 'ios') {
8	      // Performs login request requesting user email
9	      response = await appleAuth.performRequest({
10	        requestedOperation: appleAuth.Operation.LOGIN,
11	        requestedScopes: [appleAuth.Scope.EMAIL],
12	      });
13	      // On iOS, user ID and email are easily retrieved from request
14	      appleId = response.user;
15	      appleToken = response.identityToken;
16	      appleEmail = response.email;
17	    } else if (Platform.OS === 'android') {
18	      // Configure the request
19	      appleAuthAndroid.configure({
20	        // The Service ID you registered with Apple
21	        clientId: 'com.back4app.userguide',
22	        // Return URL added to your Apple dev console
23	        redirectUri: 'https://tuhl.software/back4appuserguide/',
24	        responseType: appleAuthAndroid.ResponseType.ALL,
25	        scope: appleAuthAndroid.Scope.ALL,
26	      });
27	      response = await appleAuthAndroid.signIn();
28	      // Decode user ID and email from token returned from Apple,
29	      // this is a common workaround for Apple sign-in via web API
30	      const decodedIdToken: object = jwt_decode(response.id_token);
31	      appleId = decodedIdToken.sub;
32	      appleToken = response.id_token;
33	      appleEmail = decodedIdToken.email;
34	    }
35	    // Format authData to provide correctly for Apple linkWith on Parse
36	    const authData: object = {
37	      id: appleId,
38	      token: appleToken,
39	    };
40	    // Log in or sign up on Parse using this Apple credentials
41	    let userToLogin: Parse.User = new Parse.User();
42	    // Set username and email to match provider email
43	    userToLogin.set('username', appleEmail);
44	    userToLogin.set('email', appleEmail);
45	    return await userToLogin
46	      .linkWith('apple', {
47	        authData: authData,
48	      })
49	      .then(async (loggedInUser: Parse.User) => {
50	        // logIn returns the corresponding ParseUser object
51	        Alert.alert(
52	          'Success!',
53	          `User ${loggedInUser.get('username')} has successfully signed in!`,
54	        );
55	        // To verify that this is in fact the current user, currentAsync can be used
56	        const currentUser: Parse.User = await Parse.User.currentAsync();
57	        console.log(loggedInUser === currentUser);
58	        // Navigation.navigate takes the user to the screen named after the one
59	        // passed as parameter
60	        navigation.navigate('Home');
61	        return true;
62	      })
63	      .catch(async (error: object) => {
64	        // Error can be caused by wrong parameters or lack of Internet connection
65	        Alert.alert('Error!', error.message);
66	        return false;
67	      });
68	  } catch (error: any) {
69	    // Error can be caused by wrong parameters or lack of Internet connection
70	    Alert.alert('Error!', error);
71	    return false;
72	  }
73	};
```
:::

이 기능을 <font color="#2166ae">`UserSignIn`</font> 컴포넌트에 추가하고 Apple 버튼의 <font color="#2166ae">`onPress`</font> 매개변수에 할당하세요. 새 기능을 테스트해 보세요. 사용자가 성공적으로 등록하고/또는 로그인한 후에는 홈 화면으로 리디렉션된다는 점에 유의하세요.

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

## 3 - 사용자 로그인 및 세션 생성 확인

Apple 로그인이 제대로 작동했는지 확인하려면, Parse 대시보드를 확인하고 새로운 <font color="#2166ae">`사용자`</font> (Apple 인증 데이터가 다른 사용자에 속하지 않는 경우)와 함께 Apple <font color="#2166ae">`authData`</font> 매개변수를 포함하고 있는지 확인할 수 있습니다.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/2kFrsjiGKtI8OR236o9Fh_image.png)

대시보드에서 유효한 세션이 생성되었는지 확인할 수도 있으며, 해당 <font color="#2166ae">`사용자`</font> 객체에 대한 포인터를 포함하고 있습니다.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/7cDKv-fc1S1IWbhlH3s0u_image.png)

## 4 - 기존 사용자를 Apple 로그인에 연결하기

또 다른 <font color="#2166ae">`linkWith`</font> 가능한 사용법은 기존 사용자를 다른 인증 제공자, 이 경우에는 Apple과 연결하는 것입니다. <font color="#2166ae">`linkWith`</font>를 호출하는 이 기능을 추가하세요. <font color="#2166ae">`UserLogIn`</font>에서 했던 것과 같은 방식으로 당신의 <font color="#2166ae">`HelloUser`</font> 컴포넌트나 직접 홈 화면에 추가하세요. 여기서 유일한 차이점은 빈 <font color="#2166ae">`Parse.User`</font>에서 메서드를 호출하는 대신, 로그인한 사용자 객체에서 사용할 것이라는 점입니다.

:::CodeblockTabs
JavaScript

```javascript
1	const doUserLinkApple = async function (){
2	  try {
3	    let response = {};
4	    let appleId = '';
5	    let appleToken = '';
6	    if (Platform.OS === 'ios') {
7	      // Performs login request requesting user email
8	      response = await appleAuth.performRequest({
9	        requestedOperation: appleAuth.Operation.LOGIN,
10	        requestedScopes: [appleAuth.Scope.EMAIL],
11	      });
12	      // On iOS, user ID and email are easily retrieved from request
13	      appleId = response.user;
14	      appleToken = response.identityToken;
15	    } else if (Platform.OS === 'android') {
16	      // Configure the request
17	      appleAuthAndroid.configure({
18	        // The Service ID you registered with Apple
19	        clientId: 'YOUR_SERVICE_ID',
20	        // Return URL added to your Apple dev console
21	        redirectUri: 'YOUR_REDIRECT_URL',
22	        responseType: appleAuthAndroid.ResponseType.ALL,
23	        scope: appleAuthAndroid.Scope.ALL,
24	      });
25	      response = await appleAuthAndroid.signIn();
26	      // Decode user ID and email from token returned from Apple,
27	      // this is a common workaround for Apple sign-in via web API
28	      const decodedIdToken = jwt_decode(response.id_token);
29	      appleId = decodedIdToken.sub;
30	      appleToken = response.id_token;
31	    }
32	    // Format authData to provide correctly for Apple linkWith on Parse
33	    const authData = {
34	      id: appleId,
35	      token: appleToken,
36	    };
37	    let currentUser = await Parse.User.currentAsync();
38	    // Link user with his Apple Credentials
39	    return await currentUser
40	      .linkWith('apple', {
41	        authData: authData,
42	      })
43	      .then(async (loggedInUser) => {
44	        // logIn returns the corresponding ParseUser object
45	        Alert.alert(
46	          'Success!',
47	          `User ${loggedInUser.get(
48	            'username',
49	          )} has successfully linked his Apple account!`,
50	        );
51	        // To verify that this is in fact the current user, currentAsync can be used
52	        currentUser = await Parse.User.currentAsync();
53	        console.log(loggedInUser === currentUser);
54	        return true;
55	      })
56	      .catch(async (error) => {
57	        // Error can be caused by wrong parameters or lack of Internet connection
58	        Alert.alert('Error!', error.message);
59	        return false;
60	      });
61	  } catch (error) {
62	    // Error can be caused by wrong parameters or lack of Internet connection
63	    Alert.alert('Error!', error);
64	    return false;
65	  }
66	};
```

```typescript
1	const doUserLinkApple = async function (): Promise<boolean> {
2	  try {
3	    let response: object = {};
4	    let appleId: string = '';
5	    let appleToken: string = '';
6	    if (Platform.OS === 'ios') {
7	      // Performs login request requesting user email
8	      response = await appleAuth.performRequest({
9	        requestedOperation: appleAuth.Operation.LOGIN,
10	        requestedScopes: [appleAuth.Scope.EMAIL],
11	      });
12	      // On iOS, user ID and email are easily retrieved from request
13	      appleId = response.user;
14	      appleToken = response.identityToken;
15	    } else if (Platform.OS === 'android') {
16	      // Configure the request
17	      appleAuthAndroid.configure({
18	        // The Service ID you registered with Apple
19	        clientId: 'YOUR_SERVICE_ID',
20	        // Return URL added to your Apple dev console
21	        redirectUri: 'YOUR_SERVICE_URL',
22	        responseType: appleAuthAndroid.ResponseType.ALL,
23	        scope: appleAuthAndroid.Scope.ALL,
24	      });
25	      response = await appleAuthAndroid.signIn();
26	      // Decode user ID and email from token returned from Apple,
27	      // this is a common workaround for Apple sign-in via web API
28	      const decodedIdToken: object = jwt_decode(response.id_token);
29	      appleId = decodedIdToken.sub;
30	      appleToken = response.id_token;
31	    }
32	    // Format authData to provide correctly for Apple linkWith on Parse
33	    const authData: object = {
34	      id: appleId,
35	      token: appleToken,
36	    };
37	    let currentUser: Parse.User = await Parse.User.currentAsync();
38	    // Link user with his Apple Credentials
39	    return await currentUser
40	      .linkWith('apple', {
41	        authData: authData,
42	      })
43	      .then(async (loggedInUser: Parse.User) => {
44	        // logIn returns the corresponding ParseUser object
45	        Alert.alert(
46	          'Success!',
47	          `User ${loggedInUser.get(
48	            'username',
49	          )} has successfully linked his Apple account!`,
50	        );
51	        // To verify that this is in fact the current user, currentAsync can be used
52	        currentUser = await Parse.User.currentAsync();
53	        console.log(loggedInUser === currentUser);
54	        return true;
55	      })
56	      .catch(async (error: object) => {
57	        // Error can be caused by wrong parameters or lack of Internet connection
58	        Alert.alert('Error!', error.message);
59	        return false;
60	      });
61	  } catch (error: any) {
62	    // Error can be caused by wrong parameters or lack of Internet connection
63	    Alert.alert('Error!', error);
64	    return false;
65	  }
66	};
```
:::

이 기능을 Apple 버튼 <font color="#2166ae">`onPress`</font> 매개변수에 할당하세요. 새로운 기능을 테스트하고, <font color="#2166ae">`Parse.User`</font> 객체의 <font color="#2166ae">`authData`</font> 값이 새로운 인증 제공자 데이터로 업데이트될 것임을 주의하세요. 사용자가 실제로 Parse 서버 대시보드에서 업데이트되었는지 확인하세요.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/MNr0-o_nrQgaLIDQfa8sw_image.png)

## 결론

이 가이드의 끝에서, Apple Sign-in을 사용하여 React Native에서 Parse 사용자에게 로그인, 가입 또는 기존 사용자를 연결하는 방법을 배웠습니다. <font color="#2166ae">`react-native-apple-authentication`</font>을 사용했습니다. 다음 가이드에서는 유용한 사용자 쿼리를 수행하는 방법을 보여드리겠습니다.
