PARA/03_Resources/R001_개발_레퍼런스(참고문서)/트러블슈팅/블로그 개발기 - 공개, 전체 문서 데이터 소스 비대칭.md

블로그 개발기 - 공개, 전체 문서 데이터 소스 비대칭

개요

홈 화면(/)의 좌측 태그 패널과, 개별 문서 페이지의 좌측 Tags 패널이 서로 다른 태그 목록을 보여줬다.

  • 홈: 블로그 117, 지식 79, it 77 … 공개 태그만
  • 문서 페이지: 일지 403, work 296, 커리어 84, MKGPFPJT-… 같은 비공개 업무 태그까지 노출
  • 게다가 공유 태그 카운트도 부풀려짐 — 지식 289(홈은 79), it 108(홈은 77)

처음엔 "공개 콘텐츠 유출"처럼 보였지만, 확인해 보니 관리자로 로그인한 상태에서만 나타났다.
비로그인 방문자에겐 정상적으로 공개 태그만 보였다. 즉 외부 유출이 아니라 관리자 화면의 표시 불일치였다.

원인

데이터 소스의 비대칭이 핵심이었다. 포스트 인덱스는 두 종류를 제공한다.

함수 반환 내용
getAllPosts()index.posts BlogPost[] 공개 전용
getAllIndexedPosts()index.allPosts IndexedPost[] 비공개 포함 전체
  • 홈 페이지getAllPosts()를 쓰므로 태그 트리가 항상 공개 전용.
  • 문서 페이지getAllIndexedPosts()(전체)를 가져온 뒤, 사이드바를 이렇게 빌드했다:
const visiblePosts = isAdmin ? posts : posts.filter(isPubliclyVisible);

관리자면 전체 문서 기준으로 사이드바를 만들기 때문에 비공개 태그가 그대로 흘러들어왔다.
게다가 사이드바의 태그 링크는 /?tag=X(공개 전용 홈)로 이동하므로, 관리자가 비공개 태그를 클릭해도 0건이 나오는 죽은 링크였다 — 관리자에게조차 쓸모없는 동작이었다.

해결

사이드바를 홈과 동일하게 항상 공개 전용으로 통일했다.

// 좌측 Tags 사이드바는 홈(getAllPosts=공개 전용)과 동일하게 항상 공개 문서만으로 빌드한다.
const visiblePosts = posts.filter(isPubliclyVisible);

단, 현재 보고 있는 글 자기 자신의 태그(본문 하단·primaryTag)는 기존처럼 canExposeTags = isAdmin || isPubliclyVisible(post)로 처리해, 관리자가 비공개 글의 태그는 계속 볼 수 있도록 유지했다.
(사이드바 = 전역 내비게이션 → 공개 전용 / 글 자체 태그 = 컨텍스트 → admin 노출 허용)

회귀 테스트도 추가했다 — "관리자 뷰어여도 사이드바에서 비공개 태그를 제외한다".

교훈

  • "공개 전용 목록"과 "전체 목록"을 구분해 제공하는 API가 있으면, 소비하는 쪽이 어느 것을 쓰는지가 곧 보안·일관성 경계가 된다. 같은 UI 요소(태그 트리)가 페이지마다 다른 소스를 쓰면 반드시 어긋난다.
  • "admin이니까 다 보여준다"는 분기는, 그 화면 너머의 동작(여기선 공개 전용 홈으로 가는 링크)과 맞물려야 의미가 있다. 맞물리지 않으면 노출만 늘고 기능은 죽는다.
  • 비슷한 비대칭으로 과거 Vercel fallback에서 공개 문서가 적게 집계된 사례도 있었다 — 인덱스의 공개/전체 구분은 이 프로젝트의 단골 함정 포인트다.

댓글

첫 번째 댓글을 남겨보세요.