Skip to content

refactor(db): auth.users FK 이관 + auth.uid() stub (로컬 Postgres 호환) #267

@cocoyoon

Description

@cocoyoon

배경

기존 스키마가 auth.users 테이블과 auth.uid() 함수를 참조한다. 로컬 순정 Postgres 에는 auth 스키마 자체가 없어서 migration 실행 불가. 이 문제를 근본 해결하고 prod 에서도 같은 구조로 통일.

Scope

1. auth.users FK → public.users 이관

기존 REFERENCES auth.users(id) 를 모두 REFERENCES public.users(id) 로 변경.

근거: public.users 는 앱 도메인 엔티티이며, GoTrue trigger 가 auth.userspublic.users 로 UUID 동기화하므로 1:1 매핑됨. 앱 레벨 FK 는 public.users 를 가리키는 것이 의미적으로 더 올바름.

대상 (pre-check 로 확인):

  • public.post_magazines.approved_by
  • 기타 SELECT ... FROM pg_constraint WHERE contype='f' AND confrelid='auth.users'::regclass 결과

Pre-check SQL (migration 적용 전 반드시 실행):

-- approved_by 값이 모두 public.users 에 있는지 확인
SELECT id, approved_by FROM public.post_magazines
 WHERE approved_by IS NOT NULL
   AND approved_by NOT IN (SELECT id FROM public.users);
-- 결과 0 row 여야 안전. 아니면 데이터 정합성 복구 선행.

2. auth.uid() stub (로컬 전용, prod 무영향)

-- SeaORM migration 의 raw SQL
DO $$
BEGIN
    IF NOT EXISTS (SELECT 1 FROM pg_proc 
                   WHERE proname='uid' 
                     AND pronamespace='auth'::regnamespace) THEN
        CREATE SCHEMA IF NOT EXISTS auth;
        CREATE OR REPLACE FUNCTION auth.uid() RETURNS uuid 
          LANGUAGE sql STABLE AS $fn$ SELECT NULL::uuid $fn$;
    END IF;
END $$;
  • 로컬: auth 스키마 없음 → stub 생성 → RLS policies 가 compile-pass
  • Prod: Supabase Auth 가 실제 auth.uid() 제공 → 조건 실패 → skip (덮어쓰기 없음)

3. JWT verify 후 public.users upsert (middleware)

로컬에서 원격 Supabase Auth 로 로그인한 유저의 UUID 가 로컬 public.users 에 없으면 자동 생성.

// api-server/src/middleware/auth.rs 수정
pub async fn auth_middleware(...) {
    let claims = verify_supabase_token(token, ...).await?;
    let user = User::from_claims(claims)?;
    
    // 신규: public.users 에 없으면 upsert
    upsert_user_if_missing(&state.db, &user).await?;
    
    request.extensions_mut().insert(user);
    Ok(next.run(request).await)
}

Files

  • packages/api-server/migration/src/m20260501_000001_decouple_auth_users_fk.rs (신규)
  • packages/api-server/migration/src/m20260501_000002_auth_uid_stub.rs (신규)
  • packages/api-server/migration/src/lib.rs (등록)
  • packages/api-server/src/middleware/auth.rs (수정 — user upsert)
  • packages/api-server/src/services/user/ 또는 유사 위치 (upsert 로직)

Idempotency

모든 DDL:

  • FK: DROP CONSTRAINT IF EXISTSADD CONSTRAINT
  • 함수: CREATE OR REPLACE FUNCTION (단 stub 은 조건문 안에)
  • 스키마: CREATE SCHEMA IF NOT EXISTS

Prod 영향 (안전 보장)

  • auth.uid() stub 은 IF NOT EXISTSprod 실제 함수 덮어쓰지 않음
  • FK 이관은 DROP IF EXISTS + ADD 패턴 → 재적용 안전
  • pre-check SQL 통과 후에만 배포

Acceptance

  • 로컬 순정 Postgres 에서 api-server 기동 시 Migrator::up() 성공
  • prod 에서 migration 재적용 시 no-op (기존 스키마 변경 최소)
  • JWT 로그인 후 public.users 에 자동 row 생성 확인
  • RLS policies 가 로컬/prod 양쪽에서 compile pass

연관

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions