Files
llm-wiki/vault/30-knowledge/projects/ca-tmpl/multi-tenancy-isolation-patterns.md
T

7.8 KiB

title, source_type, status, confidence, tags, related_projects, last_reviewed
title source_type status confidence tags related_projects last_reviewed
ca-tmpl - Multi-tenancy 결정 (opt-in shared DB + tenant_id) project verified high
ca-tmpl
multi-tenancy
saas
actually-implemented
locally-verified
documented-only
ca-tmpl
2026-07-02

ca-tmpl - Multi-tenancy 결정 (opt-in shared DB + tenant_id)

Layer: wiki/projects/ — 내 프로젝트 사실. 일반 개념은 wiki/concepts/multi-tenancy-isolation-patterns 참조.

프로젝트 컨텍스트

ca-tmpl(Clean Architecture skeleton)에서 multi-tenancy를 어떻게 다룰지 정한 결정 문서다. baseline은 다음 조합이다.

  • opt-in: APP_TENANT_ENABLED=true일 때만 tenant 로직 활성. single-tenant deployment에서는 비활성화하여 skeleton 적용 범위를 넓힘.
  • shared DB + tenant_id column (ULID): AWS Pool 모델 / Hibernate DISCRIMINATOR 전략에 해당.
  • Tenant resolution: JWT claim 우선, X-Tenant-Id header는 admin only(CROSS_TENANT_ADMIN capability 보유자) 에 한해 허용.
  • B2B 초기 단계(tenant 수 수십~수백 단위) 가정. isolation 비용 대비 운영 단순성 우선.

현재 진행 상태: tenant-aware registry/runbook/capability/idempotency scope 일부 구현 + repository tenant filter는 planned. 본 문서는 구현된 tenant support surface와 아직 없는 storage isolation enforcement를 분리한다.

실제 구현 내용 (actually-implemented)

  • docs/registries/env-keys.yamlAPP_TENANT_ENABLED, docs/registries/headers.yamlX-Tenant-Id, docs/registries/capabilities.yamlCROSS_TENANT_ADMIN, docs/registries/error-codes.yaml에 tenant error code가 존재한다.
  • docs/runbooks/authz-tenant-mismatch.md, docs/runbooks/authz-cross-tenant-violation.md가 cross-tenant incident response stub을 제공한다.
  • AuthorizationPrincipal, RequiresPermission, AuthorizationPort, role/permission registry와 AuthorizationContractTest가 capability 기반 authorization foundation을 제공한다.
  • IdempotencyScopeIdempotencyKeySupport는 tenant-aware scope를 표현할 수 있다.
  • repository-level tenant predicate 강제, tenant resolver filter, storage isolation은 아직 구현되지 않았다.

로컬/dev 검증 (locally-verified)

  • ./gradlew check 통과(2026-07-02, BUILD SUCCESSFUL, 114 tasks).
  • AuthorizationContractTest, IdempotencyScopeTest, IdempotencyKeySupportTest, registry governance tests가 tenant/capability/registry surface 일부를 검증한다.
  • repository tenant filter와 cross-tenant E2E isolation은 검증되지 않았다.

운영 검증 (prod-verified)

없음. ca-tmpl은 skeleton이며 prod 배포 이력 없음.

문서/계획만 존재 (documented-only / planned)

Tenant resolution + isolation 정책 (partially-implemented)

  • JWT claim 우선 → admin only X-Tenant-Id header fallback → 해석 실패 시 reject.
  • repository 진입점에서 tenant filter 강제(CROSS_TENANT_ADMIN capability 없이는 모든 query에 tenant_id predicate).
  • status: partially-implemented — registry/header/capability/runbook/idempotency scope는 존재하지만 repository filter와 tenant resolver filter는 planned.

6종 대안 검토 → Pool 채택

검토한 6가지와 채택/기각 사유:

대안 분류 채택 여부 사유
shared DB + tenant_id (ULID) AWS Pool / Hibernate DISCRIMINATOR 채택 B2B 초기, tenant 수 수십~수백 예상. 운영 단순성.
subdomain-based resolution-only 기각 wildcard DNS/TLS·subdomain takeover·local dev 비용. resolution은 isolation을 보장하지 않음.
JWT claim only (storage 분리 없음) resolution-only 기각 claim 검증 누락 시 cross-tenant leak. storage layer 강제 필요.
schema-per-tenant Hibernate SCHEMA 기각 catalog bloat·search_path 전환 plan cache 무효화·HikariCP 설계 복잡. 초기 단계 ROI 부정.
db-per-tenant AWS Silo 기각 운영 비용 폭증(마이그레이션·백업·connection pool 폭발). 규제 요구 부재.
hybrid (Azure Deployment Stamps / AWS Bridge) mixed 기각 운영 복잡도 최고. PMF 이후 단계 검토 사항.

근거: ca-tmpl은 skeleton이며 초기 도입 대상은 B2B 소규모 SaaS. 결정은 verified 되었지만 storage isolation enforcement는 아직 planned다.

Migration trigger 3가지 정의

shared DB → schema/db-per-tenant로 전환을 검토할 조건:

  1. 규제: 금융·의료(HIPAA·FedRAMP·data residency) isolation 강제.
  2. 규모: tenant 수 hundreds 도달 + 단일 row 수 억대 진입(noisy neighbor·index 비용 임계).
  3. 상품 tier: enterprise tier 등장으로 isolation을 가격에 반영해야 할 때.

status: documented-only — migration trigger는 아직 관측 지표/자동 경보로 구현되지 않았다.

CROSS_TENANT_ADMIN capability 정의

  • admin/support 운영 동선용. 보유자만 X-Tenant-Id header로 tenant 전환 가능.
  • 일반 사용자 경로는 JWT claim 단독, header 무시.
  • status: partially-implemented — capability vocabulary와 authorization foundation은 존재하지만, repository tenant filter와 admin tenant switching E2E는 미구현.

면접에서 말할 수 있는 범위

자신 있게

  • "Pool / Silo / Bridge의 차이와 각각의 비용·isolation trade-off."
  • "tenant resolution에서 JWT claim과 X-Tenant-Id header의 trust 차이, header를 admin only로 제한하는 이유."
  • "shared DB → 격리 강화 모델로 가는 migration trigger 3가지(규제 / 규모 / enterprise tier)."

적당히

  • ULID vs UUID 선택 이유(정렬 가능성·index locality·시간 정보 노출 trade-off).
  • Hibernate multi-tenancy strategy(DATABASE / SCHEMA / DISCRIMINATOR) 차이와 CurrentTenantIdentifierResolver 동작 개요.

답하면 안 됨 (모른다고 해야 함)

  • "tenant 격리를 어떻게 측정했는가" — 측정·테스트 부재.
  • "cross-tenant 침해 시도/penetration test 결과" — 수행 안 함.
  • "schema-per-tenant 운영 경험" — 검토만 했고 운영해 본 적 없음.
  • "실제 tenant 수, row 수, 성능 지표" — skeleton에 데이터 없음.

과장 금지 지점

  • "shared DB + tenant_id가 항상 우월하다" → 금지. 규제 산업(HIPAA·금융·data residency)에서는 Silo가 사실상 강제다. 본 선택은 B2B 초기 단계 가정에 종속된 결정이라는 점을 함께 말할 것.
  • Stripe/Citus schema-per-tenant 한계치 단언 금지 — 정확 인용 wording이 미완(raw 자료 needs-confirmation). "수백~수천 단위에서 catalog overhead가 보고된다" 정도로 출처와 함께만 언급.
  • "ca-tmpl에 multi-tenancy를 완성했다" → 금지. tenant-aware registry/capability/scope foundation은 구현됐지만, repository-level tenant filter와 E2E isolation은 planned다.
  • "JWT claim만 검증하면 안전하다" → 금지. repository 레벨 tenant filter가 별도로 필요하다.
  • "Atlassian이 그렇게 하니까 best practice" → 금지. company-tech-blog는 관점이지 공식 기준이 아니다.

관련 개념

Sources

Cluster / 묶음