Files
document-haness/docs/clean-architecture-backend-template/tech-log-studio/multitenancy-isolation/reference/reference-tenant-column-belongs-in-every-unique-constraint.md
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.

Follows the import procedure in README.md.

  source/     the originating repository verbatim — 78 documents, 28 SVGs,
              8 manifests, plus .source-revision recording the commit
  final/      the SSOT
    document.md   729 lines written from the 29 experiment documents, not
                  concatenated: what was predicted, what was measured, and
                  where the measurement itself was wrong
    evidence/raw    125 outputs, flattened to <experiment>__<file> because
                    the originals collided (01-baseline.txt appeared three
                    times) and the audit only globs the top level
    evidence/meta   one per raw file; command and exitCode are null and the
                    README says why rather than inventing them
    evidence/browser  22 captures
    assets/       three diagrams through techviz
    .techviz/     their VizSpecs

A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.

Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.

verify-pipeline.py passes. audit-records.py reports no issues.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 22:51:59 +09:00

56 lines
2.3 KiB
Markdown

---
kind: REFERENCE
slug: tenant-column-belongs-in-every-unique-constraint
title: tenant 컬럼이 있는 테이블의 모든 unique 제약에 그 컬럼이 들어가야 한다
topic: multitenancy-isolation
project: clean-architecture-backend-template
status: 게시 전
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
rootTreeNode: reference:tenant-column-belongs-in-every-unique-constraint
verifiedOn: # 이 기록은 이번 회차에 실행 확인을 하지 않았다
---
# tenant 컬럼이 있는 테이블의 모든 unique 제약에 그 컬럼이 들어가야 한다
## 목적
테넌트 컬럼이 빠진 유일 제약이 한 테넌트의 삽입을 다른 테넌트의 데이터 때문에 실패시켜, 버그와 정보 유출을 동시에 만드는 것을 막는다.
## 규칙
1. 유일성 요구에 테넌트 컬럼을 포함한다
격리가 컬럼에 의존하면 그 테이블의 모든 유일성 요구가 그 컬럼을 포함해야 한다.
2. 빠뜨리면 두 가지가 동시에 일어난다
정상적인 삽입이 실패하고, 그 실패가 다른 테넌트에 그 값이 존재한다는 사실을 알린다.
3. 부분 유일 인덱스와 배제 제약에도 같은 논리가 적용된다
조건부 유일성도 유일성이다.
4. 전역 유일이 의도라면 그것을 적는다
외부 시스템의 식별자처럼 전역적으로 유일해야 하는 값은 테넌트를 포함하지 않는 것이 맞다. 그때는 그 값이 테넌트 간에 노출되는 것이 의도임을 적어야 한다.
## 적용 조건
판별 컬럼 전략을 쓰는 모든 테이블
테넌트 컬럼이 있는 모든 인덱스와 제약
## 예외
전역 유일이 요구사항인 값. 그 사실과 노출 범위를 함께 적는다.
## 예시
값만으로 걸린 유일 인덱스는 다른 테넌트가 그 값을 이미 썼다는 이유로 한 테넌트의 삽입을 실패시킨다. 존재하지 않아야 할 행의 존재를 알려 주는 것이다.
## 관계
- **RLS가 아무것도 하지 않는 세 가지 방법**
같은 마이그레이션이 함께 다룬 축이다.
- **Hibernate filter는 보안 경계가 아니다**
컬럼 기반 격리의 다른 면이다.
- **위험한 조합은 정책이 아니라 생성자가 거부하게 만든다**
제약으로 강제하는 같은 계열의 원칙이다.