[flutter] Firebase Firestore와 플러터를 이용한 음악 스트리밍 애플리케이션 만들기

소개

이 튜토리얼에서는 Firebase Firestore와 Flutter를 사용하여 음악 스트리밍 애플리케이션을 만드는 방법을 알아보겠습니다. Firebase Firestore는 Firebase의 실시간 데이터베이스로써, 실시간으로 데이터를 동기화하고 관리하는 데 사용됩니다. Flutter는 Google에서 개발한 크로스 플랫폼 모바일 앱 개발 프레임워크로써, 하나의 코드베이스로 안드로이드와 iOS 앱을 동시에 개발할 수 있습니다.

목차

  1. 필요한 패키지 설치하기
  2. Firebase 프로젝트 설정하기
  3. Firestore 데이터베이스 생성하기
  4. 음악 목록 표시하기
  5. 음악 재생 기능 추가하기
  6. 음악 업로드 기능 추가하기
  7. 음악 검색 기능 추가하기
  8. 추가 기능 구현하기 (즐겨찾기, 공유 등)
  9. 배포하기

1. 필요한 패키지 설치하기

이 튜토리얼에서는 Firebase와 Firestore를 사용하므로, cloud_firestore 패키지를 설치해야 합니다. pubspec.yaml 파일의 dependencies 섹션에 다음과 같이 추가해주세요.

dependencies:
  flutter:
    sdk: flutter
  cloud_firestore: ^2.2.0

2. Firebase 프로젝트 설정하기

Firebase 콘솔에서 새로운 프로젝트를 생성하고, 앱을 추가해주세요. Firebase SDK 구성 파일(google-services.json 또는 GoogleService-Info.plist)을 다운로드하여 프로젝트 루트 디렉토리에 추가해주세요.

3. Firestore 데이터베이스 생성하기

Firebase 콘솔에서 Firestore 데이터베이스를 생성하고, 컬렉션과 필드를 설정해주세요. 예를 들어, songs 컬렉션을 생성하고 각 문서에 title, artist, url 등의 필드를 추가할 수 있습니다.

4. 음악 목록 표시하기

Flutter 앱의 화면을 구성하여 Firestore에서 음악 데이터를 가져와 목록으로 표시합니다.

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

class MusicList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
      stream: FirebaseFirestore.instance.collection('songs').snapshots(),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
        if (snapshot.hasError) {
          return Text('Error: ${snapshot.error}');
        }

        if (snapshot.connectionState == ConnectionState.waiting) {
          return CircularProgressIndicator();
        }

        return ListView(
          children: snapshot.data!.docs.map((DocumentSnapshot document) {
            final data = document.data() as Map<String, dynamic>;
            return ListTile(
              title: Text(data['title']),
              subtitle: Text(data['artist']),
            );
          }).toList(),
        );
      },
    );
  }
}

5. 음악 재생 기능 추가하기

음악 목록에서 특정 음악을 선택하면 해당 음악을 재생하는 기능을 추가합니다. 음악 재생은 다른 패키지를 사용할 수 있으며, 예를 들어 audioplayers 패키지를 사용할 수 있습니다.

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

class MusicPlayer extends StatefulWidget {
  final String url;

  MusicPlayer({required this.url});

  @override
  _MusicPlayerState createState() => _MusicPlayerState();
}

class _MusicPlayerState extends State<MusicPlayer> {
  AudioPlayer audioPlayer = AudioPlayer();
  PlayerState playerState = PlayerState.STOPPED;

  @override
  void initState() {
    super.initState();
    audioPlayer.onPlayerStateChanged.listen((PlayerState state) {
      setState(() {
        playerState = state;
      });
    });
  }

  @override
  void dispose() {
    audioPlayer.dispose();
    super.dispose();
  }

  void playMusic() async {
    if (playerState == PlayerState.PLAYING) {
      audioPlayer.pause();
    } else {
      await audioPlayer.play(widget.url, isLocal: false);
    }
  }

  @override
  Widget build(BuildContext context) {
    return IconButton(
      icon: Icon(playerState == PlayerState.PLAYING ? Icons.pause : Icons.play_arrow),
      onPressed: playMusic,
    );
  }
}

6. 음악 업로드 기능 추가하기

사용자가 음악을 업로드하는 기능을 추가합니다. 업로드된 음악은 Firestore에 저장되고, 필요할 때 다시 재생할 수 있습니다.

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';

class MusicUploader extends StatefulWidget {
  @override
  _MusicUploaderState createState() => _MusicUploaderState();
}

class _MusicUploaderState extends State<MusicUploader> {
  FirebaseFirestore firestore = FirebaseFirestore.instance;
  FirebaseStorage storage = FirebaseStorage.instance;

  TextEditingController titleController = TextEditingController();
  TextEditingController artistController = TextEditingController();
  TextEditingController urlController = TextEditingController();

  void uploadMusic() async {
    String title = titleController.text;
    String artist = artistController.text;
    String url = urlController.text;

    await firestore.collection('songs').add({
      'title': title,
      'artist': artist,
      'url': url,
    });

    titleController.clear();
    artistController.clear();
    urlController.clear();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextField(controller: titleController, decoration: InputDecoration(labelText: 'Title')),
        TextField(controller: artistController, decoration: InputDecoration(labelText: 'Artist')),
        TextField(controller: urlController, decoration: InputDecoration(labelText: 'URL')),
        ElevatedButton(onPressed: uploadMusic, child: Text('Upload')),
      ],
    );
  }
}

7. 음악 검색 기능 추가하기

사용자가 음악을 검색할 수 있는 기능을 추가합니다. Firestore의 where 메서드를 사용하여 필터링된 데이터를 가져옵니다.

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

class MusicSearch extends StatefulWidget {
  @override
  _MusicSearchState createState() => _MusicSearchState();
}

class _MusicSearchState extends State<MusicSearch> {
  TextEditingController searchController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextField(controller: searchController, decoration: InputDecoration(labelText: 'Search')),
        ElevatedButton(
          onPressed: () {
            String query = searchController.text;
            final CollectionReference songsRef = FirebaseFirestore.instance.collection('songs');

            return StreamBuilder<QuerySnapshot>(
              stream: songsRef.where('title', isEqualTo: query).snapshots(),
              builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                }

                if (snapshot.connectionState == ConnectionState.waiting) {
                  return CircularProgressIndicator();
                }

                return ListView(
                  children: snapshot.data!.docs.map((DocumentSnapshot document) {
                    final data = document.data() as Map<String, dynamic>;
                    return ListTile(
                      title: Text(data['title']),
                      subtitle: Text(data['artist']),
                    );
                  }).toList(),
                );
              },
            );
          },
          child: Text('Search'),
        ),
      ],
    );
  }
}

8. 추가 기능 구현하기

애플리케이션에 추가 기능을 구현할 수 있습니다. 예를 들어, 즐겨찾기 기능을 구현하여 사용자가 음악을 즐겨찾기에 추가하거나, 음악을 공유할 수 있도록 기능을 추가할 수 있습니다.

9. 배포하기

앱 개발이 완료되면, Flutter의 빌드 및 배포 기능을 사용하여 Android와 iOS 앱으로 빌드하고 앱 스토어에 배포합니다.

참고 자료