Flutter Firebase 데이터 저장하기 & [Dart] Stream

2021. 1. 26. 07:01Flutter

Flutter Firebase 데이터 저장하기

이번에는 인증이 아닌 Cloud FireStore를 활용하여 입력한 데이터를 저장해보는 기능을 구현해보겠습니다. Cloud FireStore는 키와 밸류로 이루어진 document형식의 NoSQL입니다. 

 

우선 Cloud FireStore에 들어가서 원하는 컬렉션, 다큐먼트를 만들어주면 된다. 

이제 Flutter에서 만든 데이터 베이스에 저장하고 변화가 있을 때 마다 트랙킹하는 코드를 작성해보자.

 

데이터 저장

FirebaseFirestore firestore = FirebaseFirestore.instance;
firestore.collection('messeges').add(
                     {'sender': loggedInUser.email, 
                     'text': messageText}
                     );

 

collection에는 자신이 저장할 컬렉션을 선택한다. 실수로 messeges라고 오타로 적었다. ㅠㅠ 그 다음 add라는 함수를 사용해서 키 값에 맞추어서 value를 넣어준다. 

 

 

데이터 가져오기

await for (var snapshot in firestore.collection('messeges').snapshots()) {
      for (var messege in snapshot.docs) {
        print(messege.data);
      }
    }

필자는 단순히 데이터를 가져오는 것이 아닌 fireStore에 messeges 컬렉션이 변경될 때 값을 가져오는 기능을 가져왔다. 여기서 snapshot이라는 것은 messeges collection을 변화를 트랙킹하고 변화 된 정보를 반복문으로 돌려주는 기능을 제공해준다. 

snapshots이라는 함수는 Future를 반환하기 때문에 await을 사용해준 것을 확인할 수 있다. 

 

 

Stream

snapshots의 반환 데이터를 잘보면 Stream이라는 데이터다. 여기서 Stream은 무엇일까? 

 

스트림이란 데이터 또는 이벤트가 오기까지 기다려야하는 상황에서 한개의 값을 기다리는 것이 아닌 여러 개의 값을 이동할 수 있는 통로이이다. 그리고 이벤트나 값이 입력으로 들어오게 되면 이를 인식하여 어떠한 동작을 발생할 수 있게 해준다. 옵저버 패턴을 이용한다고 한다. 

 

즉 저기서는 변한 메시지 정보를 Stream을 통해 클라이언트에게 전송해준다. 그리고 변경되었을 때 마다 스냅샷이 이를 인식하여 값을 알려주게 된다. 

 

 

스트림 만들어보기

void main(){
  Stream.value(30).listen((x)=>print('input Value $x'));
}

간단하게 value를 넘겨주어 스트림을 만들어주는 코드를 작성했다.

 

주기적인 시간마다 실행하는 Stream을 만들어 보겠다.

void main(){
  var stream = Stream.periodic(Duration(seconds:2), (x)=>x).take(5);
  stream.listen((x) => print(x));
}

주기적으로 각 2초마다 x의 값을 5까지 실행하는 기능을 제공하고 있다.  

 

또한 단순히 숫자 뿐만 아니라 List를 이용하여 Stream을 사용할 수도 있다. 

void main(){
  var stream = Stream.fromIterable(['상', '훈', '블로그', 'Dart']);
  stream.listen((x) => print(x));
}

 

 

스트림 컨트롤러 사용하기

import 'dart:async';

void main(){
  var streamController = StreamController();
  streamController.stream.listen((x) => print(x));
  
  streamController.add("문자열도 넣을 수 있어요");
  streamController.add(200);
  streamController.close();
}

 

함수 실행시키기

import 'dart:async';

void main(){
  var streamController = StreamController();
  streamController.stream.listen((x) => x());
  
  streamController.add((){
    print('함수도 넣을 수 있어요');
  });
  
//   streamController.add("문자열도 넣을 수 있어요");
//   streamController.add(200);
  streamController.close();
}

 

여러 개의 listen 사용하기

단순히 StreamController로 객체를 만들어주면 두개 이상의 Listen을 사용할 수 없다. 여러 개의 Listen을 사용하기 위해서는 broadcast를 사용하면 된다. 

 

import 'dart:async';

void main(){
  var streamController = StreamController.broadcast();
  
  streamController.stream.listen((x) => print('broadcast1 $x'));
  streamController.stream.listen((x) => print('broadcast2 $x'));
  
  streamController.add("문자열도 넣을 수 있어요");
  streamController.add(200);
  streamController.close();
}

StreamBuilder

스트림 빌더란 비동기적으로 계속해서 새로운 이벤트들을 잡아 낼 수 있는 위젯이다. 

StreamBuilder<QuerySnapshot>(
              stream: _firestore.collection('messeges').snapshots(),
              builder: (context, snapshot) {
                if (!snapshot.hasData) {
                  return Center(
                      child: CircularProgressIndicator(
                    backgroundColor: Colors.lightBlueAccent,
                  ));
                }

                final messages = snapshot.data.docs;
                List<Text> messageWidgets = [];

                for (var message in messages) {
                  final messageText = message.data()['text'];
                  final messageSender = message.data()['sender'];
                  final messageWidget =
                      Text('$messageText from $messageSender');
                  messageWidgets.add(messageWidget);
                }

                return Column(
                  children: messageWidgets,
                );
              },
            ),

코드를 설명해보면 stream을 지정하는데 _firestore.collection('messages').snapshots()으로 사용할 스냅샷을 지정해준다. builder의 snapshot은 snapshots들 중 한개씩 들어가게 된다. 

 

그리고 각 snapshots 들이 반환하는 값을 StreamBuilder의 반환 값으로 선택해주어야한다. 

'Flutter' 카테고리의 다른 글

Flutter Firebase 회원가입 및 로그인 하기  (0) 2021.01.26
Flutter Firebase 연동하기(ios, android)  (0) 2021.01.26
[Dart] Mixins  (0) 2021.01.25
[flash chat] animation  (0) 2021.01.25
[flash chat] static 구문  (0) 2021.01.25