Soojeong Lee

2025. 7. 30.

Soojeong Lee

2025. 7. 30.

Soojeong Lee

2025. 7. 30.

빠른 Firebase 도입

빠른 Firebase 도입

필요한 Firebase 기능 적용해놓기

뭘 추가했는가?

기능적으로 필요한 부분을 추가했다.

  • 인증이 필요하다 (Firebase Auth)

  • 영상/사진 업로드가 필요하다 (Firebase Storage)

같은 구글이라 그런지 Firebase와 Flutter 연동은 엄청 쉽다. cli 설치하고 나서 거의 떠먹여주는 수준.

똰. 추가 완료.


앱 내 로그인 추가

개인적으로 OAuth를 좋아하긴 하지만 심사 통과나 베타 테스트 목적으로는 일반 로그인만 구현해도 끝날 것 같았다. 서버 호스팅 까지 비용 감당을 벌써 하는건…좀 그렇고 일단 MVP 차원에서는 Firebase Auth 쓰면 끝난다.

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

final firebaseAuthProvider = Provider<FirebaseAuth>((ref) {
  return FirebaseAuth.instance;
});

final authStateChangesProvider = StreamProvider<User?>((ref) {
  final auth = ref.watch(firebaseAuthProvider);
  return auth.authStateChanges();
});


서비스를 추가해놓고, 초기 화면 라우트를 가드한다.

final goRouterProvider = Provider<GoRouter>((ref) {
  final authState = ref.watch(authStateChangesProvider);

  return GoRouter(
    initialLocation: '/memories',
    redirect: (context, state) {
      final isLoggedIn = authState.asData?.value != null;
      final isGoingToSignIn = state.matchedLocation == '/login';

      if (!isLoggedIn && !isGoingToSignIn) {
        return '/login';
      }
      if (isLoggedIn && isGoingToSignIn) {
        return '/memories';
      }
      return null;
    },
...


로그인 관련해서 아직은 복잡하게 구현하지는 않았고, 테스트 계정을 임의로 등록해놓고 인증 되는지만 검증하였다. (어차피 validation 붙이면서 나중에 더 작업해야 한다)

class LoginScreen extends ConsumerWidget {
  const LoginScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final auth = ref.read(firebaseAuthProvider);

    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            await auth.signInWithEmailAndPassword(
              email: 'test@test.com',
              password: 'testpassword',
            );
          },
          child: const Text('Sign In'),
        ),
      ),
    );
  }
}

(사용 중지했으니 이 글 보고 마구마구 로그인 눌러보지 마시길… 어차피 안돼요.)


사진/영상 업로드

요건 제일 많이 쓰는 image_picker 패키지와, 선택한 파일은 Firebase Storage에 업로드하고 url을 반환하는 형태로 마무리지었다.

  Future<void> _handleMediaUpload() async {
    final ImagePicker picker = ImagePicker();
    final List<XFile> medias = await picker.pickMultipleMedia();

    if (medias.isEmpty) {
      return;
    }

    final storageRef = FirebaseStorage.instance.ref();
    final userId = FirebaseAuth.instance.currentUser?.uid;

    for (final media in medias) {
      final file = File(media.path);
      final fileName = media.name;
      final uploadRef = storageRef.child('memories/$userId/$fileName');

      try {
        final uploadTask = await uploadRef.putFile(file);
        final downloadUrl = await uploadTask.ref.getDownloadURL();
        debugPrint('Uploaded: $downloadUrl');
      } catch (e) {
        debugPrint('Upload failed: $e');
      }
    }
  }

(이것도 CRUD 동작 전부 막았으니 이 글 보고 마구마구 업로드 하지 마시길… 어차피 안돼요.)

먼 훗날 AWS S3 Bucket으로 마이그레이션 해도 그리 복잡하지는 않을 것이다.


남은 것?

이제 중요한 기능은 거의 끝냈다. 남은 부분은

  • 회원가입

  • 번역

  • CRUD 동작 및 상태관리

  • iOS 앱스토어 업로드

  • Android APK 패키징 (심사가 빡빡해서 베타 테스트 방법은 고민 중)

남은 것 아마 손이 많이 가겠지만 주말에 빡개발 하면 마무리 지을 수 있을 듯.

Comments

Comments

Comments