고급
실생활 앱 (실시간 메모)
여러 기기에서 같은 메모 목록을 공유한다고 가정하고, 실시간 스트림 형태로 메모를 표시하는 앱을 만듭니다.
동작
실생활 앱 (실시간 메모) 실행 화면
실시간 메모
고급
동기화 실시간
나
팀원
공유됨
메모를 작성하면 공유 목록에 새 항목이 추가됩니다. 목록은 StreamBuilder로 구독해 바뀔 때마다 다시 표시합니다. 실제 서비스에서는 Firestore, Supabase, WebSocket 같은 실시간 백엔드와 연결할 수 있습니다.
예제 코드
실시간 메모
import 'dart:async';
import 'package:flutter/material.dart';
class SharedMemo {
const SharedMemo({required this.author, required this.text});
final String author;
final String text;
}
class RealtimeMemoApp extends StatefulWidget {
const RealtimeMemoApp({super.key});
@override
State<RealtimeMemoApp> createState() => _RealtimeMemoAppState();
}
class _RealtimeMemoAppState extends State<RealtimeMemoApp> {
final controller = TextEditingController(text: '회의 내용 정리');
final streamController = StreamController<List<SharedMemo>>.broadcast();
var memos = const [
SharedMemo(author: '나', text: 'Flutter Wiki 초안 작성'),
SharedMemo(author: '팀원', text: '배포 전 링크 확인'),
];
@override
void initState() {
super.initState();
streamController.add(memos);
}
void addMemo() {
final text = controller.text.trim();
if (text.isEmpty) return;
memos = [...memos, SharedMemo(author: '나', text: text)];
streamController.add(memos);
controller.clear();
}
@override
void dispose() {
streamController.close();
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(controller: controller),
ElevatedButton(onPressed: addMemo, child: const Text('공유')),
StreamBuilder<List<SharedMemo>>(
stream: streamController.stream,
initialData: memos,
builder: (context, snapshot) {
final items = snapshot.data ?? [];
return Column(
children: items.map((memo) {
return ListTile(
title: Text(memo.text),
subtitle: Text(memo.author),
);
}).toList(),
);
},
),
],
);
}
}
Card(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'프로젝트 보드',
style: TextStyle(fontSize: 22, fontWeight: FontWeight.w900),
),
const SizedBox(height: 16),
LinearProgressIndicator(value: progress),
const SizedBox(height: 12),
Row(
children: List.generate(3, (stage) {
return Expanded(child: Text(['할 일', '진행', '완료'][stage]));
}),
),
...cards.map((card) {
return OutlinedButton(
onPressed: () => moveCard(card),
child: Text(card.title),
);
})
],
),
),
)
실시간 메모
고급
동기화 실시간
나
팀원
공유됨
예제 코드 기능별 설명
코드를 나누어 읽기
import
dart:async은 StreamController를 사용하기 위해 필요합니다. material.dart는 입력창, 버튼, StreamBuilder, ListTile을 제공합니다.
import 'dart:async';
import 'package:flutter/material.dart';
SharedMemo 모델
SharedMemo는 작성자와 메모 내용을 묶은 데이터 클래스입니다. 실제 서비스에서는 여기에 작성 시간, 문서 id, 권한 정보가 추가됩니다.
class SharedMemo {
const SharedMemo({required this.author, required this.text});
final String author;
final String text;
}
실시간 스트림
StreamController는 예제에서 실시간 백엔드를 흉내 냅니다. 새 메모를 추가하면 같은 스트림을 구독 중인 UI가 최신 목록을 다시 받습니다.
final streamController = StreamController<List<SharedMemo>>.broadcast();
메모 추가 이벤트
메모를 추가한 뒤 streamController.add로 최신 목록을 흘려보냅니다. 실제 앱에서는 Firestore 문서 추가나 WebSocket 전송이 이 위치에 들어갑니다.
memos = [...memos, SharedMemo(author: '나', text: text)];
streamController.add(memos);
StreamBuilder
StreamBuilder는 데이터가 새로 들어올 때마다 builder를 다시 실행합니다. 실시간 메모, 채팅, 알림 목록처럼 계속 갱신되는 화면에 맞습니다.
StreamBuilder<List<SharedMemo>>(
stream: streamController.stream,
builder: (context, snapshot) => ...,
)