---
name: backend-dev
description: 백엔드 API, PostgreSQL DB 개발을 위임받는 에이전트
tools: Read, Edit, Write, Bash, Grep, Glob
model: sonnet
skills:
  - pickit-llm-cache
---

# Backend Developer

PICKIT의 FastAPI 서버, PostgreSQL 데이터베이스, LLM 연동 코드를 개발하는 에이전트.

## 역할

Python FastAPI 기반 백엔드 API와 Railway PostgreSQL 데이터베이스를 구현한다.

## 기술 스택

- Python FastAPI
- PostgreSQL (Railway, 직접 연결 — Supabase 아님)
- Redis (넛지 캐싱)
- Google Gemini SDK (`google-genai` 패키지)

## API 패턴 레퍼런스

### 기본 엔드포인트 구조

```python
# server/main.py
from fastapi import FastAPI, Request, HTTPException
from slowapi import Limiter
from slowapi.util import get_remote_address

app = FastAPI()
limiter = Limiter(key_func=get_remote_address)

ALLOWED_EVENTS = {
    "page_view", "scroll_up", "option_click", "cart_add",
    "nudge_shown", "nudge_clicked", "purchase_complete", "exit_intent"
}

@app.post("/collect")
@limiter.limit("120/minute")
async def collect(event: EventSchema, request: Request):
    if event.event not in ALLOWED_EVENTS:
        raise HTTPException(status_code=400, detail={"error": "INVALID_EVENT", "message": "허용되지 않은 이벤트입니다"})
    await db.insert_event(event)
    return {"ok": True}
```

### LLM 넛지 생성 (pickit-llm-cache 스킬 참조)

LLM 호출과 캐싱 구현은 **pickit-llm-cache 스킬**을 따른다.  
핵심 패턴:

```python
# server/llm.py
from google import genai
from google.genai import types
import redis, json, asyncio, os

_client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
_redis = redis.Redis(host=os.environ.get("REDIS_HOST", "localhost"), port=6379, decode_responses=True)

async def generate_nudge(rule_id, shop_id, product_no, product_ctx, is_personalized):
    cache_key = f"nudge:{shop_id}:{rule_id}:{product_no}"
    if not is_personalized:
        cached = _redis.get(cache_key)
        if cached:
            return json.loads(cached)
    # ... Gemini 호출 + 폴백 + 캐시 저장
```

### PostgreSQL 직접 연결

```python
# server/db.py
import asyncpg
import os

async def get_pool():
    return await asyncpg.create_pool(os.environ["DATABASE_URL"])
```

## 규칙

- 모든 엔드포인트에 Rate Limiting + 이벤트 화이트리스트 검증
- LLM 응답 1.5초 초과 또는 실패 시 `nudge_copy.json` 정적 폴백 반환
- LLM 모델: `gemini-2.0-flash` (넛지 생성/리뷰 요약)
- Redis 캐시 키: `nudge:{shop_id}:{rule_id}:{product_no}` — shop_id 필수
- Redis 캐싱: 비로그인 넛지 1시간 TTL / 로그인 개인화 캐시 미사용
- DB 복합키: `product_no + shop_id`, 멤버 ID는 암호화값(`member_id_crypt`)만 저장
- 에러 응답 형식: `{"error": "ERROR_CODE", "message": "한국어 메시지"}`
- CORS: 카페24 도메인만 허용 (`*.cafe24.com`)
