Skip to content
wys1110Public

About

[앱] 가족 일정과 육아·성장 기록을 함께 관리하는 웹앱

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

858 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

우리 가족 캘린더

가족 일정을 한눈에 보고 함께 관리하는 모바일 중심 캘린더입니다.

지금 바로 실행

별도 설정 없이 열면 브라우저의 로컬 저장소에 일정이 저장됩니다.

python3 -m http.server 8774

브라우저에서 http://localhost:8774을 엽니다.

테스트 로그인

로그인 화면의 테스트 모드로 둘러보기를 누르거나 주소 뒤에 ?demo=1을 붙이면 가상 가족 데이터로 앱 전체를 확인할 수 있습니다.

http://localhost:8774/?demo=1
https://wys1110.github.io/family/?demo=1

테스트 모드에서는 Supabase 클라이언트를 생성하지 않으므로 실제 가족 DB를 읽거나 수정하지 않습니다. 일정·성장 기록·아기 프로필은 family-demo-* 전용 로컬 저장 키에만 보관됩니다. 상단의 테스트 종료를 누르면 실제 로그인 화면으로 돌아가며, 계정 팝업의 가상 데이터 초기화로 기본 샘플을 다시 만들 수 있습니다.

Supabase 연결

  1. Supabase 프로젝트를 생성합니다.
  2. SQL Editor에서 supabase/schema.sql을 실행합니다.
  3. config.example.js를 복사해 config.js를 만들고 Project URL과 anon key를 입력합니다.
  4. Supabase Authentication의 URL Configuration에 로컬 주소와 GitHub Pages 주소를 Redirect URL로 추가합니다.
window.FAMILY_CONFIG = {
  supabaseUrl: "https://YOUR_PROJECT.supabase.co",
  supabaseAnonKey: "YOUR_ANON_KEY",
  kakaoMapsJavaScriptKey: "YOUR_KAKAO_JAVASCRIPT_KEY",
};

anon key는 브라우저용 공개 키이며, 실제 데이터 보호는 schema.sql의 Row Level Security 정책이 담당합니다. service_role 키는 절대 넣지 마세요.

카카오 지도 설정

여행 지도는 카카오맵 Web JavaScript SDK를 사용합니다. 카카오 개발자 앱 우리 가족 (ID 1604339)의 JavaScript 키를 config.js의 FAMILY_CONFIG.kakaoMapsJavaScriptKey에 넣고, 앱 설정의 Web 플랫폼에 다음 JavaScript 출처를 등록합니다.

  • 공개 웹: https://wys1110.github.io
  • 로컬 미리보기: http://localhost:8774
  • Capacitor WebView 출처: https://localhost

출처는 경로 없이 origin만 등록합니다. JavaScript 키는 브라우저 지도용 공개 키로 config.js에 설정하지만, REST 키는 브라우저에 넣지 않습니다. 지도가 표시되지 않으면 등록된 origin, Web 플랫폼, JavaScript 키를 확인합니다. 카카오맵 Web API 안내

카카오 지도는 대한민국 지도 사용을 기준으로 합니다. 해외 지역의 상세 지도 지원은 제한적이며 일본을 포함한 해외 지도를 지원한다고 가정하지 않습니다. https://localhost 설정의 Android 기기 동작은 아직 실제 기기에서 확인되지 않았습니다.

로그인은 됐는데 가족 데이터가 안 보일 때

로그인 화면은 사라졌지만 가족 일정·성장 기록이 비어 있고, 브라우저 로그에 JWT issued at future, PGRST303 또는 인증 요청 401이 반복되면 세션 자체보다 Supabase Data API가 JWT를 거부하는 상태일 수 있습니다.

다음 순서로 복구합니다.

  1. Supabase Dashboard에서 가족 앱 프로젝트를 엽니다.
  2. Project Settings → General → Restart project를 선택하고 확인합니다.
  3. 프로젝트 상태가 ACTIVE_HEALTHY가 될 때까지 기다립니다. 재시작 중 521·503은 일시적인 정상 현상입니다.
  4. 앱을 완전히 닫았다가 다시 열고 새로고침합니다. 앱도 데이터 로딩 오류를 약 44초 동안 자동 재시도합니다.
  5. 가족 데이터가 표시되는지 확인합니다.

Pause project, Delete project, 데이터베이스 초기화는 선택하지 않습니다. 재시작 후에도 401 또는 PGRST303이 계속되면 Supabase Logs → API에서 발생 시각과 요청 경로를 확인해 Supabase 지원팀에 문의합니다. 액세스 토큰·리프레시 토큰은 로그나 채팅에 붙여 넣지 않습니다.

GitHub Pages

main 브랜치에 반영되면 .github/workflows/pages.yml이 정적 사이트를 자동 배포합니다. 저장소의 Settings → Pages → Source가 GitHub Actions로 설정되어 있어야 합니다.

Android 앱

기존 PWA를 Capacitor Android 앱으로도 패키징할 수 있습니다. Android Studio와 SDK가 설치된 환경에서 npm run android:open을 실행하고, 디버그 APK는 npm run android:debug로 생성합니다. 패키지 ID와 Play 스토어 출시 절차는 docs/android/ANDROID_DEPLOYMENT.md에 정리되어 있습니다. main 변경 시 GitHub Actions가 디버그 APK 아티팩트도 빌드합니다.

Google 로그인 설정

  1. Google Cloud에서 OAuth 2.0 Client ID를 Web application으로 생성합니다.
  2. Authorized JavaScript origins에 https://wys1110.github.io를 추가합니다.
  3. Authorized redirect URI에 https://ljutcgmgtqfkwkxdbiyb.supabase.co/auth/v1/callback을 추가합니다.
  4. Supabase Authentication → Providers → Google에서 Google Client ID와 Client Secret을 입력하고 활성화합니다.

Google Client Secret은 Supabase에만 입력하고 저장소에는 커밋하지 않습니다. 자세한 내용은 Supabase Google 로그인 공식 문서를 참고하세요.

주요 기능

  • 월간 달력 및 오늘 일정
  • 일정 추가·수정·삭제, 시작일–종료일 범위 지정 및 최대 50개 일괄 입력
  • 캘린더 안 가족 할 일(오늘·예정·완료, 담당자, 마감일, 반복, 날짜별 표시)
  • 아빠·엄마·도윤 구성원별 표시
  • 브라우저 로컬 저장
  • Supabase 이메일 로그인 및 가족 초대 코드
  • Google 소셜 로그인
  • 가족 단위 RLS 데이터 보호
  • 도윤이 성장일기(첫 순간, 성장, 수유, 수면, 기저귀, 건강·병원, 놀이)
  • 시간과 유형별 수치 기록(키, 몸무게, 머리둘레, 수유량, 수면시간, 체온)
  • 기록당 사진 최대 4장 업로드(비공개 Supabase Storage, 가족 구성원 전용)
  • 여러 아기 프로필과 태어난 날 기준 D-day·생후 일수
  • 수유·수면·기저귀 원터치 기록과 오늘 요약
  • 최근 성장 측정 및 비공개 사진 타임라인
  • 로그인 계정 본인만 접근할 수 있는 나만의 공간(일기·기도·생각·메모)
  • 아기에게 들려주는 창작 영어동화 7편과 한글 뜻
  • 영어동화 전체·문장별 음성 재생, 느린 속도, 오늘의 동화 완료 표시
  • 가족 구성원 기능 요청 DB 저장과 가족 관리자 전용 조회·상태 관리
  • 가족 공동 아기 특징·부모 생활 패턴과 최근 7일 기록을 반영하는 AI 육아 질문·수유·수면 전략
  • 매일 지정 시각에 오늘 일정을 보내는 홈 화면 앱 푸시 브리핑

영어동화는 브라우저의 영어 음성 읽기 기능을 사용하며 별도 DB 설정 없이 바로 동작합니다. 완료 표시는 현재 기기의 로그인 계정별 로컬 저장소에 보관됩니다.

이미 초기 스키마를 적용한 프로젝트에서 성장일기를 추가하려면 SQL Editor에서 supabase/migrations/20260714_growth_diary.sql을 한 번 실행합니다.

기존 성장일기에 상세 기록과 사진 업로드를 추가하려면 SQL Editor에서 supabase/migrations/20260715_growth_records_and_photos.sql을 한 번 실행합니다. 이 마이그레이션은 비공개 growth-photos 버킷과 가족 단위 Storage RLS 정책도 함께 만듭니다.

일정·성장 카드에 가족 공용 사진 월페이퍼를 사용하려면 supabase/migrations/20260810005856_household_wallpapers.sql을 실행합니다. 월페이퍼는 가족 공간별·카드별로 한 장만 저장되며 가족 관리자가 변경 또는 삭제할 수 있습니다.

아기 프로필, 생후 일수, 원터치 수유 기록을 추가하려면 supabase/migrations/20260715_baby_profiles_and_quick_logs.sql을 SQL Editor에서 한 번 실행합니다.

아기 프로필을 기록·사진 삭제 없이 아카이브하고 복원하려면 supabase/migrations/20260717_archive_baby_profiles.sql을 SQL Editor에서 한 번 실행합니다.

기존 일정에 날짜 범위를 추가하려면 SQL Editor에서 supabase/migrations/20260715_event_date_ranges.sql을 한 번 실행합니다. 기존 일정의 종료일은 시작일과 동일하게 자동 설정됩니다.

가족 구성원 추가와 구성원별 일정 색상을 사용하려면 supabase/migrations/20260715_family_calendar_members.sql을 SQL Editor에서 한 번 실행합니다. 기존 가족 공간에는 가족·아빠·엄마·도윤이 자동 등록되며, 이후 추가한 구성원은 가족 모두에게 공유됩니다.

개인 전용 나만의 공간을 사용하려면 SQL Editor에서 supabase/migrations/20260716_private_space.sql을 한 번 실행합니다. 이 테이블은 auth.uid() = owner_id RLS 정책으로 로그인한 본인에게만 읽기·쓰기·수정·삭제를 허용합니다.

기능 요청을 Supabase DB에 저장하고 가족 관리자만 조회·상태 변경하도록 하려면 supabase/migrations/20260716_feature_requests.sql을 SQL Editor에서 한 번 실행합니다. 일반 가족 구성원은 요청 등록만 가능하며 목록 조회 권한은 없습니다.

가족 할 일을 모든 가족 기기에서 공유하려면 supabase/migrations/20260716_family_todos.sql을 SQL Editor에서 한 번 실행합니다. 이어서 supabase/migrations/20260811000000_private_family_todos.sql을 적용하면 기존 항목은 가족 할 일로 유지되고, 새 내 할 일은 작성자만 조회·수정·삭제할 수 있습니다. 적용 전에도 기능은 동작하지만 현재 기기의 로컬 저장소에만 임시 저장됩니다.

매일 일정 브리핑 앱 알림 배포

브라우저가 닫혀 있어도 오전 9시에 알림을 받으려면 Web Push용 Edge Function과 Cron을 한 번 배포해야 합니다. iPhone은 iOS 16.4 이상에서 사이트를 홈 화면에 추가한 앱으로 실행해야 푸시 권한을 요청할 수 있습니다.

  1. SQL Editor에서 supabase/migrations/20260719_daily_briefing_push.sql을 실행합니다.

  2. VAPID 키를 한 번 생성합니다.

    npx web-push generate-vapid-keys
  3. Git에 포함되지 않는 supabase/.env.push 파일에 아래 값을 저장합니다.

    DAILY_BRIEFING_VAPID_SUBJECT=mailto:관리자_이메일
    DAILY_BRIEFING_VAPID_PUBLIC_KEY=생성된_공개키
    DAILY_BRIEFING_VAPID_PRIVATE_KEY=생성된_비밀키
    DAILY_BRIEFING_CRON_SECRET=충분히_긴_무작위_문자열
  4. 비밀값과 Edge Function을 배포합니다.

    export SUPABASE_PROJECT_ID="프로젝트-ref"
    supabase secrets set --env-file ./supabase/.env.push --project-ref "$SUPABASE_PROJECT_ID"
    supabase functions deploy daily-briefing-push --project-ref "$SUPABASE_PROJECT_ID"
  5. Supabase Database → Vault에 아래 이름으로 값을 등록합니다.

    • daily_briefing_project_url: Supabase Project URL
    • daily_briefing_publishable_key: 브라우저용 publishable key 또는 anon key
    • daily_briefing_cron_secret: DAILY_BRIEFING_CRON_SECRET과 같은 값
  6. SQL Editor에서 supabase/daily-briefing-cron.sql을 실행합니다.

  7. iPhone에서 Safari 공유 버튼 → 홈 화면에 추가 → 앱 아이콘으로 실행 → 설정 → 아침 일정 브리핑 → 앱 알림 켜기를 누릅니다. 기본 시간은 오전 9시이며 테스트 알림으로 즉시 확인할 수 있습니다.

확인은 Edge Function 로그와 아래 쿼리로 합니다.

select jobname, schedule, active from cron.job where jobname = 'daily-briefing-push-every-5-minutes';
select enabled, timezone, briefing_time, last_sent_on, last_error from public.push_subscriptions order by updated_at desc;

VAPID 비밀키와 Cron 비밀값은 저장소, 브라우저 코드, 이슈 또는 채팅에 넣지 마세요.

AI 육아 도우미 배포

AI 기능은 브라우저에서 Gemini를 직접 호출하지 않습니다. 로그인 사용자는 Supabase Edge Function을 호출하며 GEMINI_API_KEY와 예약 작업용 BABY_AI_CRON_SECRET은 Supabase Function Secret으로만 보관합니다. 일반 질문은 DB에 저장하지 않고, 가족이 확정한 수유·수면 전략만 공동 저장합니다.

  1. Supabase SQL Editor에서 supabase/migrations/20260719_baby_ai_assistant.sql을 실행합니다.

  2. Git에 포함되지 않는 supabase/.env.ai 파일을 만들고 다음 두 값을 입력합니다.

    GEMINI_API_KEY=Google_AI_Studio에서_발급한_키
    BABY_AI_CRON_SECRET=충분히_긴_무작위_문자열
  3. 로컬 셸에 Supabase 프로젝트 ref를 설정한 뒤 비밀값과 함수를 배포합니다.

    export SUPABASE_PROJECT_ID="프로젝트-ref"
    supabase secrets set --env-file ./supabase/.env.ai --project-ref "$SUPABASE_PROJECT_ID"
    supabase functions deploy baby-ai --project-ref "$SUPABASE_PROJECT_ID"
  4. Supabase Dashboard의 Database → Vault에 아래 이름으로 값을 등록합니다.

    • baby_ai_project_url: Supabase Project URL
    • baby_ai_publishable_key: 브라우저용 publishable key 또는 기존 anon key
    • baby_ai_cron_secret: BABY_AI_CRON_SECRET과 동일한 값
  5. SQL Editor에서 supabase/baby-ai-cron.sql을 실행합니다. 5분마다 만료된 갱신 큐를 확인하며, 새 수유·수면 기록은 마지막 기록으로부터 30분 뒤 처리됩니다.

확인은 Supabase Edge Functions → baby-ai → Logs와 SQL Editor의 아래 쿼리로 합니다.

select jobname, schedule, active from cron.job where jobname = 'baby-ai-refresh-every-5-minutes';
select baby_id, due_at, status, attempt_count from public.baby_ai_refresh_queue order by due_at;

마이그레이션이나 Function Secret이 적용되지 않은 환경에서도 캘린더와 성장일기는 그대로 동작하며 AI 카드에 관리자 설정 안내만 표시됩니다. service_role, Gemini 키, cron 비밀값은 config.js, GitHub Actions 로그, 이슈 또는 채팅에 넣지 마세요.

여행 장소 검색

장소 추가에서 지역과 관광지·음식점·카페·숙소를 고르면 카카오 키워드 검색 결과를 보여 줍니다. 결과를 누르면 이름·주소·좌표·출처와 선택한 날짜·방문 여부가 함께 저장되고, 같은 창에서 다음 장소를 추가할 수 있습니다. 검색 결과는 카카오 검색 순서이며 가족 맞춤 추천이나 현재 GPS 주변 추천은 아닙니다. 이름으로 직접 남기는 기록은 좌표를 추정하지 않습니다.

  1. 카카오 개발자 앱의 REST API 키를 준비합니다. 지도용 JavaScript 키와는 별도입니다.
  2. Supabase Edge Function Secrets에 KAKAO_REST_API_KEY로 등록합니다. 키는 브라우저 코드나 채팅에 넣지 않습니다.
  3. supabase functions deploy travel-place-search --project-ref ljutcgmgtqfkwkxdbiyb로 배포합니다. JWT 검증과 함수 내부의 로그인·가구 가입 검증이 모두 필요합니다.
  4. 가족 계정으로 장소 추가를 열고 지역을 입력해 실제 결과·추가·지도 위치를 확인합니다. 키 존재 확인은 실제 검색 성공을 뜻하지 않습니다.

데모·비로그인 상태나 키가 없는 환경에서는 검색 영역을 숨기고 이름으로 추가할 수 있게 합니다. 검색 실패는 입력을 보존하고 오류를 표시합니다.

About

[앱] 가족 일정과 육아·성장 기록을 함께 관리하는 웹앱

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages