한 줄 목표
PostgreSQL RLS가 활성화된 제한 Runtime DB Role 환경에서도
DEMO_SEED_ENABLED=true를 유지한 채 Demo/Test Seed가 최초 기동과 동일
DB 재기동 모두 정상·멱등하게 수행되도록 Demo Seed의 tenant context와
transaction 경계를 정리합니다.
현재 배포 전제
이 이슈는 아직 배포되지 않은 신규 환경을 준비하는 작업이 아닙니다.
Server·PostgreSQL DB·Infra는 이미 dev 환경에 배포되어 외부 URL로
서비스 중입니다.
Server는 SPRING_PROFILES_ACTIVE=dev로 실행 중입니다.
배포 환경은 DEMO_SEED_ENABLED=true이며 애플리케이션 기동·재기동 시
Demo Seed가 실행됩니다.
기존 PostgreSQL PVC에는 현재 Demo/Test fixture가 저장되어 있습니다.
이 변경은 기존 fixture를 삭제하거나 새 DB로 교체하지 않고, 기존
DB/PVC를 그대로 유지한 재기동에서도 호환성을 보장해야 합니다.
PR feat: PostgreSQL RLS 기반 사업장 2차 격리 활성화 #135 배포 전 실제 Runtime Role이 Migration Role과 분리되어 있고
RLS를 우회하지 않는지는 현재 dev 배포 DB의 live catalog 기준으로
별도 확인합니다.
왜 필요한가요?
PR #135는 PostgreSQL RLS를 활성화하여 애플리케이션의 company_id 범위
조건에 더해 DB가 다른 사업장의 행을 한 번 더 차단하도록 합니다.
현재 배포 환경은 DEMO_SEED_ENABLED=true이며 Demo/Test fixture를
startup seed로 유지하고 있습니다. 하지만 현재 Demo Seed runner는 RLS가
활성화된 제한 Runtime Role과 호환되지 않습니다.
PR #135에서 수행한 수동 검증에서는 RLS 활성화 후 Seed를 켠 상태로
재기동할 때 다음 흐름으로 실패했습니다.
tenant context 없이 기존 company를 조회
RLS에 의해 기존 Demo/Test company 행을 조회하지 못함
Seed가 company가 없는 것으로 판단하고 신규 insert 시도
RLS WITH CHECK에 의해 SQLSTATE 42501로 차단
startup Seed 실패로 애플리케이션 기동 실패
특히 RLS Flyway migration은 Seed runner보다 먼저 commit되므로, 이
상태에서 Pod가 기동에 실패해도 DB에는 RLS가 활성화된 상태가 남습니다.
단순 image rollback만으로 migration을 되돌릴 수 없습니다.
현재의 임시 우회책은 #135 배포 전에 DEMO_SEED_ENABLED=false로 변경하는
것이지만, 이 경우 기존 데이터는 유지되더라도 재기동 시 Demo/Test
fixture의 자동 복구·보충 기능을 사용할 수 없습니다.
따라서 배포 환경에서 Demo Seed를 계속 활성화하려면 PR #135보다 먼저 Seed
자체를 RLS-aware하게 만드는 별도 호환 변경이 필요합니다.
현재 대상
현재 startup Demo Seed의 주요 단계는 다음 세 runner입니다.
DemoAuthSeedRunner
Demo/Test 회사·사용자 등 인증 fixture
DemoWorkerSeedRunner
DemoOperationalSeedRunner
현재 구조에서는 Demo/Test 두 회사에 대한 Seed가 각 runner의 큰
transaction 경계 안에서 함께 처리될 수 있어, RLS 활성 환경에서 회사별
tenant context를 안전하게 적용하기 어렵습니다.
작업 범위
1. Demo/Test 회사별 transaction 분리
2. transaction-local tenant context 적용
3. transaction 실행 구조 정리
4. 기존 Seed 멱등성 유지
구현 원칙
이번 작업은 RLS를 약화시키지 않고 Seed를 기존 tenant 계약에 맞추는
방향으로 구현합니다.
다음 방식으로 문제를 우회하지 않습니다.
Runtime DB Role에 SUPERUSER 또는 BYPASSRLS 부여
Runtime Role을 tenant table owner로 변경하여 RLS 우회
Seed 실행 중 임시로 DISABLE ROW LEVEL SECURITY
모든 tenant를 볼 수 있는 Seed 전용 unrestricted Repository 추가
connection session 전체에 tenant context를 남기는 방식
#135의 RLS policy 범위를 축소하여 Seed를 통과시키는 방식
Seed도 실제 Runtime과 같은 tenant isolation 원칙을 따라야 합니다.
완료 조건
자동 테스트
PostgreSQL 제한 Role 검증
다음 검증은 table owner/superuser가 아닌 실제 제한 Runtime Role로
수행합니다.
재기동 Smoke Test
RLS 활성 PostgreSQL에 DEMO_SEED_ENABLED=true로 서버를 기동합니다.
Demo/Test 로그인과 주요 화면 데이터를 확인합니다.
같은 DB/PVC를 유지한 채 서버 Pod를 재기동합니다.
두 번째 기동도 정상 완료되는지 확인합니다.
Demo/Test 회사·사용자·근로자·주요 운영 fixture의 중복이 없는지
확인합니다.
Demo/Test tenant 간 데이터 격리가 유지되는지 확인합니다.
권장 검증·배포 순서
이 이슈의 호환 변경과 #135를 한 번에 배포하지 않습니다.
이 이슈 구현 PR merge
RLS가 아직 활성화되지 않은 현재 환경에 먼저 배포
DEMO_SEED_ENABLED=true 상태의 최초/재기동 회귀 확인
#135를 최신 main에 갱신하고 RLS 활성화 migration을 포함한 임시
통합 branch 또는 동일 commit 조합을 준비
운영 DB가 아닌 격리된 새 PostgreSQL DB에서 다음 리허설 완료
Flyway 전체 migration 적용 및 validate
제한 Runtime Role 사용
DEMO_SEED_ENABLED=true 최초 기동
동일 DB 재기동
Demo/Test 로그인·fixture 멱등성·tenant 격리 확인
위 리허설이 통과한 경우에만 feat: PostgreSQL RLS 기반 사업장 2차 격리 활성화 #135 merge 및 RLS migration 배포
배포 직후 DEMO_SEED_ENABLED=true + 제한 Runtime Role + RLS enabled
상태에서 재기동 Smoke Test
이상이 없으면 Seed 활성 상태를 유지
PR #135가 먼저 배포되어야 하는 긴급 상황에서는
DEMO_SEED_ENABLED=false를 임시 운영 우회책으로 사용할 수 있지만, 이
이슈가 배포·검증되기 전에는 Seed를 다시 true로 전환하지 않습니다.
이번 이슈에서 하지 않는 것
#135의 RLS policy 자체 변경
새로운 tenant isolation 모델 도입
Runtime DB Role 권한 완화
Flyway RLS 활성화 migration 추가/변경
Demo fixture 내용의 대규모 개편
Demo/Test 데이터 초기화 또는 재생성 정책 변경
기존 PostgreSQL PVC 데이터 삭제
production profile에서 Demo Seed 활성화
Infra Secret 원문 또는 DB credential 변경
연계
한 줄 목표
PostgreSQL RLS가 활성화된 제한 Runtime DB Role 환경에서도
DEMO_SEED_ENABLED=true를 유지한 채 Demo/Test Seed가 최초 기동과 동일DB 재기동 모두 정상·멱등하게 수행되도록 Demo Seed의 tenant context와
transaction 경계를 정리합니다.
현재 배포 전제
이 이슈는 아직 배포되지 않은 신규 환경을 준비하는 작업이 아닙니다.
서비스 중입니다.
SPRING_PROFILES_ACTIVE=dev로 실행 중입니다.DEMO_SEED_ENABLED=true이며 애플리케이션 기동·재기동 시Demo Seed가 실행됩니다.
DB/PVC를 그대로 유지한 재기동에서도 호환성을 보장해야 합니다.
RLS를 우회하지 않는지는 현재 dev 배포 DB의 live catalog 기준으로
별도 확인합니다.
왜 필요한가요?
PR #135는 PostgreSQL RLS를 활성화하여 애플리케이션의
company_id범위조건에 더해 DB가 다른 사업장의 행을 한 번 더 차단하도록 합니다.
현재 배포 환경은
DEMO_SEED_ENABLED=true이며 Demo/Test fixture를startup seed로 유지하고 있습니다. 하지만 현재 Demo Seed runner는 RLS가
활성화된 제한 Runtime Role과 호환되지 않습니다.
PR #135에서 수행한 수동 검증에서는 RLS 활성화 후 Seed를 켠 상태로
재기동할 때 다음 흐름으로 실패했습니다.
company를 조회WITH CHECK에 의해 SQLSTATE42501로 차단특히 RLS Flyway migration은 Seed runner보다 먼저 commit되므로, 이
상태에서 Pod가 기동에 실패해도 DB에는 RLS가 활성화된 상태가 남습니다.
단순 image rollback만으로 migration을 되돌릴 수 없습니다.
현재의 임시 우회책은 #135 배포 전에
DEMO_SEED_ENABLED=false로 변경하는것이지만, 이 경우 기존 데이터는 유지되더라도 재기동 시 Demo/Test
fixture의 자동 복구·보충 기능을 사용할 수 없습니다.
따라서 배포 환경에서 Demo Seed를 계속 활성화하려면 PR #135보다 먼저 Seed
자체를 RLS-aware하게 만드는 별도 호환 변경이 필요합니다.
현재 대상
현재 startup Demo Seed의 주요 단계는 다음 세 runner입니다.
DemoAuthSeedRunnerDemoWorkerSeedRunnerDemoOperationalSeedRunner현재 구조에서는 Demo/Test 두 회사에 대한 Seed가 각 runner의 큰
transaction 경계 안에서 함께 처리될 수 있어, RLS 활성 환경에서 회사별
tenant context를 안전하게 적용하기 어렵습니다.
작업 범위
1. Demo/Test 회사별 transaction 분리
분리합니다.
조회·생성·수정하지 않습니다.
실패하면, 성공한 회사의 commit은 유지하고 실패한 회사만 rollback한
뒤 startup 전체를 실패 처리합니다.
2. transaction-local tenant context 적용
company_id를 DB tenantcontext에 설정합니다.
company존재 여부 조회·생성처럼 RLS 적용 대상에 접근하기전에도 필요한 tenant context가 설정되어 있어야 합니다.
방식으로 적용합니다.
app.company_idtransaction-local tenant DBcontext 계약을 재사용합니다.
만들지 않습니다.
3. transaction 실행 구조 정리
@Transactionalself-invocation에 의존하지않습니다.
Bean,
TransactionTemplate또는 동등한 구조를 사용합니다.순서를 테스트로 보장합니다.
누출되지 않음을 검증합니다.
4. 기존 Seed 멱등성 유지
데이터가 중복 생성되지 않습니다.
유지합니다.
DEMO_SEED_ENABLED=false일 때 Seed가 실행되지 않는 기존 동작은변경하지 않습니다.
구현 원칙
이번 작업은 RLS를 약화시키지 않고 Seed를 기존 tenant 계약에 맞추는
방향으로 구현합니다.
다음 방식으로 문제를 우회하지 않습니다.
SUPERUSER또는BYPASSRLS부여DISABLE ROW LEVEL SECURITYSeed도 실제 Runtime과 같은 tenant isolation 원칙을 따라야 합니다.
완료 조건
자동 테스트
DEMO_SEED_ENABLED=true최초기동 성공
조회됨
성공한 다른 회사 transaction의 결과는 다음 재기동에서 멱등하게
재사용됨
PostgreSQL 제한 Role 검증
다음 검증은 table owner/superuser가 아닌 실제 제한 Runtime Role로
수행합니다.
rolsuper=false,rolbypassrls=false이고 tenanttable owner가 아님
DML·sequence·bootstrap 함수 권한만 부여됨
처리됨
42501로 startup이 실패하지 않음재기동 Smoke Test
DEMO_SEED_ENABLED=true로 서버를 기동합니다.확인합니다.
권장 검증·배포 순서
이 이슈의 호환 변경과 #135를 한 번에 배포하지 않습니다.
DEMO_SEED_ENABLED=true상태의 최초/재기동 회귀 확인main에 갱신하고 RLS 활성화 migration을 포함한 임시통합 branch 또는 동일 commit 조합을 준비
DEMO_SEED_ENABLED=true최초 기동DEMO_SEED_ENABLED=true + 제한 Runtime Role + RLS enabled상태에서 재기동 Smoke Test
PR #135가 먼저 배포되어야 하는 긴급 상황에서는
DEMO_SEED_ENABLED=false를 임시 운영 우회책으로 사용할 수 있지만, 이이슈가 배포·검증되기 전에는 Seed를 다시
true로 전환하지 않습니다.이번 이슈에서 하지 않는 것
연계
DEMO_SEED_ENABLED=true유지 조건에서의 선행 배포게이트