---
task_id: task-2119
type: context
scope: task
created: 2026-04-23
updated: 2026-04-23
status: in-progress
---

# 맥락 노트: task-2119

**task**: task-2119

---

## 결정 근거

### FeatureGate가 useFeatureGate 훅 결과를 사용하도록 통합
- **기존 문제**: FeatureGate 컴포넌트는 planFeatureMap의 minPlan만 비교 (정적 매핑), useFeatureGate 훅은 DB features 값을 조회 (동적 관리자 토글 반영)
- **결정**: FeatureGate에서 useFeatureGate 훅을 호출하여 DB features의 값을 추가로 확인. 두 조건(플랜 레벨 충족 AND DB feature 활성화)을 모두 만족해야 접근 허용
- **대안 기각**: FeatureGate를 완전히 제거하고 useFeatureGate로 일원화 → 기존 사용처 전체 리팩토링 필요, 범위 과대

### 서버 require_feature에 DB features 값 확인 추가
- **기존 문제**: require_feature는 PLAN_FEATURE_MAP에서 최소 플랜만 조회하여 sort_order 비교. plan_info["features"]의 실제 boolean 값은 확인하지 않음
- **결정**: plan_info에 이미 features dict가 포함되어 있으므로, features[feature_key]가 falsy(false, 0, null)이면 403 반환하는 검사 추가
- **대안 기각**: 별도 미들웨어 신설 → 기존 Depends 패턴과 불일치, 복잡도 증가

## 3 Step Why 자문

### 1st Why: "왜 이 설계가 필요한가?"
- A: 관리자 토글 OFF가 실제로 사용자 접근을 차단하지 않는 보안 결함. 프론트/서버 이중 제어 모두 정적 플랜 매핑만 참조하여 관리자 의도가 무시됨.

### 2nd Why: "왜 A가 최선의 접근인가?"
- B: 기존 useFeatureGate 훅이 이미 DB features를 올바르게 조회하는 로직을 가지고 있으므로, 이를 FeatureGate 컴포넌트에서 재사용하면 새 로직 작성 없이 정합성 확보 가능. 서버는 이미 get_user_plan에서 features dict를 반환하므로 추가 DB 쿼리 불필요.

### 3rd Why: "왜 B가 다른 대안보다 나은가?"
- C: 대안1(FeatureGate 제거+일원화)은 모든 사용처 리팩토링 필요(범위 과대). 대안2(별도 미들웨어)는 기존 Depends 패턴과 불일치. 현재 접근은 최소 변경으로 정합성을 달성하며, 기존 아키텍처와 조화롭다.

## 참조 자료

- FeatureGate 컴포넌트: `/home/jay/projects/InsuRo/src/components/FeatureGate.tsx`
- useFeatureGate 훅: `/home/jay/projects/InsuRo/src/hooks/use-feature-gate.ts`
- useFeatureAccess 훅: `/home/jay/projects/InsuRo/src/hooks/use-feature-access.ts`
- planFeatureMap: `/home/jay/projects/InsuRo/src/config/planFeatureMap.ts`
- server require_feature: `/home/jay/projects/InsuRo/server/main.py:400`
- get_user_plan: `/home/jay/projects/InsuRo/server/main.py:276`

## 주의사항

- useFeatureGate는 비동기(Supabase 직접 호출)이므로 FeatureGate에 추가 시 loading 상태 처리 필요
- 서버 캐시(5분 TTL) 때문에 관리자 토글 변경 후 최대 5분간 이전 값 유지 가능 — 이는 기존 동작이므로 본 작업 범위 외
- features dict에 feature_key가 없는 경우(= 관리자가 해당 기능을 설정하지 않은 경우) 처리: key 부재 시 기존 플랜 레벨 검사만 적용 (하위호환)
