# task-2142: FeatureGate 어드민 토글 동적 연동 — 이중 게이트 제거

## ★ 프로젝트: `/home/jay/projects/InsuRo/`

## 문제
`FeatureGate.tsx`에서 접근 허용 로직이 이중 게이트로 되어 있음:
```typescript
const canAccess = !planLoading && hasPlanLevel && dbAllowed;
```

- `hasPlanLevel`: `planFeatureMap.ts`의 `minPlan` 하드코딩 비교
- `dbAllowed`: DB `subscription_plans.features` JSON에서 피쳐 값 조회 (어드민 토글)

**문제**: 어드민에서 특정 플랜에 피쳐를 켜도(DB `true`), `minPlan` 하드코딩에 걸려서 차단됨.
예: `infoKeyword`의 `minPlan`은 "맥스"인데, 어드민이 Max 플랜에 `infokeyword_access: false`로 설정 → 차단. 어드민 토글이 무의미.

## 수정 (1건, surgical)

### 파일: `/home/jay/projects/InsuRo/src/components/FeatureGate.tsx` L41

**현재 코드 (L41):**
```typescript
  const canAccess = !planLoading && hasPlanLevel && dbAllowed;
```

**수정:**
```typescript
  // DB feature 값이 존재하면 DB(어드민 토글)가 단일 소스
  // DB에 해당 키가 없으면(null) planLevel 폴백
  const canAccess = !planLoading && (dbGate.value !== null ? dbAllowed : hasPlanLevel);
```

### 로직 변경 요약
- DB에 피쳐 키 있음 (`dbGate.value !== null`) → **어드민 토글 값만** 사용
- DB에 피쳐 키 없음 (`dbGate.value === null`) → **planLevel 하드코딩** 폴백
- `minPlan`은 잠금 UI 메시지용으로만 유지 ("맥스 플랜 이상에서 사용 가능")

## ★ 먼저 읽을 파일
- `/home/jay/projects/InsuRo/src/components/FeatureGate.tsx` — 전체 (67줄)
- `/home/jay/projects/InsuRo/src/config/planFeatureMap.ts` — 전체 (44줄)
- `/home/jay/projects/InsuRo/src/hooks/use-feature-gate.ts` — L96~110 (dbGate.value 로직)

## 검증 시나리오

### 시나리오 1: Hidden 플랜 + infokeyword_access: true (DB)
- 결과: 접근 허용 (dbGate.value=true → dbAllowed=true → canAccess=true)

### 시나리오 2: Max 플랜 + infokeyword_access: false (DB)
- 결과: 접근 차단 (dbGate.value=false → dbAllowed=false → canAccess=false)
- 잠금 메시지: "맥스 플랜 이상에서 사용 가능" (planFeatureMap의 minPlan 참조)

### 시나리오 3: Free 플랜 + infokeyword_access: false (DB)
- 결과: 접근 차단

### 시나리오 4: DB에 피쳐 키 없는 경우
- 예: `blog-rank` 탭 (planFeatureMap에만 있고 DB features에 키 없음)
- 결과: planLevel 폴백으로 동작 (기존과 동일)

### 시나리오 5: TypeScript 빌드
- `npx tsc --noEmit` 에러 0건
- `npx vite build` 성공

## 완료 시그니처
- L41: `dbGate.value !== null ? dbAllowed : hasPlanLevel` 조건
- 기존 잠금 UI 메시지 유지
- TypeScript 빌드 에러 0건
- Vite 빌드 성공

## 레벨
- normal

## 프로젝트
- insuro