Skip to content

Latest commit

 

History

History
201 lines (147 loc) · 9 KB

File metadata and controls

201 lines (147 loc) · 9 KB

cellar-teller 시스템 아키텍처

서비스 개요

cellar-teller는 개인 와인 인벤토리 관리와 시음 기록을 위한 모바일 우선 반응형 웹 앱이다. 사용자는 보유 와인을 수동으로 등록하고, 셀러 내부 위치와 외부 보관 위치를 시각적으로 관리하며, 시음 기록을 누적하고, 현재 보유 와인 중 마시기 좋은 와인을 추천받을 수 있다.

1차 MVP는 React 프론트엔드와 Supabase를 기반으로 구현한다. LLM API는 마실 와인 추천 기능에만 사용하며, 사진 촬영과 AI 기반 와인 정보 draft 기능은 후순위 백로그로 미룬다.

제품 범위

MVP 기능

  1. 수동 와인 등록 및 관리

    • 사용자가 직접 와인 정보를 입력한다.
    • 입력 필드는 이름, 생산자, 빈티지, 품종, 가격, 날짜, 노트로 시작한다.
    • 등록, 조회, 수정, 삭제 흐름을 Supabase에 저장한다.
  2. 시각적 셀러 매핑

    • 셀러 내부를 계층형 grid 구조로 보여준다.
    • 셀러 외부 보관 와인은 가로 스크롤 목록으로 보여준다.
    • Drag & Drop으로 외부 보관 목록과 셀러 내부 위치 사이를 이동한다.
    • 이미 와인이 있는 셀러 위치끼리는 swap을 지원한다.
  3. 마실 와인 추천

    • 현재 인벤토리 데이터를 기준으로 사용자의 조건에 맞는 와인을 추천한다.
    • 실제 LLM API와 mock API를 모두 지원하는 구조로 구현한다.
    • 개발과 테스트에서는 mock API로 안정적인 응답을 검증하고, 운영 또는 통합 환경에서는 실제 LLM API를 사용할 수 있게 분리한다.
  4. 시음 기록

    • 와인별 시음 노트를 타임라인으로 기록한다.
    • 시음 기록을 기반으로 간단한 통계와 요약 정보를 보여준다.
    • AI 요약은 MVP 필수 범위가 아니며, 우선은 로컬 계산 기반의 요약만 다룬다.

후순위 백로그

  1. 사진 촬영 및 업로드

    • 라벨, 영수증, 매장 사진 등을 저장하는 기능은 MVP 이후로 미룬다.
    • Supabase Storage 연동도 사진 기능 착수 시점에 추가한다.
  2. AI 기반 와인 정보 draft

    • 텍스트 트리거와 연속 사진 업로드를 이용해 와인 등록 초안을 만드는 기능은 후순위로 둔다.
    • MVP에서는 와인 입력을 수동 입력 방식으로만 구현한다.
  3. AI 기반 시음 인사이트

    • 시음 기록 전체를 분석해 취향과 패턴을 요약하는 기능은 추천 기능 이후 단계로 둔다.

전체 구조

Mobile / Desktop Browser
        |
        v
React Mobile-First Web App
        |
        v
Supabase Client SDK
        |
        +--> Supabase Auth
        +--> Supabase Postgres
        +--> Supabase Edge Functions
                    |
                    +--> Mock Recommendation API
                    +--> External LLM API

프론트엔드 아키텍처

프론트엔드는 React 기반 모바일 우선 UI로 구성한다. 작은 화면에서 핵심 흐름이 먼저 자연스럽게 동작해야 하며, 태블릿과 데스크톱에서는 동일한 정보 구조를 넓은 레이아웃으로 확장한다.

주요 화면은 다음과 같다.

  • 인벤토리: 와인 목록, 검색, 필터, 상세 화면.
  • 와인 폼: 수동 입력 기반 생성 및 수정 화면.
  • 셀러 맵: 셀러 내부 grid와 외부 보관 가로 목록.
  • 추천: 추천 조건 입력, 추천 결과, 추천 사유 표시.
  • 시음 기록: 타임라인, 기본 통계, 와인별 기록.

프론트엔드의 주요 책임은 다음과 같다.

  • Supabase에서 인벤토리, 위치, 시음 기록을 읽고 렌더링한다.
  • 와인 입력 폼을 검증하고 저장 요청을 보낸다.
  • Drag & Drop 이동 중에는 낙관적 UI 상태를 제공한다.
  • 추천 요청은 Edge Function을 통해 호출하고, 실제 LLM API와 mock API 선택은 클라이언트 밖에서 관리한다.
  • 모바일 화면에서 터치 가능한 크기, 읽기 쉬운 정보 밀도, 가로 overflow 방지를 우선한다.

Supabase 아키텍처

Supabase는 MVP 백엔드의 중심 역할을 맡는다.

주요 책임은 다음과 같다.

  • Auth: 사용자 인증과 세션 관리.
  • Postgres: 와인 인벤토리, 보관 위치, 셀러 슬롯, 시음 기록 저장.
  • Edge Functions: 추천 요청 처리, mock API 또는 실제 LLM API 라우팅, 응답 검증.

MVP에서는 사진 업로드가 후순위이므로 Supabase Storage를 필수 구성 요소로 두지 않는다. 사진 기능을 시작할 때 Storage bucket, 사진 메타데이터, 업로드 UI를 추가한다.

클라이언트에서 외부 LLM API를 직접 호출하지 않는다. 추천 요청은 Supabase Edge Function을 통해 처리해 API key를 서버 측에만 보관하고, mock과 실제 API를 같은 인터페이스로 교체할 수 있게 한다.

데이터 모델 초안

MVP 기준 핵심 엔티티는 다음과 같다.

  • wines: 와인 기본 정보. 이름, 생산자, 빈티지, 품종, 가격, 구매 또는 등록 날짜, 노트, 상태, 소유자 정보를 가진다.
  • storage_locations: 셀러, 외부 보관함 등 논리적 보관 구역.
  • cellar_slots: 셀러 내부의 계층형 위치. 섹션, 행, 열, 표시 라벨을 가진다.
  • wine_positions: 와인이 현재 셀러 슬롯에 있는지, 외부 보관 목록에 있는지 나타내는 위치 정보.
  • tasting_entries: 시음 날짜, 노트, 선택적 평점, 연결된 와인, 소유자 정보를 가진 타임라인 기록.
  • recommendation_requests: 추천 조건, 사용한 provider, 응답 상태, 추천 결과 요약을 저장할 수 있는 선택적 로그 테이블.

후순위 기능 착수 시 추가할 수 있는 엔티티는 다음과 같다.

  • wine_photos: 와인 또는 draft session에 연결되는 사진 메타데이터.
  • ai_draft_sessions: 사진과 텍스트 트리거 기반 와인 정보 초안 상태.

사용자 소유 데이터 테이블은 모두 owner 컬럼과 Row-Level Security 정책을 가져야 한다.

추천 API 구조

추천 기능은 provider 교체가 가능한 인터페이스로 설계한다.

Recommendation UI
        |
        v
recommendationService
        |
        v
Supabase Edge Function: recommend-wine
        |
        +--> MockRecommendationProvider
        +--> LlmRecommendationProvider

Edge Function은 다음을 담당한다.

  • 현재 사용자 인벤토리 조회.
  • 사용자가 입력한 추천 조건 검증.
  • mock 또는 llm provider 선택.
  • provider 응답을 공통 스키마로 정규화.
  • 추천 와인, 추천 사유, 매칭된 조건, 주의사항을 반환.

mock API는 다음 목적을 가진다.

  • LLM API key 없이 로컬 개발과 UI 구현을 진행한다.
  • 테스트에서 결정적인 추천 응답을 사용한다.
  • 실제 LLM 장애 시 fallback 동작을 검토할 수 있게 한다.

기능 흐름

수동 와인 등록

  1. 사용자가 와인 폼을 연다.
  2. 이름, 생산자, 빈티지, 품종, 가격, 날짜, 노트를 직접 입력한다.
  3. 클라이언트에서 필수값과 타입을 검증한다.
  4. Supabase에 와인 레코드를 저장한다.
  5. 기본 위치는 외부 보관 목록 또는 사용자가 선택한 위치로 설정한다.

시각적 셀러 매핑

셀러 위치는 단순 화면 좌표가 아니라 구조화된 데이터로 관리한다.

  • 외부 보관 와인을 빈 셀러 슬롯으로 이동한다.
  • 셀러 와인을 외부 보관 목록으로 이동한다.
  • 점유된 셀러 슬롯끼리 와인을 교환한다.
  • 실패한 저장 요청은 낙관적 UI 상태를 rollback한다.

마실 와인 추천

  1. 사용자가 조건을 입력한다.
  2. Edge Function이 현재 사용자 인벤토리를 조회한다.
  3. 설정에 따라 mock provider 또는 LLM provider를 호출한다.
  4. 추천 결과와 이유를 공통 응답 형식으로 반환한다.
  5. 추천 결과는 인벤토리나 시음 기록을 자동 변경하지 않는다.

시음 기록

시음 기록은 와인에 연결된 append-only 성격의 타임라인으로 다룬다. 기본 통계는 클라이언트 또는 Supabase 조회 결과를 기반으로 계산하며, AI 요약은 후순위 기능으로 남긴다.

비기능 요구사항

  • 모바일 우선 반응형 레이아웃.
  • 사용자 소유 데이터에 대한 Supabase RLS 적용.
  • LLM API key는 서버 측에서만 관리.
  • 추천 기능은 mock provider와 실제 LLM provider를 같은 인터페이스로 지원.
  • Drag & Drop 실패 시 복구 가능한 UI 상태.
  • 폼과 Drag & Drop 컨트롤은 터치 환경에서 사용 가능해야 한다.

구현 우선순위

  1. React 앱 구조, 라우팅, 모바일 레이아웃 기반.
  2. Supabase client와 환경 변수 설정.
  3. 와인, 보관 위치, 셀러 슬롯, 시음 기록 schema와 RLS.
  4. 수동 와인 CRUD.
  5. 셀러 grid와 외부 보관 목록.
  6. Drag & Drop 위치 이동 및 swap.
  7. 시음 기록 타임라인과 기본 통계.
  8. 추천 조건 UI.
  9. mock 추천 API.
  10. 실제 LLM 추천 API 연동.
  11. 사진 촬영, 업로드, AI draft 기능은 MVP 이후 백로그로 진행.