EP7. Flutter 로그인 (AuthService) 패키지 구현
1. 딥링크 정의
특정 URL을 통해 모바일 앱의 특정 화면이나 기능으로 직접 연결해주는 기술입니다. 이를 통해 사용자는 웹페이지나 다른 앱에서 해당 앱의 특정 콘텐츠로 바로 이동할 수 있습니다
Dart
복사
외부 Provider(ex. 카카오톡, 구글, 애플, 네이버 등…)로그인을 진행하면 아래 Flow로 진행됩니다.
•
내 앱 > 외부 Provider 로그인 화면 > 내 앱
위 구간 중 외부 Provider 로그인 화면 > 내 앱을 위해 딥링크를 등록해야 합니다.
보통 앱 이름 정도를 많이 사용하나 타 앱과 겹치지 않는 선에서 선택 사용할 수 있습니다.
강의에서는 flutter-package-sample 을 사용하도록 하겠습니다.
2. iOS 프로젝트 설정
1.
XCode open
•
sample > ios > Flutter > Open iOS/macOS module in Xcode
위 메뉴를 통해 XCode로 iOS 프로젝트를 열 수 있습니다.
2.
URL Scheme 등록
3. Android 프로젝트 설정
sample 프로젝트 > AndroidManifest.xml 파일에 아래 내용을 추가합니다.
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="flutter-package-sample"/>
</intent-filter>
XML
복사
FYI) 작업 Commit
4. Supabase에 딥링크 등록
•
Authentication > URL Configuration > Redirect URLs
App Scheme을 Redirect URL로 사용할 수 있도록 등록합니다. 외부 로그인 Provider로부터 로그인이 완료되면 다시 앱으로 돌아가기 위한 방법으로 사용됩니다.
딥링크://* 포맷으로 넣어주시면 됩니다.
5. Package 디렉토리 구조
•
entities: 패키지에서 공통으로 사용하는 Entity를 관리
•
services: 패키지에서 공통으로 사용하는 Service를 관리
패키지 디렉토리에 entities와 services디렉토리를 추가합니다.
6. User Entity 구현
1.
entities/user.dart
import 'package:supabase_flutter/supabase_flutter.dart';
class FPUser {
final String id;
final Map<String, dynamic>? userMetadata;
final String createdAt;
final String? lastSignInAt;
final bool isAnonymous;
const FPUser({
required this.id,
required this.userMetadata,
required this.createdAt,
this.lastSignInAt,
this.isAnonymous = false,
});
}
// Supabase에서 제공하는 User class의 extension 구현
extension SupabaseUserExtension on User {
FPUser toFPUser() {
return FPUser(id: id, userMetadata: userMetadata, createdAt: createdAt);
}
}
Dart
복사
•
Supabase에서 User 클래스를 선언해서 사용하고 있음. Supabase 의존성을 줄이기 위해 Supabase User에서 주로 사용되는 필드만 따로 FPUser 클래스로 변환하여 사용하도록 함.
2.
services/auth_service.dart
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:swm_flutter_package/entities/user.dart';
class FPAuthService {
FPAuthService();
/// 현재 사용자가 로그인되어 있는지 확인합니다.
bool isSignedIn() {
return getCurrentUser() != null;
}
/// 현재 사용자의 인증 상태 변경을 스트림으로 반환합니다.
Stream<FPUser?> getUserStream() {
return Supabase.instance.client.auth.onAuthStateChange.map((event) => event.session?.user.toFPUser());
}
/// 현재 인증된 사용자를 가져옵니다. (있다면)
FPUser? getCurrentUser() {
return Supabase.instance.client.auth.currentSession?.user.toFPUser();
}
/// 현재 세션의 JWT 액세스 토큰을 가져옵니다.
String? getJWTToken() {
return Supabase.instance.client.auth.currentSession?.accessToken;
}
/// Kakao OAuth Provider를 사용하여 사용자를 로그인합니다.
/// redirectTo에는 로그인 완료 후 돌아올 링크(현재 앱의 app scheme)을 입력합니다.
Future<bool> signInWithKakao({required String appScheme}) async {
return await Supabase.instance.client.auth.signInWithOAuth(
OAuthProvider.kakao,
authScreenLaunchMode: LaunchMode.externalApplication,
redirectTo: appScheme
);
}
/// 사용자를 익명으로 로그인합니다.
/// Supabase Console > Project Settings > Authentication > Allow anonymous sign-ins를 먼저 활성화해야합니다.
Future<void> signInAnonymously() async {
await Supabase.instance.client.auth.signInAnonymously();
return;
}
/// 현재 사용자를 로그아웃합니다.
Future<void> signOut() async {
return await Supabase.instance.client.auth.signOut();
}
}
Dart
복사
•
signInAnonymously(익명로그인)의 경우 Supabase 웹 콘솔에서 옵션을 활성화해야 사용할 수 있습니다.