Flutter Instagram Clone #8 Firebase를 이용한 구글 로그인 구현하기

jakeseo_me·2020년 7월 24일
0

Flutter-Instagram-Clone

목록 보기
8/14

Flutter Instagram Clone #8 Firebase를 이용한 구글 로그인 구현하기

원본 강의

https://www.inflearn.com/course/flutter-%EC%9E%85%EB%AC%B8/dashboard

여기서 유료 결제를 해서 듣고있는 강의의 내용을 개인적인 공부 목적으로 지식 위주로 정리해봅니다.

설계

위와 같다. Firebase를 이용한 인증과 Firestore를 이용하여 DB를 구성해본다.

구현

Firebase와 앱 연동하기

먼저 Firebase에 접속하여 프로젝트를 생성하자

프로젝트를 생성한 뒤에는 메인 페이지에서 안드로이드 앱으로 테스트를 해보자

가운데 안드로이드 아이콘을 누르면 아래와 같은 화면이 나온다.

이 화면에서 입력하란 것을 입력하면 되는데, 먼저 Android 패키지 이름에는 android > app > src > main > AndroidManifest.xml 경로에 존재하는 package 정보를 입력하면 된다.

패키지 이름에 위에서 찾은 내용을 입력해주고, 앱 닉네임은 대충 입력해준다.

그리고 디버그 서명 인증서 SHA-1을 입력해야 하는데, 서명 인증서를 입력해야 구글 로그인 기능을 구현할 수 있다. ?에 마우스를 올리고 '이 페이지를 참조하십시오.' 에 있는 페이지에 들어가면 아래와 같이 명령어가 나온다.

위 명령어를 터미널에 입력하면

글자가 좀 깨지긴 했지만 이렇게 키가 나온다. 스크린샷 아래 부분에 MD5와 SHA1키가 있다.

키를 정상적으로 입력하면 위와 같은 화면이 된다. google-services.json 파일을 다운로드 받고, 매뉴얼에서 시키는 위치에 옮겨준다.

android > app 경로에 넣어준다.

다음을 누르면,

이렇게 SDK를 추가하는 것에 대한 내용이 나온다.

프로젝트 수준의 build.gradle은 android 바로 아래에 있는 build.gradle을 의미한다. app밑에도 build.gradle이 있기 때문에 헷갈리지 않도록 한다.

위와 같이 디펜던시에 추가하자.

이후에는 위와 같이 앱 수준의 build.gradle에 플러그인과 디펜던시를 추가하라고 나오는데, 앱 수준이란 android > app 아래에 있는 build.gradle을 말하는 것이다.

이렇게 넣어주고,

이렇게 넣어준다.

전부 진행했으면 확실히 적용하기 위해 앱을 껐다 다시 켜주자.

그리고 Firebase 진행 화면으로 다시 넘어가서 다음 버튼을 누르면 다음과 같은 화면이 등장한다.

이 메세지가 정상적으로 나왔다면, 앱이 파이어베이스와 무사히 통신을 한 것이다.

나는 여기까지만 진행해도 Firebase와 통신이 아주 잘 됐지만, 강의에서는 app 밑의 build.gradle 파일에서 multiDexEnabled 라는 설정을 더 해주었다.

defaultConfig에서 multiDexEnabled true라고 입력하면, multiDex라는 설정이 되는데, 이 설정의 설명은 다음과 같다.

Android application (APK) files contain executable bytecode files in the form of Dalvik Executable (DEX) files, which contain the compiled code used to run your app. The Dalvik Executable specification limits the total number of methods that can be referenced within a single DEX file to 65,536, including Android framework methods, library methods, and methods in your own code. Getting past this limit requires that you configure your app build process to generate more than one DEX file, known as a multidex configuration.

안드로이드 어플리케이션 (APK) 파일들은 앱을 구동하기 위해 컴파일된 Dalvik Executable (DEX) 파일들 내부에 실행 가능한 바이트코드 파일들을 소유하고 있다. Dalvik Executable 세부사항은 하나의 DEX 파일내에서 참조될 수 있는 메소드의 총 숫자를 안드로이드 프레임워크 메소드와 라이브러리 메소드 그리고 코드 내부의 메소드를 포함하여 65536개로 제한한다. 이러한 제한을 해제하기 위해 앱 빌드 프로세스에서 1개 이상의 DEX 파일을 생성하도록 설정해야 하는데, 그게 바로 multidex 설정이다.

결국엔 DEX의 메소드 숫자의 한계를 풀기 위해 하는 설정인 것 같다.

하지만 이 멀티덱스를 마구잡이로 사용하면 앱 빌드 속도가 느려지고, 앱의 용량이 커진다고 한다. 관련 설명글이 여기에 있다.

이제 다시 파이어베이스 페이지로 돌아와서 인증 탭으로 들어간다.

그리고 로그인 방법 설정을 클릭하자.

구글 로그인을 할 거니까 당연히 구글을 클릭한다.

이메일은 당연히 내 메일로하고 저장하면

이렇게 사용 설정됨이 보인다.

이제 pubspec.yaml에 들어가서 google_sign_in 패키지와 firebase_auth 패키지를 입력해준다.

다 입력하면 잊지 않고, 우측 상단의 Pub get 버튼을 누른다. Pub get을 한 이후에는 패키지를 새로 깔았으니 앱을 껐다 켜주자.

앱에 구글 인증 소스코드 작성하기

다시 login_page.dart 파일로 돌아와서

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_signin_button/button_list.dart';
import 'package:flutter_signin_button/button_view.dart';
import 'package:google_sign_in/google_sign_in.dart';

class LoginPage extends StatelessWidget {
  final GoogleSignIn _googleSignIn = GoogleSignIn();
  final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;

위와 같이 GoogleSignIn 객체와 FirebaseAuth 객체를 생성하여 변수에 넣는다. 그런데, FirebaseAuth와 같은 경우에는 이미 싱글톤 패턴으로 지원을 하기 때문에 .instance라는 메소드를 통하여 인스턴스를 불러올 수 있다.

그리고 기존의 버튼에 달려있는 콜백 함수에 _handleSignIn()이라는 로그인을 처리할 새로운 메소드를 집어넣는다. 아래는 user의 displayName을 표출하게 해서 user가 잘 들어왔는지 확인하려고 임시로 넣은 코드이다.

SignInButton(Buttons.Google, onPressed: () {
  _handleSignIn().then((user) {
    print('user');
    print(user.displayName);
  });

마지막으로 _handleSignIn() 메소드를 작성하는데, 아래와 같이 작성하면 된다.

Future<FirebaseUser> _handleSignIn() async {
  GoogleSignInAccount googleUser = await _googleSignIn.signIn();
  GoogleSignInAuthentication googleAuth = await googleUser.authentication;
  FirebaseUser authResult = (await _firebaseAuth.signInWithCredential(
          GoogleAuthProvider.getCredential(
              idToken: googleAuth.idToken,
              accessToken: googleAuth.accessToken)))
      .user;
  return authResult;
}

로그인에 이용되는 각종 메소드를 살펴보면,

signIn() 메소드는 sign-in 프로세스를 시작하는 메소드라고 설명이 나와있다. 구글 페이지를 띄워서 로그인을 하게 만드는 녀석일 것이다. (추측)

authenticationsignIn() 메소드를 이용해 가져온 GoogleSignInAccount 객체에서 인증 정보를 가져오는 것이다.

signInWithCredential() 메소드는 부여된 서드파티 인증 정보를 이용해서 파이어베이스쪽으로 SignIn 하는 것이다. 만일 성공할 경우, 파이어베이스 앱으로 가입시키며, onAuthStateChanged의 흐름이 업데이트된다.

getCredentialidTokenaccessToken정보를 받아서 GoogleAuthProvider 객채로 바꾸어줍니다.

구글 인증으로 가져온 정보 앱에 적용하기

먼저 TabPage에서 유저 정보를 받게 만들어야 한다.

class TabPage extends StatefulWidget {
  final FirebaseUser user;
  TabPage(this.user);

  
  _TabPageState createState() => _TabPageState();
}

위와 같이 작성해주면, TabPage에서 생성자로 FirebaseUser를 받게 된다.

SignInButtononPressed 콜백에 MaterialPageRoute를 이용하여 TabPage를 생성자 호출을 하게 한다.

SignInButton(Buttons.Google, onPressed: () {
  _handleSignIn().then((user) {
    Navigator.pushReplacement(context,
        MaterialPageRoute(builder: (context) => TabPage(user)));
  });
})

pushReplacement는 처음 사용하는 메소드인데, 설명은 다음과 같다.

주어진 라우트를 밀어넣음으로써 가장 가까이 붙어있던 주어진 컨텍스트의 현재 네비게이터의 라우트를 대체한다. 그리고 새로운 라우트가 들어가면 이전 라우트는 지워버린다.

조건별로 분기하도록 RootPage 작성하기

RootPage에서 기존에는 그냥 LoginPage를 표출하게 만들었다면, 이번에는 저장된 FirebaseUser가 있으면 TabPage를 띄우고 없으면 LoginPage를 띄우게 만들어보자.

이러한 유형의 기능 구현은 StreamBuilder를 이용하여 가능하다.

class RootPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return StreamBuilder<FirebaseUser>(
        builder: (BuildContext context, AsyncSnapshot snapshot) {
      if (snapshot.hasData) {
        return TabPage(snapshot.data);
      } else {
        return LoginPage();
      }
    });
  }
}

snapshot이란 곳에 데이터가 있는지 판단하여 그에 따라 리턴할 페이지를 결정한다.

로그아웃 기능 구현하기

계정정보 화면의 우측 상단 나가기버튼을 누르면 로그아웃이 되게 만들 것이다.

먼저 account_page에 이전에 SignIn 했던 것과 같이 firebase_authgoogle_sign_in을 임포트해준다.

import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

잘 구현된 SignOut() 메소드들이 이미 있기 때문에 인스턴스만 잘 생성해서 SignOut() 메소드를 실행시켜주면 된다.

actions: <Widget>[
  IconButton(
    icon: Icon(Icons.exit_to_app),
    onPressed: () {
      FirebaseAuth.instance.signOut();
      _googleSignIn.signOut();
    },
  )

로그아웃 기능을 테스트해보려면 이전에 SignInButtonNavigation 코드 작성했던 것을 지워야 한다.

SignInButton(Buttons.Google, onPressed: () {
  _handleSignIn().then((user) {
    print(user.displayName);
  });
})

이렇게 바꿔주자.

결과

Sign In with Google Account 버튼을 클릭하면 아래와 같은 화면이 뜬다.

그리고 로그인을 진행하면 RootPage에서 snapshot에 데이터가 들어가게 된다.

이게 로그인 후의 화면이다.

Account 탭으로 들어가서 우측 상단의 로그아웃 버튼을 누르면...

다시 초기 로그인 화면으로 돌아온다.

profile
대전에 있는 (주) 아이와즈에서 풀스택 웹개발자로 일하고 있는 서진규입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. Javascript를 좋아합니다.

0개의 댓글