본문으로 건너뛰기

public 스키마

목적

public 스키마는 Lumie의 주요 런타임 스키마입니다. 이 안에는 플랫폼 범위 테이블과 tenant 범위 테이블이 모두 들어 있습니다. tenant 격리는 별도 스키마로 모델링되지 않으며, tenant_id 컬럼, 백엔드 tenant 컨텍스트, PostgreSQL RLS policy로 강제됩니다.

이 페이지는 persistence를 변경하거나 특정 테이블이 플랫폼 범위인지 tenant 범위인지 검토하는 백엔드 개발자를 위한 reference 문서입니다.

소스 경로

경로역할
V1__create_platform_tables.sqltenants, tenant_settings 생성
V13__create_event_publication.sqlSpring Modulith event publication 저장소
V14__create_shedlock.sql스케줄 작업 lock 테이블
V16__create_idempotency_keys.sql요청 idempotency 테이블
V18__rls_baseline.sqlpublic에서 tenant 범위 도메인 테이블을 RLS와 함께 재구성
V27__langgraph_schema.sql별도 langgraph 스키마와 role 생성
lumie-backend/libs/common/src/main/java/com/lumie/common/tenant/런타임 tenant 컨텍스트 헬퍼

범위 결정

테이블 유형public에 속함RLS 필요전형적 소유자
Platform catalogueYesNoTenant, billing, app platform 모듈
Tenant domain dataYesYesexam, content, attendance 같은 제품 모듈
Outbox and locksYesUsually no애플리케이션 인프라
Worker checkpoint dataNoNolanggraph 같은 전용 스키마

플랫폼 테이블

플랫폼 테이블은 전역 제어 평면 레코드입니다. Lumie가 tenant 전반에서 관리해야 하므로 tenant RLS로 필터링되지 않습니다.

테이블목적
tenantstenant 식별자, slug, lifecycle, 연락처, 브랜딩 필드
tenant_settingstenant별 플랫폼 설정
plans제품 요금제 카탈로그
subscriptionstenant 구독 상태
billing_keysToss billing key 메타데이터
event_publicationSpring Modulith outbox 테이블
shedlock스케줄 작업 lock
idempotency_keysAPI idempotency 레코드

public 안의 테넌트 범위 테이블

tenant 데이터 테이블은 물리적으로는 public에 있지만 tenant_id를 가지며 RLS로 보호됩니다. 예시는 다음과 같습니다.

  • 신원 및 사용자: users, students, staff, staff_permissions
  • 교육 모델: classes, lectures, assignments, textbooks
  • 시험 및 채점: exams, exam_results, questions, question_results, omr_grading_jobs
  • 커뮤니케이션 및 콘텐츠: announcements, qna_boards, sms_messages, ai_chat_messages
  • 출결: attendance_sessions, attendance_records
  • 파일 메타데이터 및 링크: file_metadata, file_links, file_download

RLS 계약

tenant 범위 테이블은 다음 패턴을 따릅니다.

ALTER TABLE <table_name> ENABLE ROW LEVEL SECURITY;
ALTER TABLE <table_name> FORCE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON <table_name>
USING (tenant_id = NULLIF(current_setting('app.tenant_id', true), '')::bigint)
WITH CHECK (tenant_id = NULLIF(current_setting('app.tenant_id', true), '')::bigint);

백엔드 코드는 이 테이블을 조회하기 전에 활성 트랜잭션 안에서 app.tenant_id를 설정해야 합니다. tenant 컨텍스트 없이 실행되는 쿼리는 fail closed 되거나 행을 반환하지 않아야 합니다.

검증

public schema를 변경할 때는 다음 검사를 사용하세요.

rg -n "ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|tenant_isolation" \
lumie-backend/app/src/main/resources/db/migration/public
rg -n "TenantContextHolder|app.tenant_id|SET LOCAL" lumie-backend