본문 바로가기

리액트 네이티브

[인스타그램 클론코딩] 앱 로그인 구조

[인스타그램 클론코딩] 웹 로그인 구조 포스트와 달리 앱에서는 Context를 사용하지 않았습니다.

왜 Context를 사용하지 않았나요?

googleLogin 함수는 구글 로그인 버튼을 클릭했을 때 실행되는 핸들러입니다.

import { Auth } from 'aws-amplify';

const googleLogin = async () => {
   const user = await Auth.federatedSignIn({provider: 'Google'});
   console.log(user) // undefined
}

그런데 user 출력해 보면 undefined라고 나옵니다.

왜일 까요?

웹에서는 이런 현상이 발생하지 않았습니다. 그래서 Auth.federatedSignIn 후에 AuthContext의 isLoggedIn을 변경해 주었습니다.

웹에서는 동일한 탭에서 소셜 인증 사이트로 넘어간 다음 리디렉션 되면서 토큰이 전송됩니다.

하지만 앱에서는 외부 브라우저에서 소셜 인증 사이트가 나타나고, 계정을 선택하면 앱으로 리디렉션 됩니다. 즉, 소셜 인증 사이트에 접속해 있을 때도 앱은 계속 동작하고 있습니다.

그리고 Auth.federatedSignIn도 단순히 외부 브라우저에 소셜 인증 사이트를 로드하는 것으로 마무리되는 메소드로 추측됩니다. 즉, await를 했다고 사용자가 외부 브라우저에서 계정을 선택할 때까지 기다리는 것이 아니라, 외부 브라우저에 소셜 인증 사이트 로드를 시작할 때까지만 기다리는 것입니다. 

 

외부 브라우저에서 실행되는 인증 프로세스

그렇다면 해결 방법은?

다행히도 AWS Amplify는 Hub라는 객체도 제공해 줍니다. Amplify 인증 관련 이벤트를 수신할 수 있는 객체입니다.

참조: https://docs.amplify.aws/lib/utilities/hub/q/platform/js#working-with-the-api

 

App.js

App 컴포넌트가 마운트될 때 Hub.listen 메소드로 인증(auth) 관련 이벤트 리스닝을 시작합니다. 이후 어떤 컴포넌트에서 인증 관련 요청을 하더라도 Hub.listen 메소드의 콜백 함수로 수신할 수 있습니다.

import React, { useState, useEffect } from 'react';
import Amplify, { Auth, Hub } from 'aws-amplify';
import aws_exports from "./aws-exports";
Amplify.configure(aws_exports);

export default function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  useEffect(() => {
    Hub.listen('auth', (data) => {
      const { payload } = data
      if (payload.event === 'signIn') {
         setIsLoggedIn(true);
      }
      if (payload.event === 'signOut') {
         //console.log('a user has signed out!')
         setIsLoggedIn(false);
      }
    });

    return () => {}
  }, []);

  return (
    <NavController isLoggedIn={isLoggedIn}/>
  ) : (
    <AppLoading />
  );
}

다이어그램

App 컴포넌트가 마운트될 때, Auth.currentAuthenticatedUser 메소드를 사용해 Async Storage에서 사용자 정보를 가져오면 isLoggedIn을 true로 설정하고(DummyNavigation 랜더링), 그렇지 않으면 false로 설정(AuthNavigation 랜더링)합니다.

이후에는 App 컴포넌트에서 Hub 객체가 Amplify 인증 이벤트를 수신해서 isLoggedIn을 변경합니다.

isLoggedIn 상태가 변경되면 App 컴포넌트부터 다시 랜더링됩니다.

 

[인스타그램 클론코딩] 앱 로그인 구조