Field Log · Entry
조카에게 칭찬스티커 만들어주기 1: 초기 APK는 왜 한 기기에서만 됐을까?
기록 시점: 본문은 2026-08-04에 오프라인 체험판에서 온라인 가족 앱으로 넘어가며 정리한 단계입니다. 2026-09-08에 확인한 프로젝트 README에는 Supabase·FCM을 연결한 가족 파일럿
1.0.0 (4)배포가 기록되어 있습니다. 아래의 미완료 항목은 당시 상태이며, 설치 절차와 실제 가족 기기에서 관찰한 결과를 같은 것으로 보지 않습니다.
먼저 답부터
- 2026-08-04 초기
칭찬별APK에는 원격 Supabase 데이터베이스가 연결되어 있지 않다.- 그래서 당시 APK는 한 휴대폰에서 아이·엄마·이모·이모부 역할을 바꿔 보는 오프라인 체험판이다.
- 여러 휴대폰의 로그인·데이터 동기화·원격 알림에 필요한 코드는 구현하고 로컬 통합 테스트까지 했지만, 실제 Supabase·Expo·Firebase 계정 연결은 아직 남아 있다.
- DB 연결과 푸시 연결은 서로 다른 단계다. Supabase만 연결하면 동기화는 되지만, 앱이 꺼진 휴대폰에 알림을 보내려면 EAS projectId와 FCM V1 자격 증명도 필요하다.
이 시리즈는 “조카에게 칭찬스티커 앱을 만들어 주고 싶다”는 작은 가족 요구에서 출발한다. 아이는 오늘 할 일과 받을 스티커 수를 보고, 완료했거나 도움을 준 일을 보호자에게 알린다. 엄마·이모·이모부는 각자의 Android 휴대폰에서 확인한 뒤 스티커를 보낸다.
기능만 보면 간단한 체크리스트처럼 보이지만, 실제 앱이 되려면 네 가지 문제가 동시에 풀려야 했다.
- 아이에게 어렵지 않은 화면
- 보호자별 로그인과 승인 권한
- 여러 기기에서 같은 데이터를 보는 동기화
- 앱이 꺼져 있어도 도착하는 Android 원격 알림
첫 글에서는 구현한 범위와 아직 연결하지 않은 범위를 먼저 선명하게 나눈다. 이 구분이 없으면 “화면은 되는데 왜 엄마 폰에는 안 보이지?” 같은 혼란이 생긴다.
1. 요구사항을 기능이 아니라 가족의 대화로 바꾸기
처음 받은 요구를 사용자 흐름으로 다시 적었다.
아이의 흐름
- 오늘 반복할 루틴과 새로 들어온 할 일을 한 화면에서 본다.
- 각 할 일을 끝냈을 때 받을 스티커 수를 미리 본다.
- 일을 마치면 “다 했어요”라고 확인을 요청한다.
- 정해진 할 일 외에 도움을 줬다면 이유를 적고 엄마·이모·이모부 중 한 명을 선택해 칭찬을 요청한다.
- 승인되면 스티커 도착 알림을 받고 누적 스티커판을 확인한다.
- 브라우저에서 내려받은 이미지를 Android 사진 선택기로 가져와 스티커나 배경으로 쓴다.
보호자의 흐름
- 자기 이메일 계정으로 로그인한다.
- 아이의 완료 요청과 자신을 대상으로 한 칭찬 요청을 확인한다.
- 실제 상황을 확인한 뒤 승인하거나 보류한다.
- 당일 할 일과 매일 반복할 루틴을 만든다.
- 이유를 적어 스티커를 바로 보낼 수도 있다.
여기서 중요한 제품 원칙도 정했다. 감점, 스티커 회수, 가족 간 순위는 넣지 않았다. 보상을 통제와 비교의 도구로 만들기보다 “어떤 행동을 알아봐 줬는지” 남기는 쪽을 택했다.
2. 왜 웹페이지가 아니라 Android 앱으로 갔을까
처음 아이디어는 웹페이지였다. 그러나 원격 알림과 휴대폰 사진 선택, 홈 화면 접근성이 중요해지면서 Expo·React Native 기반 Android 앱이 더 자연스러웠다.
웹도 푸시 알림을 지원할 수 있지만 브라우저와 설치 방식에 따라 동작 차이가 생긴다. 이 가족은 모두 Android를 쓰기 때문에 한 플랫폼의 설치형 앱에 집중하는 편이 테스트 범위를 줄였다.
선택한 기술은 다음과 같다.
| 영역 | 선택 | 맡은 일 |
|---|---|---|
| 앱 | Expo SDK 57·React Native·TypeScript | 아이와 보호자 화면, 사진 선택, 알림 권한 |
| 로컬 체험 | AsyncStorage | 계정 없이 한 기기에서 역할 전환 |
| 온라인 데이터 | Supabase Auth·Postgres·Realtime | 로그인, 가족 데이터, 기기 간 동기화 |
| 이미지 | Supabase Private Storage | 가족별 스티커·배경 이미지 |
| 알림 생성 | Supabase Database Webhook·Edge Function | DB 이벤트를 푸시 요청으로 변환 |
| Android 전달 | Expo Push Service·Firebase Cloud Messaging | 앱이 백그라운드일 때 시스템 알림 전달 |
3. 현재 APK에서 되는 것과 안 되는 것
현재 배포한 APK는 환경 변수 없이 빌드했다. 앱은 Supabase 공개 URL과 publishable key가 없으면 자동으로 체험 모드를 선택한다.
| 항목 | 현재 체험 APK | 온라인 빌드 후 |
|---|---|---|
| 아이·엄마·이모·이모부 화면 | 가능 | 가능 |
| 할 일·루틴·승인·칭찬 요청 | 한 기기에서 가능 | 여러 기기에서 가능 |
| 앱 재시작 후 데이터 유지 | 해당 기기에서 가능 | Supabase에 유지 |
| 다운로드 이미지 꾸미기 | 해당 기기에 저장 | 가족 비공개 Storage에 저장 |
| 보호자 이메일 로그인 | 불가 | 가능 |
| 기기 간 실시간 동기화 | 불가 | 가능 |
| 다른 휴대폰 원격 알림 | 불가 | EAS·FCM 연결 후 가능 |
즉 “DB가 연결되어 있지 않은가?”라는 질문의 답은 현재 APK에는 그렇다이다. 다만 DB 스키마와 앱 연결 코드는 없는 것이 아니라, 외부 프로젝트에 배포되기 전 상태다.
4. 화면보다 먼저 지킨 데이터 규칙
가족 앱이라도 권한 경계는 필요하다. 특히 아이가 보상을 직접 늘리거나 다른 가족의 사진을 읽을 수 있어서는 안 된다.
이번 구현에서는 다음 규칙을 DB 레벨에 두었다.
- 모든 앱 테이블에 Row Level Security를 켠다.
- 사용자는 자기 가족의 행만 읽는다.
- 아이 계정은 완료 요청과 칭찬 요청을 만들 수 있지만 스티커 원장에 직접 쓰지 못한다.
- 보호자 승인 함수만 양수 스티커를 기록한다.
- 같은 요청을 두 번 승인해도 고유
source_key때문에 한 번만 지급한다. - 특정 이모에게 보낸 요청은 엄마나 이모부가 승인하지 못한다.
- 꾸미기 이미지는 비공개 버킷에 저장하고 가족·소유자 경로를 검사한다.
이 규칙은 화면 버튼을 숨기는 것보다 강하다. 조작된 API 요청이 들어와도 DB가 거부하기 때문이다.
5. 무엇을 실제로 검증했나
온라인 계정 연결 전에도 로컬 Supabase 스택으로 실제 API 흐름을 검증할 수 있었다.
- 엄마 계정이 가족을 만들고 이모 계정이 초대 코드로 참여
- 이메일이 없는 아이가 익명 계정과 일회용 코드로 기기 연결
- 새 할 일 생성 → 완료 요청 → 보호자 승인 → 스티커 1회 지급
- 이모 대상 칭찬 요청 → 엄마 승인 거부 → 이모 승인 성공
- 두 번째 가족이 첫 번째 가족의 데이터와 이미지에 접근하지 못함
- 비공개 이미지 업로드와 signed URL 조회
- 잘못된 푸시 Webhook 비밀 헤더 401, 올바른 헤더 200
- Android 15 에뮬레이터에서 릴리스 APK와 시스템 사진 선택기 확인
여기서 검증한 것은 코드와 로컬 보안 경계다. 실제 엄마·이모·이모부·아이 휴대폰에서의 백그라운드 알림은 외부 서비스 연결 후 별도로 확인해야 한다. 계획과 완료를 섞지 않는 것이 이 프로젝트의 첫 번째 교훈이었다.
6. DB와 푸시는 왜 따로 연결해야 할까
데이터 흐름과 푸시 흐름을 분리하면 구조가 보인다.
[데이터 동기화]
Android 앱 → Supabase Auth/RLS → Postgres/Realtime → 다른 Android 앱
[백그라운드 알림]
Postgres INSERT → Database Webhook → Edge Function
→ Expo Push Service → FCM V1 → Android 시스템 알림
Supabase 연결만 끝내도 앱을 열어 둔 기기들은 Realtime으로 바뀐 데이터를 받을 수 있다. 하지만 앱이 닫힌 휴대폰을 깨우는 일은 Android의 푸시 인프라가 맡는다. 이때 Expo 프로젝트와 Firebase 발송 권한이 추가로 필요하다.
7. 남은 작업을 순서로 고정하기
다음 순서로 진행하면 실패 지점을 좁히기 쉽다.
- Supabase 원격 프로젝트를 만든다.
- migration과 Edge Function을 배포한다.
- Auth, Anonymous Sign-ins, Database Webhook을 설정한다.
- 앱에 Supabase 공개 URL과 publishable key를 넣고 두 기기 동기화를 먼저 확인한다.
- EAS 프로젝트를 만들고
projectId를 앱에 연결한다. - Firebase Android 앱과 FCM V1 서비스 계정 키를 EAS에 연결한다.
- 온라인 preview APK를 새로 빌드한다.
- 네 대의 실제 Android에서 알림 파일럿을 한다.
다음 글 Supabase로 가족 DB 연결하기에서는 1~4단계를 실제 명령과 Dashboard 설정 순서로 진행한다.
참고자료
- Supabase React Native Auth 공식 가이드
- Supabase Anonymous Sign-Ins 공식 가이드
- Expo Push Notifications 설정 가이드
- 프로젝트 내부 검증 근거:
praise-sticker/README.md,docs/PRODUCT_SPEC.md,docs/ARCHITECTURE.md,next.yml(2026-08-04 확인)
Reader questions
읽으며 남긴 질문
글을 읽으며 붙잡아 둔 질문입니다. 다시 살펴보거나, 보내지 않은 질문을 한 번에 블로그 주인에게 전달할 수 있습니다.