Firebase 기반 팀 협업 실험실. 로그인한 사용자가 소속된 그룹을 생성하고 목록을 조회할 수 있도록 기본 데이터 모델과 UI를 제공합니다.
groups/{groupId}:{ id, name, createdBy, createdAt }id: 문서 키를 그대로 저장해두면 다른 화면에서 접근하기 편합니다.createdAt:FieldValue.serverTimestamp()로 저장되며, 앱에서는DateTime?으로 변환합니다.
groupMembers/{groupId_userId}:{ groupId, userId, role }- 복합 키(
groupId_userId) 덕분에 Firestore 규칙에서exists()체크로 멤버 여부를 판별할 수 있습니다. role은owner또는member중 하나입니다.
- 복합 키(
projects/{projectId}:{ groupId, name, description, status, createdAt, createdBy }status는"ACTIVE"또는"ARCHIVED"중 하나이며 기본값은"ACTIVE"입니다.createdAt은FieldValue.serverTimestamp()로 기록하고, 앱에서는DateTime?으로 변환합니다.groupId는 상위 그룹 문서 ID,createdBy는 작성자 UID입니다.
tasks/{taskId}:{ projectId, title, description, assigneeId, dueDate, status, priority, createdAt, createdBy }status:"TODO" | "DOING" | "DONE", 기본값"TODO".priority:"LOW" | "MEDIUM" | "HIGH", 기본값"MEDIUM".dueDate는 null 허용 Timestamp,projectId는 프로젝트 문서 ID (또는 임시 groupId).- 하위에
subtasks/{subtaskId}서브컬렉션을 두고{ title, isDone, createdAt }구조로 체크리스트를 유지합니다.
Firestore 콘솔에서 테스트 데이터를 만들려면 projects 컬렉션을 생성한 후, 문서 ID(testProject1 등)를 지정하고 위 필드를 채우면 됩니다. 실제 앱에서는 serverTimestamp()를 사용하지만, 테스트용으로 아무 Timestamp나 입력해도 됩니다.
Flutter/Dart 타입은 lib/models/group.dart에 정의되어 있으며 다른 스택에서도 그대로 매핑하면 됩니다.
GroupStore(lib/state/group_store.dart)- 로그인 상태를 구독하여 자동으로
getMyGroups호출. createGroup(name)→groups에 문서 작성 →groupMembers에 owner 등록 → 리스트 갱신.addMemberToGroup(group, memberUserId)→ owner만 호출 가능, 해당 UID를 member 역할로 연결.
- 로그인 상태를 구독하여 자동으로
GroupsPageGroupStore를 구독해 실시간으로 목록을 표시하고, 다이얼로그로 그룹을 생성합니다.- 각 카드에서
멤버 추가버튼으로 Firebase UID 기반 직접 초대, 당겨서 새로고침 및 오류 메시지 UI 포함.
GroupSidebar- 모든 로그인 화면 왼쪽(대화면) 또는 Drawer(소화면)에 현재 사용자의 최근 그룹 10개를 노출해 빠르게 이동할 수 있습니다.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isSignedIn() {
return request.auth != null;
}
function isGroupMember(groupId) {
return isSignedIn() && exists(
/databases/$(database)/documents/groupMembers/$(groupId + '_' + request.auth.uid)
);
}
match /groupMembers/{memberId} {
allow read: if isSignedIn() && resource.data.userId == request.auth.uid;
allow create, update, delete: if isSignedIn()
&& request.resource.data.userId == request.auth.uid;
}
match /groups/{groupId} {
allow read, write: if isGroupMember(groupId);
}
}
}
Firebase 프로젝트 설정을 마친 뒤 flutter pub get과 flutter run으로 앱을 실행하면 로그인 → 그룹 생성 → 목록 조회까지의 기본 플로우를 확인할 수 있습니다.