플러터 강좌: 16.3 Firebase Auth 패키지 설치 및 이메일 인증 설정하기

안녕하세요, 플러터 개발자 여러분! 이번 강좌에서는 Firebase를 이용한 사용자 인증 중에서도 Email 인증을 설정하는 방법에 대해 자세히 알아보겠습니다. Firebase는 데이터베이스, 호스팅, 스토리지 등 다양한 서비스를 제공하며, 특히 Firebase Auth는 사용자 인증을 처리하는데 매우 유용합니다. 이 강좌에서는 Firebase Auth 패키지를 설치하고, 이메일 인증을 설정하는 방법을 단계별로 안내하겠습니다.

1. Firebase 프로젝트 생성하기

Firebase를 사용하기 위해서는 먼저 Firebase 콘솔에서 프로젝트를 생성해야 합니다. 다음 단계를 따라 프로젝트를 만듭니다.

  1. Firebase 콘솔에 접속합니다.
  2. 오른쪽 상단에 있는 ‘프로젝트 추가’ 버튼을 클릭합니다.
  3. 프로젝트 이름을 입력하고, Google 애널리틱스 설정을 선택한 후 ‘프로젝트 만들기’를 클릭합니다.

2. Firebase Auth 설정하기

프로젝트가 생성되면 Firebase Auth를 설정해야 합니다.

  1. 왼쪽 메뉴에서 ‘인증’을 클릭합니다.
  2. ‘로그인 방법’ 탭으로 이동합니다.
  3. 이메일/비밀번호 로그인 옵션을 찾아 활성화합니다.

3. 플러터 프로젝트 생성하기

이제 플러터 프로젝트를 생성해보겠습니다. 아래의 명령어로 새로운 플러터 프로젝트를 생성합니다.

flutter create firebase_auth_example

프로젝트 디렉토리로 이동합니다.

cd firebase_auth_example

4. Firebase Core 및 Auth 패키지 설치하기

플러터에서 Firebase를 사용하기 위해 필요한 패키지를 추가해야 합니다. ‘pubspec.yaml’ 파일을 열고 다음 의존성을 추가합니다.

dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^2.0.0
  firebase_auth: ^5.0.0

이제 패키지를 설치하기 위해 아래의 명령어를 입력합니다.

flutter pub get

5. Firebase 초기화하기

패키지를 설치한 후, Firebase를 초기화해야 합니다. ‘main.dart’ 파일을 열고 다음 코드를 추가합니다.

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Firebase Auth Example',
      home: HomeScreen(),
    );
  }
}

6. 로그인 UI 만들기

이메일 인증을 위한 로그인 화면을 구축해보겠습니다. ‘HomeScreen’ 위젯을 추가하고, 이메일과 비밀번호 입력 필드 및 로그인 버튼을 포함합니다.

import 'package:firebase_auth/firebase_auth.dart';

// ...

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final TextEditingController _emailController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  void signIn(String email, String password) async {
    try {
      UserCredential userCredential = await _auth.signInWithEmailAndPassword(
        email: email,
        password: password,
      );
      print('User signed in: ${userCredential.user}');
    } on FirebaseAuthException catch (e) {
      print('Failed to sign in: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('로그인'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _emailController,
              decoration: InputDecoration(labelText: '이메일'),
            ),
            TextField(
              controller: _passwordController,
              decoration: InputDecoration(labelText: '비밀번호'),
              obscureText: true,
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                signIn(_emailController.text, _passwordController.text);
              },
              child: Text('로그인'),
            ),
          ],
        ),
      ),
    );
  }
}

7. 이메일 인증 요청하기

이메일 인증을 완료하기 위해 사용자가 로그인한 후 이메일 인증을 요청할 수 있습니다. 아래와 같이 코드를 추가합니다.

void sendVerificationEmail(User user) async {
  if (!user.emailVerified) {
    await user.sendEmailVerification();
    print('Verification email sent to ${user.email}');
  }
}

// signIn 메소드의 끝부분에 추가합니다.
if (userCredential.user != null) {
  sendVerificationEmail(userCredential.user!);
}

8. 이메일 인증 확인하기

사용자가 이메일을 확인했는지 상태를 확인하는 로직을 추가합니다. 로그인 후 사용자가 이메일을 확인했는지 확인할 수 있습니다.

void checkEmailVerification() async {
  User? user = _auth.currentUser;
  await user?.reload();
  user = _auth.currentUser;
  if (user != null && user.emailVerified) {
    print('Email verified!');
    // 인증된 사용자로 이동하는 로직 추가 가능
  } else {
    print('Email not verified yet.');
  }
}

// 로그인 메소드 끝부분에 추가합니다.
checkEmailVerification();

9. 완성된 코드

마지막으로 완성된 main.dart 코드는 다음과 같습니다.

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Firebase Auth Example',
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final TextEditingController _emailController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  void signIn(String email, String password) async {
    try {
      UserCredential userCredential = await _auth.signInWithEmailAndPassword(
        email: email,
        password: password,
      );
      sendVerificationEmail(userCredential.user!);
      checkEmailVerification();
    } on FirebaseAuthException catch (e) {
      print('Failed to sign in: $e');
    }
  }

  void sendVerificationEmail(User user) async {
    if (!user.emailVerified) {
      await user.sendEmailVerification();
      print('Verification email sent to ${user.email}');
    }
  }

  void checkEmailVerification() async {
    User? user = _auth.currentUser;
    await user?.reload();
    user = _auth.currentUser;
    if (user != null && user.emailVerified) {
      print('Email verified!');
    } else {
      print('Email not verified yet.');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('로그인'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _emailController,
              decoration: InputDecoration(labelText: '이메일'),
            ),
            TextField(
              controller: _passwordController,
              decoration: InputDecoration(labelText: '비밀번호'),
              obscureText: true,
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                signIn(_emailController.text, _passwordController.text);
              },
              child: Text('로그인'),
            ),
          ],
        ),
      ),
    );
  }
}

10. 결론

이제 플러터와 Firebase를 사용하여 이메일 인증을 설정하는 방법을 배웠습니다. 사용자 경험을 향상시키기 위해 사용자에게 이메일 인증을 요청하는 것은 중요한 기능입니다. 추가적인 보안을 위해 이 기능을 활용하시길 바랍니다. 다음 강좌에서는 소셜 로그인을 구현하는 방법을 다뤄보겠습니다. 감사합니다!