Flutter/Social Login

[Flutter] Kakao Login ② - 구현

찌김이 2022. 8. 23. 06:00
728x90
반응형

 

 

[Flutter] Kakao Login ① - 준비

소셜 로그인 구현 세번째는 카카오 로그인 입니다. 세팅방법은 소셜 로그인중에서는 제일 간단하지 싶습니다. Kakao Developers 카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오

dalgoodori.tistory.com

 

이전 포스팅에서 카카오 로그인을 위한 모든 셋팅을 완료하였습니다.

이번 포스팅에서는 카카오 로그인을 구현하고 유저의 이메일, 이름을 가져오는 것 까지 구현해보겠습니다.

 

pubspec.yaml

 

kakao_flutter_sdk_user | Flutter Package

A flutter plugin for Kakao API, which supports Kakao login, KakaoTalk Share, User API, KakaoTalk API, KakaoStory API and Navi API.

pub.dev

dependencies:
  kakao_flutter_sdk_user: ^1.2.1

 

 

main.dart

  • KakaoSdk.init(nativeAppKey: '네이티브 앱 키') 를 넣어주세요.

 

void main() {
  KakaoSdk.init(nativeAppKey: '네이티브 앱 키');
  runApp(const MyApp());
}

 

login_platform.dart

  • 로그인을 구현할 플랫폼들을 enum 으로 한개 만들어 둡니다.

 

enum LoginPlatform {
  facebook,
  google,
  kakao,
  naver,
  apple,
  none, // logout
}

 

sample_screen.dart

  • 로고 버튼을 눌러 로그인을 실행하고 로그아웃 버튼으로 로그아웃을 처리하는 화면입니다.
  • StatefulWidget 으로 만들고 현재 로그인한 플랫폼을 저장할 변수를 선언합니다.

 

LoginPlatform _loginPlatform = LoginPlatform.none;

 

 

로그인 처리 

  • 모든 셋팅을 정상적으로 완료하였다면 아래의 코드로 로그인이 진행됩니다.
  • isKakaoTalkInstalled() 로 카카오톡 설치 여부를 확인합니다.
  • 카카오톡이 설치되어 있다면 await UserApi.instance.loginWithKakaoTalk() 을 통해 카카오톡을 실행하여 로그인을 진행 합니다.
  • 카카오톡이 설치되어 있지 않다면 await UserApi.instance.loginWithKakaoAccount() 을 통해 웹으로 로그인을 진행 합니다.
bool isInstalled = await isKakaoTalkInstalled();

OAuthToken token = isInstalled
    ? await UserApi.instance.loginWithKakaoTalk()
    : await UserApi.instance.loginWithKakaoAccount();

 

 

유저정보 확인

  • 예제에서는 유저정보 확인을 http 패키지로 진행하였습니다.

 

 

http | Dart Package

A composable, multi-platform, Future-based API for HTTP requests.

pub.dev

 

  • 로그인을 성공했다면 OAuthToken 으로 accessToken 값을 받아올 수 있습니다.
  • 이 토큰 값으로 유저정보를 확인하는 요청을 보내면 이름과 이메일 정보를 얻을 수 있습니다. (이메일은 동의 필요)
  • 로그인 상태값을 갱신시켜줍니다.

 

  void signInWithKakao() async {
    try {
      bool isInstalled = await isKakaoTalkInstalled();

      OAuthToken token = isInstalled
          ? await UserApi.instance.loginWithKakaoTalk()
          : await UserApi.instance.loginWithKakaoAccount();

      final url = Uri.https('kapi.kakao.com', '/v2/user/me');

      final response = await http.get(
        url,
        headers: {
          HttpHeaders.authorizationHeader: 'Bearer ${token.accessToken}'
        },
      );

      final profileInfo = json.decode(response.body);
      print(profileInfo.toString());
      
      setState(() {
        _loginPlatform = LoginPlatform.kakao;
      });
      
    } catch (error) {
      print('카카오톡으로 로그인 실패 $error');
    }
  }

 

 

로그아웃 처리

  • await UserApi.instance.logout() 을 통하여 처리합니다.
  • 로그인 상태값을 false, 현재 로그인 플랫폼을 none 으로 갱신 시켜줍니다.

 

  void signOut() async {
    switch (_loginPlatform) {
      case LoginPlatform.facebook:
        break;
      case LoginPlatform.google:
        break;
      case LoginPlatform.kakao:
        // 추가
        await UserApi.instance.logout();
        break;
      case LoginPlatform.naver:
        break;
      case LoginPlatform.apple:
        break;
      case LoginPlatform.none:
        break;
    }

    setState(() {
      _loginPlatform = LoginPlatform.none;
    });
  }

 

 

로그인 버튼 

  • onPressed 나 onTap 이 있는 아무 위젯이나 사용해도 되지만 그렇게하면 기분이 나지 않으니 버튼을 구현해봅시다.

 

  • 프로젝트에서 asset 폴더와 그 안에 image 폴더를 만들고 다운받은 로고를 넣어줍니다.

 

  • pubspec.yaml 에 assets 를 추가해주세요.
flutter:
  assets:
    - asset/image/

 

 

  • 버튼에 그림자 효과를 주기위해 Card 위젯을 사용했습니다.
  • 버튼에 ripple 효과를 주기위해 Card 위젯 자식으로 Ink 위젯을 사용했습니다.
  • 그리고 onTap 사용을 위해 InkWell 위젯을 사용했습니다.
  • 이미지 경로는 path 부분을 빼고 모두 공통으로 처리할 것이기 때문에 이미지의 이름만 path 로 받습니다.
  • VoidCallback 을 통해 로그인 처리를 하는 함수를 받습니다.

 

  Widget _loginButton(String path, VoidCallback onTap) {
    return Card(
      elevation: 18.0,
      shape: const CircleBorder(),
      clipBehavior: Clip.antiAlias,
      child: Ink.image(
        image: AssetImage('asset/image/$path.png'),
        width: 60,
        height: 60,
        child: InkWell(
          borderRadius: const BorderRadius.all(
            Radius.circular(35.0),
          ),
          onTap: onTap,
        ),
      ),
    );
  }

 

 

로그아웃 버튼

  Widget _logoutButton() {
    return ElevatedButton(
      onPressed: signOut,
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all(
          const Color(0xff0165E1),
        ),
      ),
      child: const Text('로그아웃'),
    );
  }

 

 

전체 코드

main.dart

import 'package:flutter/material.dart';
import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart';

void main() {
  KakaoSdk.init(nativeAppKey: '네이티브 앱 키');
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const SampleScreen(),
    );
  }
}

 

 

sample_screen.dart

import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart';
import 'package:social_login_app/login_platform.dart';


class SampleScreen extends StatefulWidget {
  const SampleScreen({Key? key}) : super(key: key);

  @override
  State<SampleScreen> createState() => _SampleScreenState();
}

class _SampleScreenState extends State<SampleScreen> {
  LoginPlatform _loginPlatform = LoginPlatform.none;


  void signInWithKakao() async {
    try {
      bool isInstalled = await isKakaoTalkInstalled();

      OAuthToken token = isInstalled
          ? await UserApi.instance.loginWithKakaoTalk()
          : await UserApi.instance.loginWithKakaoAccount();

      final url = Uri.https('kapi.kakao.com', '/v2/user/me');

      final response = await http.get(
        url,
        headers: {
          HttpHeaders.authorizationHeader: 'Bearer ${token.accessToken}'
        },
      );

      final profileInfo = json.decode(response.body);
      print(profileInfo.toString());

      setState(() {
        _loginPlatform = LoginPlatform.kakao;
      });

    } catch (error) {
      print('카카오톡으로 로그인 실패 $error');
    }
  }

  void signOut() async {
    switch (_loginPlatform) {
      case LoginPlatform.facebook:
        break;
      case LoginPlatform.google:
        break;
      case LoginPlatform.kakao:
        await UserApi.instance.logout();
        break;
      case LoginPlatform.naver:
        break;
      case LoginPlatform.apple:
        break;
      case LoginPlatform.none:
        break;
    }

    setState(() {
      _loginPlatform = LoginPlatform.none;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child: _loginPlatform != LoginPlatform.none
              ? _logoutButton()
              : Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    _loginButton(
                      'kakao_logo',
                      signInWithKakao,
                    )
                  ],
                )),
    );
  }

  Widget _loginButton(String path, VoidCallback onTap) {
    return Card(
      elevation: 5.0,
      shape: const CircleBorder(),
      clipBehavior: Clip.antiAlias,
      child: Ink.image(
        image: AssetImage('asset/image/$path.png'),
        width: 60,
        height: 60,
        child: InkWell(
          borderRadius: const BorderRadius.all(
            Radius.circular(35.0),
          ),
          onTap: onTap,
        ),
      ),
    );
  }

  Widget _logoutButton() {
    return ElevatedButton(
      onPressed: signOut,
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all(
          const Color(0xff0165E1),
        ),
      ),
      child: const Text('로그아웃'),
    );
  }
}

 

login_platform.dart

enum LoginPlatform {
  facebook,
  google,
  kakao,
  naver,
  apple,
  none,
}
 

 

 

카카오 로그인 뿐만 아니라 다른 소셜 로그인 구현도 포스팅 해놓았습니다!! 

 

코딩전사의 기록

 

dalgoodori.tistory.com

 

 

728x90
반응형

'Flutter > Social Login' 카테고리의 다른 글

[Flutter] Naver Login ② - 구현  (5) 2022.08.25
[Flutter] Naver Login ① - 준비  (0) 2022.08.24
[Flutter] Kakao Login ① - 준비  (3) 2022.08.22
[Flutter] Google Login ② - 구현  (2) 2022.08.21
[Flutter] Google Login ① - 준비  (1) 2022.08.19