공부방 출석 알림 앱
목표
초등 공부방 태블릿에서 학생이 이름을 탭해 출석 체크하면, 담당 선생님의 SMS를 통해 학부모에게 자동 알림 발송.
현황
- 상태: active — 핵심 기능 구현 완료, 프로덕션 배포 직전 단계
- 코드베이스:
~/projects/gongbubang-app - 테스트: 41개 파일 (services 11 / screens 10 / repositories 7 / widgets 6 / models)
- 기술 스택: Flutter · Firebase (Firestore / Auth / FCM) · Google 로그인 · SMS (telephony, Android 전용)
아키텍처
Flutter App (태블릿 / 폰 이중 모드)
├── screens/
│ ├── login_screen.dart # Google 로그인
│ ├── role_selection_screen.dart # 태블릿 모드 / 폰 모드 선택
│ ├── attendance_check_screen.dart # 출석 체크 (Optimistic UI)
│ ├── phone_mode_screen.dart # 폰 모드 (SMS 발송 이력·템플릿 편집)
│ ├── attendance_history_screen.dart # 날짜별 출석 조회
│ ├── student_attendance_history_screen.dart
│ └── student_management_screen.dart # 학생 등록/수정/삭제
├── services/
│ ├── attendance_service.dart # 출석 체크 (CheckInResult sealed class)
│ ├── sms_service.dart # SMS 발송 + Firestore 로그
│ ├── sms_retry_policy.dart # 최대 3회 / 30초 간격 재시도
│ ├── fcm_service.dart # FCM 토큰 획득·갱신
│ ├── fcm_notification_service.dart
│ ├── notification_handler.dart # 백그라운드 FCM 핸들러 → SMS 자동 발송
│ ├── google_auth_service.dart # Google OAuth + Firestore teachers 저장
│ └── student_service.dart
├── repositories/
│ ├── student_repository.dart # CRUD + 실시간 Stream
│ ├── attendance_repository.dart # 출석 checkIn / 날짜별 조회
│ ├── teacher_repository.dart # FCM 토큰·SMS 템플릿 저장
│ └── sms_log_repository.dart # 발송 이력 (attempting/success/failed)
└── models/
├── student.dart / check_in_event.dart
├── sms_template.dart # {변수명} 플레이스홀더
├── sms_log.dart / attendance.dart
Firebase
├── Firestore: students / attendance / teachers / smsLog 컬렉션
└── FCM: 백그라운드 출석 알림 → 폰 모드 SMS 자동 발송
구현 현황 (Sub-AC 기준)
| 기능 | 구현 상태 | 비고 |
|---|---|---|
| Google 로그인 + Firebase Auth | ✅ 완료 | Firestore teachers 컬렉션 저장 |
| 역할 선택 (태블릿/폰 모드) | ✅ 완료 | FCM 토큰 획득 포함 |
| 출석 체크 화면 | ✅ 완료 | Optimistic UI, 실시간 Firestore 스트림 |
| 학생 등록/수정/삭제 | ✅ 완료 | 유효성 검사 포함 |
| SMS 발송 (Android) | ✅ 완료 | 재시도 3회, Firestore 이력 저장 |
| SMS 템플릿 편집 | ✅ 완료 | {변수명} 플레이스홀더 자동 추출 |
| SMS 발송 이력 조회 | ✅ 완료 | SmsLogListView |
| FCM 백그라운드 핸들러 | ✅ 완료 | @pragma('vm:entry-point') 처리 |
| 출석 이력 날짜별 조회 | ✅ 완료 | DatePickerWidget 연동 |
| 폰 모드 FCM 포그라운드 수신 | ✅ 완료 | 배너 표시 |
프로덕션 배포 전 체크리스트
main.dart 테스트 우회 코드 — 반드시 수정 후 배포
teacherId = 'test-teacher-001'하드코딩으로 실제 Google Auth 우회 중
-
lib/main.dart— 테스트 모드 고정 teacherId 제거, 실제 Google Auth 복원 - Firebase 설정 파일 추가
android/app/google-services.jsonios/GoogleService-Info.plistflutterfire configure실행
- Firestore 인덱스 배포 (
firestore.indexes.json확인 후firebase deploy --only firestore:indexes) - Firestore 보안 규칙 배포 (
firestore.rules— teacherId 스코핑 확인 후firebase deploy --only firestore:rules) - SMS 권한 거부 시 사용자 피드백 추가 (현재 silent failure)
- 실기기 테스트 — 태블릿(출석 체크) + Android 폰(SMS 발송) 동시 검증
- 실 공부방 dogfooding (1주)
기술 부채
| 항목 | 심각도 | 내용 |
|---|---|---|
| main.dart 테스트 우회 | 🔴 높음 | 배포 전 필수 수정 |
| SMS 권한 거부 silent failure | 🟡 중간 | 사용자 피드백 없음 |
| SMS/재시도 간격 하드코딩 | 🟢 낮음 | 60초 타임아웃·30초 간격 |
| Firestore 로컬 캐시 없음 | 🟢 낮음 | 실시간 동기화만 지원 |
다음 행동 (Next Actions)
-
lib/main.dart테스트 우회 코드 제거 - Firebase 설정 파일 추가 +
flutterfire configure실행 -
firebase deploy --only firestore(인덱스 + 보안 규칙) -
flutter test전체 41개 통과 확인 - 실기기 테스트 (태블릿 + Android 폰)
연관 노트
Projects
- mathflat-clone-service-plan — 같은 공부방 도메인. A+ Tracker의 출결 기능과 역할 중복. 장기 통합 가능성 검토
로그
| 날짜 | 내용 |
|---|---|
| 2026-05-16 | vault 프로젝트 문서 생성. 코드 분석 결과 핵심 기능 대부분 완료 확인. 프로덕션 배포 직전 상태. |