권한 (Entitlement) 시스템
문서 정보
- 작성일: 2026-02-27
- 최종 업데이트: 2026-02-27
- 버전: v1.0.0
TL;DR
Entitlement 테이블은 사용자 1명당 1개의 레코드로 현재 멤버십 권한을 관리합니다. API 요청 시 이 테이블 하나만 조회하면 O(1)으로 권한 판단이 완료되며, 구독/체험/관리자 부여 등 어떤 경로로 권한을 받았든 동일한 방식으로 처리합니다.
목차
- 왜 Entitlement 테이블이 필요한가
- Entitlement 테이블 구조
- 권한 부여 소스
- 권한 판별 흐름
- Guard 기반 접근 제어
- Entitlement 라이프사이클
- 만료 처리 스케줄러
- 기능별 접근 권한 정리
- FAQ
왜 Entitlement 테이블이 필요한가
기존 방식의 문제
Entitlement 도입 이전에는 사용자의 PLUS 권한을 확인하려면 여러 테이블을 동시에 조회해야 했습니다.
| 문제 | 설명 |
|---|---|
| 느린 응답 | 매 요청마다 2~3개 테이블을 조회해야 함 |
| 복잡한 로직 | 구독 상태, 체험 기간, 관리자 부여를 모두 종합해서 판단 |
| 확장 어려움 | 새로운 권한 부여 방식이 생길 때마다 판단 로직 수정 필요 |
Entitlement의 해결 방식
핵심 아이디어는 간단합니다. "복잡한 판단은 권한이 변경될 때 한 번만 하고, 조회는 항상 단순하게"
| 항목 | 기존 방식 | Entitlement 방식 |
|---|---|---|
| 조회 횟수 | 2~3개 테이블 | 1개 테이블, 1건 |
| 판단 시점 | API 요청 시 매번 | 이벤트 발생 시 한 번 |
| Guard 역할 | 여러 테이블 종합 판단 | 단순 조건 비교만 |
| 새 권한 소스 추가 | Guard 로직 수정 필요 | EntitlementService만 확장 |
Entitlement 테이블 구조
사용자 1명당 정확히 1개의 레코드만 존재합니다. userId가 곧 기본 키(Primary Key)입니다.
| 필드 | 설명 | 예시 |
|---|---|---|
| userId | 사용자 ID (기본 키, User와 1:1) | 12345 |
| plan | 현재 플랜 | PLUS 또는 FREE |
| status | 권한 상태 | ACTIVE, INACTIVE, SUSPENDED |
| validFrom | 권한 시작일 | 2026-02-27T00:00:00Z |
| validUntil | 권한 종료일 | 2026-03-27T00:00:00Z |
| sourceType | 권한이 어디서 왔는지 | SUBSCRIPTION, TRIAL, ADMIN |
| sourceId | 원본 레코드 ID | 구독 ID 또는 정책 적용 ID |
핵심 원칙
하나의 사용자에게 항상 하나의 레코드만 유지됩니다. 여러 권한 소스가 경쟁할 경우 가장 강한 권한이 우선합니다.
상태(status) 의미
| 상태 | 의미 | 서비스 접근 |
|---|---|---|
| ACTIVE | 유효한 멤버십 | 허용 |
| INACTIVE | 만료 또는 미가입 | 차단 |
| SUSPENDED | 환불/부정 사용 등으로 정지 | 차단 |