-- 0018 · place_reviews — 이용 후기(손님이 쓴 글). -- -- ★ 사진 칸이 없다 (2026-09-16 대표: "후기사진 X"). 사진을 받는 순간 우리가 남의 파일을 -- 호스팅하게 되고 — PRODUCT.md 6절 non-goal — EXIF·저작권·신고 대응이 전부 따라온다. -- ★ 별점 칸도 없다(회의 확정). 그래서 JSON-LD aggregateRating 도 만들지 않는다 — -- 자체 수집 후기는 구글 리치결과 대상이 아니다. -- ★ 손님이 남긴 이름은 표시용 한 조각뿐이다. 연락처는 받지 않는다 — 받으면 보관·파기가 따라온다. CREATE TABLE IF NOT EXISTS public.place_reviews ( review_id uuid PRIMARY KEY DEFAULT gen_random_uuid(), place_id uuid NOT NULL, body VARCHAR(1000) NOT NULL, nickname VARCHAR(40) NULL, -- 손님이 적은 표시 이름. 비면 '손님' status SMALLINT NOT NULL DEFAULT 1, -- ReviewStatus: 1=pending 2=published 3=rejected submitted_ip_hash VARCHAR(64) NULL, -- sha256(ip+소금). 원문 IP 는 남기지 않는다 published_at TIMESTAMPTZ NULL, published_version_id uuid NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted BOOLEAN NOT NULL DEFAULT FALSE ); -- 화면이 읽는 경로: 그 업장의 게재된 후기를 최신순. CREATE INDEX IF NOT EXISTS ix_place_reviews_published ON public.place_reviews (place_id, published_at DESC) WHERE deleted = FALSE AND status = 2; -- 운영 경로: 검수 대기 목록. CREATE INDEX IF NOT EXISTS ix_place_reviews_status ON public.place_reviews (status, created_at) WHERE deleted = FALSE;