문제 상황 요약

A가 나가면 A만 나가고, B는 그대로 채팅 가능하며,

A가 다시 들어오면 이전 대화는 안 보이고 새 대화부터 이어져야함.

원인 분석

create policy "view only active participants"
on direct_messages for select
to authenticated
using (
  exists (
    select 1
    from direct_participants dp
    where dp.chat_id = direct_messages.chat_id
      and dp.user_id = auth.uid()
      and dp.left_at is null  -- 나간 사람은 즉시 차단해버림.
  )
);

→ 사용자가 left_at 이 있는 상태로 나가면 다시 들어와도, 새 direct_participants 레코드를 만들기 전까지는 메시지를 조회할 수 없음.

문제 해결 및 새로 다시 공부해서 짠 코드

목표는 안전한 접근 제어 / 퇴장·재참여 / 자동 정리 / 최소 성능 부하

1. 접근 제어 (RLS)

구분 대상 테이블 정책명 주요 조건 핵심 목적
SELECT direct_chats direct_chats_select_self_only auth.uid() IN (host_id, member_id) 본인만 방 조회 가능
INSERT direct_chats direct_chats_insert_host_member_only host/member 모두 실제 그룹 내 멤버 검증 무단 채팅방 생성 방지
UPDATE / DELETE direct_chats direct_chats_update_delete_self 본인만 수정/삭제 가능 권한 통제
구분 대상 테이블 정책명 주요 조건 핵심 목적
SELECT direct_messages direct_messages_select_if_active 참여 중(left_at IS NULL)인 사용자만 퇴장자는 열람 불가
INSERT direct_messages direct_messages_insert_if_active 참여 중(left_at IS NULL)인 사용자만 퇴장자는 메시지 작성 불가
UPDATE / DELETE direct_messages direct_messages_update_delete_own sender_id = auth.uid() 자기 메시지 관리만 허용
구분 대상 테이블 정책명 주요 조건 핵심 목적
SELECT direct_participants select_own_participant user_id = auth.uid() 본인 정보만 열람 가능
INSERT direct_participants insert_self_participant user_id = auth.uid() 본인만 참여 등록 가능
INSERT (예외) insert_by_host_for_member dc.host_id = auth.uid() 호스트가 상대방 강제 등록 허용
UPDATE update_self_participant_leave user_id = auth.uid() 본인 퇴장/재참여만 직접 수정

2. 데이터 무결성 & 중복 방지