Field Log · Entry
조카에게 칭찬스티커 만들어주기 4: 네 대의 Android로 가족 파일럿하기
기록 시점: 본문은 2026-08-04에 오프라인 체험판에서 온라인 가족 앱으로 넘어가며 정리한 단계입니다. 2026-09-08에 확인한 프로젝트 README에는 Supabase·FCM을 연결한 가족 파일럿
1.0.0 (4)배포가 기록되어 있습니다. 아래의 미완료 항목은 당시 상태이며, 설치 절차와 실제 가족 기기에서 관찰한 결과를 같은 것으로 보지 않습니다.
파일럿의 목표
- “알림이 한 번 왔다”가 아니라 새 할 일·완료 요청·대상 지정 칭찬 요청·승인 알림이 올바른 사람에게 도착하는지 확인한다.
- 화면 동기화와 시스템 푸시를 분리해서 검사한다.
- 앱을 연 상태뿐 아니라 백그라운드·화면 잠금·절전 모드에서도 관찰한다.
- 실패했을 때 DB, Webhook, Expo ticket, FCM receipt, Android 권한 중 어디서 멈췄는지 기록한다.
3편까지 따라왔다면 Supabase와 EAS·FCM이 연결된 preview APK가 준비되어 있다. 마지막 단계는 실제 가족 기기에서 제품 흐름을 확인하는 일이다.
자동 테스트가 통과해도 가족이 실제로 쓰는 상황은 다르다. 제조사별 절전 정책, 알림 권한, 네트워크 전환, 아이가 이해하기 어려운 문구는 에뮬레이터만으로 발견하기 어렵다.
1. 시작 조건
파일럿 전에 아래 항목을 모두 확인한다.
- Supabase 원격 migration이 적용됨
- Email Auth와 Anonymous Sign-ins가 켜짐
pushEdge Function과 Database Webhook이 배포됨- EAS projectId가
app.json에 있음 - Firebase Android 앱의 package가
com.ruahverce.praisestar와 일치함 - EAS에 FCM V1 서비스 계정 키가 등록됨
- preview EAS 환경에 Supabase URL과 publishable key가 있음
- 같은 온라인 preview APK를 네 기기에 설치함
- 네 기기 모두 Android 알림 권한을 허용함
기존 오프라인 APK와 온라인 APK가 같은 package와 다른 서명으로 만들어졌다면 설치가 충돌할 수 있다. 파일럿 전에 체험판 데이터를 초기화하고 필요하면 기존 앱을 제거한 뒤 온라인 빌드를 설치한다.
2. 사람과 기기 표 만들기
실명과 이메일을 공개 문서에 남기지 않는다. 로컬 파일럿 노트에는 참조 이름만 쓴다.
| 참조 | 역할 | 확인할 알림 |
|---|---|---|
device-child | 아이 | 새 할 일, 스티커 도착, 보류 결과 |
device-mother | 엄마 | 완료 요청, 엄마 대상 칭찬 요청 |
device-aunt | 이모 | 완료 요청, 이모 대상 칭찬 요청 |
device-uncle | 이모부 | 완료 요청, 이모부 대상 칭찬 요청 |
기기별로 Android 버전, 제조사, 알림 권한, 배터리 최적화 상태만 기록한다. 가족 실명, 이메일, 이미지 원본은 테스트 보고서에 복사하지 않는다.
3. 가족 온보딩부터 검증하기
첫 보호자
- 엄마 기기에서 이메일 계정을 만든다.
- 새 가족 공간을 만들고 아이 별명을 등록한다.
- 7일짜리 보호자 초대 코드를 만든다.
다른 보호자
- 이모와 이모부가 각자 이메일 계정으로 로그인한다.
- 12자리 가족 초대 코드로 참여한다.
- 역할과 표시 이름이 각 기기에서 맞는지 확인한다.
아이 기기
- 보호자가 30분짜리 8자리 아이 기기 코드를 만든다.
- 아이 기기에서 익명 로그인과 코드 연결을 진행한다.
- 아이 화면에 보호자용 관리 기능이 보이지 않는지 확인한다.
새 아이 기기 코드를 사용하면 이전 아이 계정의 연결이 해제되도록 설계했다. 기기 교체 테스트를 할 때는 이 동작도 확인한다.
4. 첫 30분 종단 테스트
다음 시나리오는 데이터와 알림 수신자를 동시에 검증한다.
시나리오 A: 새 할 일
- 엄마가 “책가방 정리” 할 일을 만들고 보상 2개를 설정한다.
- 아이 기기의 앱을 닫고 화면을 잠근다.
- 아이 기기에 새 할 일 알림이 오는지 확인한다.
- 앱을 열어 제목과 보상 2개가 보이는지 확인한다.
통과 조건은 “푸시가 왔다”와 “DB에서 올바른 할 일을 읽었다” 두 가지다.
시나리오 B: 완료 요청과 승인
- 아이가 “다 했어요”를 누른다.
- 세 보호자에게 완료 요청 알림이 오는지 확인한다.
- 이모가 승인한다.
- 아이에게 스티커 2개 도착 알림이 오는지 확인한다.
- 같은 승인 버튼을 다시 눌러도 원장이 두 번 늘지 않는지 확인한다.
시나리오 C: 대상 지정 칭찬 요청
- 아이가 “식탁 정리를 도왔어요”라고 적는다.
- 요청 대상을 이모부로 선택한다.
- 엄마와 이모에게 해당 대상 알림이 가지 않는지 확인한다.
- 엄마 계정으로 승인할 수 없는지 확인한다.
- 이모부가 승인했을 때만 아이의 스티커가 늘어나는지 확인한다.
“오지 않아야 할 사람에게 오지 않는 것”도 중요한 성공 조건이다.
시나리오 D: 꾸미기 이미지
- 아이 기기에서 가족용 테스트 이미지를 스티커로 가져온다.
- 다른 가족 기기에서도 같은 스티커가 보이는지 확인한다.
- 앱을 재시작한 뒤 테마가 유지되는지 확인한다.
- Supabase Storage bucket이 public으로 노출되지 않았는지 확인한다.
5. 데이터 동기화와 푸시를 분리해 진단하기
| 관찰 | 해석 | 다음 확인 |
|---|---|---|
| 앱을 열면 데이터는 보이지만 시스템 알림이 안 옴 | Supabase는 연결, 푸시 경로 문제 | token·Webhook·EAS·FCM·Android 권한 |
| 데이터 자체가 다른 기기에 안 보임 | Auth/RLS/Realtime 또는 잘못된 Supabase 환경 | 세션, project URL, member 연결, DB 로그 |
| Expo 테스트 도구 알림은 옴, 앱 이벤트 알림은 안 옴 | FCM은 정상, 서버 이벤트 경로 문제 | app_notifications, Webhook, Edge Function 로그 |
Webhook 200, no_registered_device | 수신자 push token 없음 | 알림 권한 후 push_devices 등록 |
MismatchSenderId | Firebase 설정끼리 다른 프로젝트 | FCM key와 google-services.json의 sender 일치 |
DeviceNotRegistered | 앱 삭제·재설치 등으로 토큰 무효 | 해당 토큰 제거 후 새 토큰 등록 |
Expo는 push ticket과 push receipt를 구분한다. ticket은 Expo가 요청을 접수한 결과이고, receipt는 FCM 같은 하위 푸시 서비스에 전달한 결과다. “HTTP 200을 받았다”만으로 휴대폰 도착을 확정할 수 없다.
6. Android에서 꼭 확인할 상태
앱 상태
- 앱이 화면에 열린 상태
- 홈 화면으로 나간 백그라운드 상태
- 화면 잠금 상태
- 앱을 강제 종료한 뒤 상태
- 휴대폰 재부팅 이후
네트워크와 전원
- Wi-Fi
- 모바일 데이터
- Wi-Fi에서 모바일 데이터로 전환
- 배터리 절약 모드
- 제조사별 앱 절전 예외 전후
고우선순위 푸시라도 Android 제조사와 사용자의 전원 설정에 따라 지연될 수 있다. 알림을 중요한 안전 경보처럼 절대 전달 보장 수단으로 사용하면 안 된다. 칭찬별은 DB의 앱 알림함을 원본으로 두어 푸시를 놓쳐도 앱을 열면 기록을 확인할 수 있게 했다.
다음 표는 아직 채우지 않은 관찰 양식입니다. 빌드 배포, Expo ticket 접수, push receipt, 실제 기기의 표시/수신자 확인은 따로 기록합니다. 가족의 실명·이메일·기기 token을 공개하지 않고 기기 별칭·Android 버전·앱 빌드·상태·예상/관측 결과만 남깁니다. 파일럿 배포가 완료됐다는 사실을 일주일 사용성·알림 전달 성공률까지 검증했다는 뜻으로 확장하지 않습니다.
7. 일주일 파일럿 기록표
첫날 종단 테스트가 통과하면 실제 생활에서 1주일 관찰한다.
| 날짜 | 이벤트 | 앱 내부 기록 | 시스템 알림 | 지연 | 문구 이해 | 비고 |
|---|---|---|---|---|---|---|
| Day 1 | 새 할 일 | O/X | O/X | 초·분 | 쉬움/어려움 | 권한 상태 |
| Day 2 | 완료 요청 | O/X | O/X | 초·분 | 쉬움/어려움 | 보호자 3명 |
| Day 3 | 대상 칭찬 | O/X | O/X | 초·분 | 쉬움/어려움 | 오수신 여부 |
| Day 4~7 | 반복 사용 | O/X | O/X | 초·분 | 쉬움/어려움 | 알림 피로도 |
측정하려는 것은 기술 성공률만이 아니다.
- 아이가 보상 수를 이해하는가
- 완료 요청과 칭찬 요청을 구분하는가
- 보호자는 어떤 요청을 누가 처리했는지 이해하는가
- 알림 빈도가 부담스럽지 않은가
- 스티커 꾸미기가 계속 쓸 동기를 주는가
8. 파일럿 중 지켜야 할 안전선
- 스티커를 회수하거나 벌점으로 쓰지 않는다.
- 가족 간 순위를 만들지 않는다.
- 사진에는 가족이 동의한 이미지나 사용 권한이 있는 이미지만 쓴다.
- service account key, Supabase secret key, DB 비밀번호를 화면 캡처나 메신저로 공유하지 않는다.
- 기기 분실 시 아이 기기 링크를 새로 발급하고 이전 계정 접근이 끊겼는지 확인한다.
- 장기 사용 전 이미지 삭제, 가족 탈퇴, 계정 삭제와 개인정보 안내 흐름을 추가한다.
9. 파일럿이 끝났다고 판단하는 기준
다음 조건이 모두 만족되면 가족 내부 온라인 MVP가 준비된 것으로 본다.
- 네 역할이 각자의 기기에서 올바른 화면을 본다.
- 새 할 일과 승인 결과가 데이터 손실 없이 동기화된다.
- 완료 요청은 한 번만 보상으로 기록된다.
- 대상 지정 요청은 선택된 보호자만 승인한다.
- 앱이 백그라운드일 때 주요 알림이 실제 기기에 도착한다.
- 실패한 push receipt와 무효 토큰을 찾을 수 있다.
- 다른 가족 데이터와 이미지를 읽을 수 없다.
- 아이와 보호자가 문구와 동선을 이해한다.
Play Store 배포는 그다음 문제다. 현재 체험 APK는 디버그 인증서로 서명되어 있으므로, 파일럿 후 가족 내부 APK를 계속 쓸지 Play Store 비공개 테스트로 옮길지 결정하고 영구 release signing과 업데이트 경로를 준비해야 한다.
10. 이 작은 앱에서 얻은 설계 교훈
칭찬스티커 앱은 단순한 CRUD 예제보다 많은 경계를 드러냈다.
- 로그인 성공과 역할 권한은 다르다.
- DB 동기화 성공과 푸시 성공은 다르다.
- 알림 전송 성공과 사용자 도착은 다르다.
- 비공개 버킷과 안전한 파일 접근 정책은 다르다.
- 화면에서 버튼을 숨기는 것과 서버에서 행위를 금지하는 것은 다르다.
- 에뮬레이터 통과와 가족이 실제로 이해하는 제품은 다르다.
그래서 이 시리즈의 완성은 “앱을 빌드했다”가 아니라, 완료된 것과 아직 검증하지 않은 것을 구분하고 실제 가족 환경에서 하나씩 닫아 가는 과정이다.
참고자료
- Expo: Push notifications troubleshooting and FAQ
- Expo: Send notifications with the Expo Push Service
- Expo: Push notifications setup
- Supabase: Database Webhooks
- Firebase: FCM HTTP V1
- 프로젝트 내부 검증 근거:
praise-sticker/docs/ARCHITECTURE.md,scripts/test-local-cloud.mjs, Android 15 에뮬레이터 캡처와 arm64 APK 검사 기록
Reader questions
읽으며 남긴 질문
글을 읽으며 붙잡아 둔 질문입니다. 다시 살펴보거나, 보내지 않은 질문을 한 번에 블로그 주인에게 전달할 수 있습니다.