# InsuRo 서버 Pyright 에러 85건 전량 수정

## 작업 레벨: Lv.2

## 프로젝트
- InsuRo: `/home/jay/projects/InsuRo`
- 서버: `/home/jay/projects/InsuRo/server`

## 문제
`server/main.py`에 Pyright 에러 85건 존재. 대부분 Supabase Python SDK의 JSON 타입 추론 문제.

## 에러 유형 분석 (상위 5개)
1. **reportOptionalMemberAccess (9건)**: `res.data`가 None일 수 있는데 `.get()` 등 접근
2. **reportCallIssue (7건)**: `__getitem__`/`get` 오버로드 매칭 실패
3. **reportIndexIssue (8건)**: JSON 반환값에 `[]` 접근 시 타입 불일치
4. **reportOptionalIterable (4건)**: None일 수 있는 값을 for 루프에 사용
5. **`.get()` 접근 불가 (20건+)**: Supabase JSON 타입이 `str|int|float|bool|Sequence|None` 유니온이라 `.get()` 호출 불가

## 수정 전략

### 1차: 타입 가드 패턴 적용 (권장)
```python
# 기존 — Pyright 에러
result = sb.table("x").select("*").execute()
item = result.data[0]  # data가 None일 수 있음
val = item.get("key")  # item이 dict인지 불확실

# 수정 — 타입 가드
result = sb.table("x").select("*").execute()
if result.data:
    item = result.data[0]
    if isinstance(item, dict):
        val = item.get("key")
```

### 2차: 반복 패턴은 헬퍼 함수로 통합
```python
def _sb_first(result) -> dict | None:
    """Supabase 결과에서 첫 번째 row를 dict로 반환. 없으면 None."""
    if result.data and isinstance(result.data, list) and len(result.data) > 0:
        row = result.data[0]
        return row if isinstance(row, dict) else None
    return None

def _sb_rows(result) -> list[dict]:
    """Supabase 결과에서 모든 row를 list[dict]로 반환."""
    if result.data and isinstance(result.data, list):
        return [r for r in result.data if isinstance(r, dict)]
    return []
```

### 3차: 불가피한 경우 `# type: ignore[...]` (최소한으로)

## 목표
- Pyright 에러: 85건 → **0건** (또는 10건 이하)
- 기능 변경 없음 (타입 안전성만 강화)
- 기존 테스트 전량 통과

## affected_files
- `server/main.py` (수정 — 타입 가드 + 헬퍼 함수)

## 검증 시나리오
1. `pyright main.py` → 에러 0건 (또는 최소화)
2. `python3 -m pytest server/tests/ -q` → 기존 테스트 전량 통과
3. npm run build 성공
4. 서버 재시작 정상
