탈인간중심주의 관점의 환경 컨퍼런스 웹사이트 - 비인간 존재들의 권리와 발언권을 고민하는 환경 컨퍼런스 플랫폼 (외주 프로젝트)
주요 기능 개발
1. 사용자 사이트
- 메인 히어로·포스터·스케줄·조직위원·장소 안내(Kakao Map) 등 전 페이지 구현
- 공지/FAQ/모집/아카이브 리스트·상세 기능 구축
- 홈페이지 특성 상 모바일 유저가 많을 것으로 예상해 반응형 디자인 설계
2. 관리자 대시보드
- 공지·FAQ·스케줄·아카이브 CRUD 관리 시스템 구축
- 검색/필터 UI 구조 통일 → 관리 효율 개선
- PDF 업로드 + Supabase Storage 연동
- 카카오 OAuth + Supabase Auth 관리자 인증 체계 구현
admin/*접근 시 AuthCheck를 통해 관리자 체크 및 접근 제어 처리
3. SEO·운영 품질 개선
- sitemap/robots/metadata 전면 개선
- 구글 서치 콘솔 연동 및 주요 키워드 상위 노출 유지
- 불필요 페이지 제거, 리다이렉트 및 유지보수 페이지 추가
- sitemap 특정 페이지에 dynamic metadata를 추가해
lastperiod를 매일 자동 업데이트 되도록 구현
트러블슈팅 경험
SEO 색인 누락 트러블슈팅 (도메인/리다이렉트 설정 오류)


Vercel 배포 후 가비아에서 구입한 도메인을 연결하면서, 실수로 기본 접근 도메인을
samulparliament.com이 아닌 www.samulparliament.com으로 설정해 리다이렉트를 잘못 구성했습니다.
초기 sitemap.txt, robots.txt, 서치콘솔, 네이버 서치어드바이저 모두 정식 도메인(samulparliament.com) 기준으로 세팅되어 있었기 때문에, 약 1~2주 동안은 정상적으로 상단 노출이 유지됐습니다.
하지만 이후 검색엔진 측에서 다음과 같은 문제로 색인이 끊기기 시작했습니다.
문제 원인
- 검색엔진은 samulparliament.com을 기준으로 크롤링하나, 실제 서버는
www.samulparliament.com → samulparliament.com이 아닌 반대 방향(또는 일관되지 않은 방향)으로 Redirect됨. - 일부 요청은 307 리다이렉트가 www → non-www가 아닌 non-www → www로 걸려 있었고 설정이 뒤섞여 canonical이 혼란 상태가 됨.
- 그 결과
- samulparliament.com 기준 색인이 생성되지 않음
- 서치콘솔에서 “페이지 색인이 생성되지 않음”, “404 오류 증가” 등의 메일 발생
- 검색엔진이 어느 URL을 ‘대표 URL’로 삼아야 하는지 판단하지 못한 상태가 됨
해결 과정
문제 원인을 확인한 뒤, 도메인 접근 경로를 완전히 일관된 한 방향으로 정리했습니다.
해결 조치

- 기존 설정
- samulparliament.vercel.app → www.samulparliament.com (307)
- 일부 접근: samulparliament.com → www로 리다이렉트되는 혼선 존재
- 수정 후
- www.samulparliament.com → samulparliament.com 로 307
- samulparliament.vercel.app → samulparliament.com 로 307
- 즉, 모든 경로를 non-www(samulparliament.com)로 강제 통일
결과
- 검색엔진이 canonical URL을 명확하게 인식
- 404 및 ‘색인 생성 불가’ 오류 사라짐
- 2~3일 내로 색인 정상화 → 주요 키워드 상단 노출 회복
- sitemap, robots의 정식 도메인과 실제 리다이렉트 규칙이 일관되게 맞춰짐
배운 점
- 도메인 연결 시 www / non-www 중 반드시 하나로 통일해야 한다.
- 리다이렉트가 한 방향으로만 흐르도록(canonical 방향) 설정해야 검색엔진 혼선을 방지할 수 있다.
- sitemap.txt, robots.txt, 서치콘솔 URL과 실제 서버 redirect 규칙이 일관되지 않으면 색인 누락이 발생할 수 있다.
Supabase RLS 설정 오류로 사용자 페이지 전체 데이터 조회 실패 트러블 슈팅
공지사항, FAQ 테이블에 관리자만 생성/수정/삭제할 수 있도록 RLS(Row Level Security)를 설정했으나,
일반 사용자(role=0) 또는 로그인하지 않은 사용자가 접근했을 때 데이터를 전혀 불러오지 못하고 무한 로딩이 발생하는 문제가 있었습니다.
초기에는 사용자 페이지는 모두 공개되어야 하기 때문에 단순 네트워크 오류로 보였으나,
서버 컴포넌트와 클라이언트 양쪽에서 동일하게 데이터가 응답되지 않는 패턴을 확인하면서
RLS 정책의 구조적 문제임을 파악했습니다.
문제 원인
- RLS 활성화 시 기본 정책은 “모든 접근 금지” Supabase에서 RLS를 켜면,
- 허용 정책이 없으면 `SELECT / INSERT / UPDATE / DELETE` 모두 거부됩니다.
- Insert/Update/Delete 정책만 role=1(Admin)에 대해 허용한 상태
초기 RLS 정책이 다음과 유사하게 구성되어 있었습니다
FOR INSERT, UPDATE, DELETEUSING (role = 1)
즉, 작성/수정/삭제 권한만 관리자에게 부여했고,
정작 SELECT(조회)에 대한 정책을 만들지 않은 상태였습니다.
- SELECT 정책이 없으면 Supabase는 다음처럼 동작합니다
- 로그인하지 않은 사용자(anon) → 차단
- 회원이지만 role = 0 → 차단
- 서버 컴포넌트에서 실행하는 익명 요청 → 차단
공지사항, FAQ처럼 누구에게나 공개되어야 하는 데이터임에도
SELECT 정책이 없으면 Supabase는 아예 row를 반환하지 않습니다.
그 결과 클라이언트는 null 또는 []를 받게되고 SSR/서버 컴포넌트도 데이터를 받지 못해 응답 대기 상태 지속되어 전체 페이지가 무한 로딩 상태 로 진입했던 것입니다.
해결 조치
1. 공개 데이터에 대해 SELECT 정책 허용
CREATE POLICY "public read"ON noticeFOR SELECTUSING (true);
2. 관리자 전용 쓰기 정책 분리
공지사항, FAQ는 관리자만 수정할 수 있도록 하기 위해
INSERT / UPDATE / DELETE 정책을 관리자 role(=1)로 명확하게 제한했습니다.
CREATE POLICY "admin write"ON noticeFOR INSERT, UPDATE, DELETEUSING (role = 1);
이 정책으로 다음을 보장할 수 있습니다:
- 일반 사용자(
role = 0) → 쓰기 작업 완전 차단 - 비로그인 사용자(anon) → 쓰기 작업 완전 차단
- 관리자(
role = 1) → 정상적으로 생성/수정/삭제 가능
3. 서버 컴포넌트에서 admin-only 요청은 Service Role Client로 수행
Next.js 서버 컴포넌트는 기본적으로 인증 정보가 없는 anon 상태로 Supabase 요청을 실행합니다.
따라서 관리자만 접근 가능한 쓰기 작업은 아래 방식으로 권한을 분리해 처리했습니다.
- 일반 사용자 페이지 →
anonclient 사용- RLS 기반
"public read"정책만 허용
- RLS 기반
- 관리자 페이지 →
service roleclient 사용- 환경변수로 관리되는 관리자 권한 클라이언트
- RLS를 우회해 admin 전용 쓰기 작업 수행 가능
이 구조로:
- public 페이지는 안전하게 전체 공개되고
- admin 페이지는 별도의 강력한 인증/권한 체계를 통해서만 접근 가능하도록 분리할 수 있습니다.
결과
- 공지/FAQ 페이지 데이터가 정상적으로 즉시 조회됨
- 무한 로딩 및 DB 응답 없음 문제 완전히 해결
- RLS 정책이 "공개 읽기 + 관리자 쓰기" 형태로 정리되며 보안성과 안정성이 강화됨
- 클라이언트 및 서버 컴포넌트 모두 일관된 권한 흐름으로 안정적으로 동작
배운 점
- Supabase RLS는 정책이 하나도 없으면 기본적으로 모든 접근을 거부한다.
- 읽기(SELECT) 정책도 반드시 명시적으로 허용해야 한다.
- 공개 데이터 테이블은 "읽기 정책"과 "쓰기 정책"을 분리해야 안전한 구조를 만들 수 있다.
- SSR(서버 컴포넌트)은 인증 정보가 없기 때문에 anon 요청으로 판단되어
RLS에 가장 민감하게 영향을 받으므로 설계 시 특히 주의가 필요하다.




