WEBBOOK CHAPTER

Spring Security 6, 인증에서 운영까지: 17장. 멀티테넌트 조건을 데이터 계층까지 내린다

17장. 멀티테넌트 조건을 데이터 계층까지 내린다

service에서 tenant를 검사해도 repository가 ID 하나로 조회하면 실수 한 번에 다른 회사 데이터가 반환될 수 있다. 저장소 메서드 자체가 tenant를 필수로 받게 한다.


Optional<Contract> findByTenantIdAndId(String tenantId, UUID id);

@Query("""
  select c from Contract c
  where c.tenantId = :tenantId and c.id = :id
""")
Optional<Contract> findOwned(String tenantId, UUID id);

클라이언트가 보낸 tenant header를 신뢰하지 않는다. URL의 tenant와 인증된 membership을 대조하고, 가능하면 내부 TenantContext를 인증 정보에서 만든다. global support 역할은 별도 승격, 사유, 시간 제한, 감사가 있어야 한다.

DB row-level security를 쓰면 추가 방어층이 되지만 애플리케이션 정책을 대체하지 않는다. connection pool에서 tenant session variable이 다음 요청에 남지 않는지 transaction마다 설정과 초기화를 검증한다. migration, batch, backup export도 같은 경계를 따른다.

다른 tenant의 존재를 404로 숨기는 정책은 보안과 지원성을 함께 고려한다. 어떤 응답을 택하든 timing과 목록 count, search suggestion, 파일 URL에서 존재가 새지 않게 한다.