프로젝트 개요

매일 반복되는 "오늘 뭐 먹지?" 고민을 해결합니다. 팀이 큐레이션한 식당 풀에서 무작위 1개를 추천하고, 1명이라도 거부하면 즉시 재추천하는 만장일치 원칙을 적용합니다.

거부자에게는 후식 룰렛 당첨 확률이 올라가는 페널티가 부과되어 무분별한 반대를 방지합니다. Flutter로 iOS/Android/Web 크로스플랫폼을 지원합니다.

FlutterDartFirebaseFirestoreRiverpodGoRouterGoogle Maps

프로젝트 구조

lib/
├── main.dart                          # 엔트리 포인트
├── core/
│   ├── router.dart                    # GoRouter 설정
│   ├── theme.dart                     # 앱 테마
│   └── network_check.dart             # 오프라인 감지
└── features/
    ├── auth/                          # Google 로그인
    │   ├── domain/app_user.dart
    │   ├── data/auth_repository.dart
    │   └── presentation/login_screen.dart
    ├── group/                         # 그룹 & 식당 관리
    │   ├── domain/ (group, restaurant, menu_item)
    │   ├── data/group_repository.dart     # 388줄
    │   └── presentation/
    │       └── group_home_screen.dart     # 3,354줄
    ├── session/                       # 추천 & 수락/거부
    │   ├── data/session_repository.dart   # 359줄
    │   └── presentation/
    │       └── suggestion_screen.dart     # 454줄
    └── roulette/                      # 후식 룰렛
        ├── data/roulette_repository.dart
        └── presentation/
            └── roulette_screen.dart       # 597줄

functions/
└── src/index.ts                       # Kakao API 검색

Feature-Based Architecture

auth, group, session, roulette 4개 피처로 분리. 각 피처는 domain/data/presentation 3계층 구조로 관심사를 명확히 분리합니다.

Firebase 실시간 동기화

Firestore 스트림으로 그룹 멤버, 식당, 세션 상태를 실시간 동기화. Riverpod Provider가 상태 변화를 자동으로 UI에 반영합니다.

주요 기능

만장일치 추천 엔진

식당 풀에서 무작위 1개를 추천하고, 최근 5일 방문 식당은 자동 제외합니다. 1명이라도 거부하면 즉시 재추천하는 민주적 결정 방식입니다.

페널티 룰렛 시스템

거부 횟수에 비례해 후식 당첨 확률이 증가하는 가중 모드를 지원합니다. 시각적 룰렛 애니메이션과 confetti 축하 효과로 재미를 더합니다.

식당 큐레이션 & 지도

Google Places로 식당을 검색·등록하고, 카테고리·메뉴·가중치를 관리합니다. Google Maps로 위치를 확인하고 즐겨찾기로 관리할 수 있습니다.

크로스플랫폼 & 실시간

Flutter로 iOS, Android, Web을 단일 코드베이스로 지원합니다. Firestore 실시간 스트림으로 팀원 간 상태가 즉시 동기화됩니다.

사용 흐름

01
Google 로그인 & 그룹 참가

초대 코드로 팀 그룹에 참가하거나 새 그룹 생성

02
오늘 출석 체크

점심 참석 여부 토글, 매일 자정 자동 초기화

03
식당 추천 & 거부권

무작위 식당 제시, 1명이라도 거부 시 즉시 재추천

04
메뉴 선택

확정된 식당의 메뉴에서 각자 선택

05
후식 룰렛

거부 패널티 가중치 반영, 당첨자가 후식 비용 부담

식당 데이터 자동 수집

앱에 등록된 식당의 메뉴·가격·주소·좌표 정보를 네이버 지도에서 자동으로 크롤링하는 별도 파이프라인입니다. Playwright로 브라우저를 자동화하고, 결과를 Firebase에 동기화합니다.

PlaywrightTypeScriptFirebase AdminNaver Maps
restaurant-crawler/
├── src/
│   ├── index.ts              # 크롤링 오케스트레이터
│   ├── naverMapCrawler.ts    # 네이버 지도 스크래핑
│   ├── firebase.ts           # Firestore CRUD
│   └── utils.ts              # Haversine 거리 계산
└── .github/workflows/        # 자동 스케줄 (GitHub Actions)

3단계 스크래핑 전략

네트워크 API 인터셉트 → API 직접 호출 → DOM 폴백 순으로 시도합니다. Haversine 공식으로 반경 500m 내 결과만 필터링합니다.

자동 동기화

크롤링 결과(메뉴, 가격, 좌표)를 Firebase에 자동 업데이트합니다. 앱에서 별도 작업 없이 항상 최신 메뉴 정보를 확인할 수 있습니다.

댓글

불러오는 중...