Skip to content

친구 데이터 전용 접근점 분리 — 계정 전환 제거 + 일지 월 총중량 0kg 수리

  • 기간: 2026-08-31 (하루)
  • 랜딩: PR #1031 (Phase 0~3 묶음, CI 1회) · 마이그레이션 6개 Production 적용
  • 설계서: 이슈 #1028 본문(분석·Phase 계획·예상 효과)
  • 정본: 친구·그룹 접근 계약 — 전용 접근점 원칙·viewer/target 분리·전환 금지·접근점 장부
  • 도구: Production 드라이런(마이그레이션 전문 적용→원자 롤백 + 행동 검증 8종), 정본 추출-치환 빌더(schema.sql 마지막 정의 기반 재발행)
  • 게이트: tests/react/friendAccessSqlContract.test.mjs — 친구/그룹 노출 함수 이름 스윕(전환 부재·게이트·장부 등재 상시 단언)
  • 버그리포트: BUG-052 (친구 일지 월 총중량 0kg)
  • 계약: 본인 RPC 시그니처·payload 전부 불변(클라 수정은 일지 월 합계 배선뿐) — strict adapter 무접촉

Phase 현황

Phase내용상태
Phase 0전환 52곳 전수 장부 + 친구·그룹 접근 계약 문서 신설
Phase 1친구 일지 월 총중량 수리(summary.volume + 하드코딩 0 제거)
Phase 2-1~2-5접근점 5개 엔진 분리·전환 제거 (PR·대시보드·볼륨·피드·그룹 세션)
Phase 3전환 재유입 방지 상시 게이트 + remote-schema 핀 갱신

1. 배경

친구 스코프(8/25, #792)는 랜딩·일지·리포트·피드 4화면으로 친구 데이터를 보여준다. 데이터 공급의 4곳은 계정 전환 방식 — 팔로우 게이트 통과 후 트랜잭션 로컬로 JWT sub 클레임을 대상 유저로 바꿔 본인용 함수를 그대로 실행(8/23 친구 리포트 v1 기법) — 이었고, 일지 달력·즐겨찾기 2곳만 전용 조회였다. 그룹 멤버 세션 상세(#847)도 같은 전환 기법을 썼다.

2. 문제 제기

  1. 오너 보고(2026-08-31): "친구 일지 탭의 월별 중량 총합이 전부 0kg." — 조사 결과 친구 달력 응답에 중량이 아예 없고 클라이언트가 volume: 0을 하드코딩(BUG-052).
  2. 구조 문제(조사 중 정리, 오너 결정으로 확정): 전환 방식은 ①원 함수가 돌려주는 전부가 자동으로 친구에게 공개된다 — 8/26 실사고: 피드 원 함수가 집계형으로 바뀌자 제3자 기록이 노출(20260821790000 교정) ②Supabase 내부 동작(auth.uid()가 어느 설정을 먼저 읽는지)에 의존 — 바뀌면 무음 오작동 ③전환 중 쓰기가 생기면 대상 명의로 기록될 위험 ④열람자 종속 값(liked_by_me 등)이 대상 관점으로 계산되는 잠재 부정확.

3. 해결 방안

원칙(오너 결정 D1, 2026-08-31): 다른 계정의 호출에 응답하는 지점은 계정 전환 없이 전용 접근점으로 분리한다. 계산이 비싸면 내부 엔진(대상 유저 명시 인자)을 본인 경로와 공유한다. D2: 통합 단일 함수(파라미터 분기, B안) 대신 입구 2개·엔진 1개(A안) — 사고 시 친구 문만 긴급 차단(8/26 실사용), 표면별 노출 축소, 본인 경로 무접촉, 접속 로그 식별이 근거.

접근: 데이터 종류마다 ①내부 엔진 …_engine(p_user_id, …)(기존 본문에서 auth.uid()만 인자 치환, 실행 권한 전면 회수) ②본인 문(시그니처·payload 불변, engine(auth.uid()) 위임) ③친구/그룹 문(게이트 → engine(p_user_id) 직결). 열람자 종속 값이 있으면 엔진이 p_viewer를 별도 인자로 받는다.

4. 적용한 내용

  • Phase 0: 전환 52곳 분류(친구/그룹 5 vs 내부 배치·인입·정비 ~47곳은 범위 밖 명시), docs/contracts/friend-access.md 신설 + 사이드바 등록.
  • Phase 1: get_following_calendar_month_v1summary.volume(본인 일지 정본 user_calendar_day_summaries 구간 합) 추가, friendScopeStore/mobileApp 배선, pgTAP +1.
  • Phase 2 (마이그레이션 5개, 각각 자가 검증 DO 동반):
    • 2-1 PR 오버뷰: get_pr_overview_engine_v1 신설(하위 헬퍼는 이미 인자화 — 1함수 치환).
    • 2-2 홈 대시보드: build_home_dashboard_core_v2 (uuid,date) 재서명(drop 후 재생성) + get_home_dashboard_engine_v1(누적·레벨·PR 카운트·반영 계획 합류 포함) 신설.
    • 2-3 볼륨 리포트: 체인 5층(v1/v2/v3_core·annual_v3·선택자) 전부 p_user_id 관통 + get_volume_overview_engine_v1. 친구 문은 engine(대상, as_of, 4) 직결.
    • 2-4 프로필 피드: get_profile_feed_page_engine_v1(p_viewer, p_author) — 열람자/작성자 분리. p_author 지정 = 그 작성자 본인 글만(친구 페이지, 교정판의 6페이지 보정 루프 폐기), 미지정 = 열람자 집계(내 피드). 구 get_profile_feed_v2_engine drop.
    • 2-5 세션 상세: build_session_detail_payload_v1(게이트 없는 빌더) + 본인 문(소유자/팔로워 게이트)·그룹 문(동일 그룹 게이트) — 전환 제거.
  • Phase 3: friendAccessSqlContract.test.mjs(이름 스윕이라 새 접근점 자동 포착) + check-supabase-remote-schema.mjs 볼륨 체인 핀 신구조·전환 부재 술어·v2_engine 은퇴 등재. SQL 계약 테스트 12파일을 "계산 본문 = 엔진 소유"로 재조준.
  • 작업 중 드러난 것: ①잠정 장부의 오귀속 2건(volume_level_progress_v1·get_home_dashboard — 실제는 인접 정비 루틴의 전환) 정밀 재조사로 교정 ②tests/support/schemaSql.mjs의 함수 열거가 베이스라인 인용형만 세던 것을 비인용형까지 확장 ③전환 시절 친구 피드·그룹 세션의 열람자 종속 값(liked_by_me 등)이 대상 관점으로 계산되던 잠재 부정확을 함께 교정.

5. 적용 결과

항목
친구 일지 월 총중량항상 0kg실제 값 — Production 실측 성근 8월 49,032kg == 일 롤업 합
친구/그룹 접근점의 계정 전환5/7곳 사용0곳 (행동 드라이런에서 전 과정 sub GUC 미접촉 확인)
친구 응답 == 본인 응답전환 결과로 성립엔진 공유로 구조적으로 성립 — 리포트·PR 정확 일치(765,269kg 등) 실측
친구 피드 제3자 노출 방어전환+자기글 필터 루프(사후 교정)처음부터 대상 글만 질의(20장 전부 대상 본인 글 실측)
친구 피드 liked_by_me대상 유저 관점(부정확)실제 열람자 관점
전환 재유입 방지규칙 없음상시 게이트(스윕 테스트) + remote-schema 술어
검증로컬 게이트 전체 green(유닛 2,267) · Production 스키마/행동 드라이런 · CI 1회

미검증: pgTAP·e2e는 CI에서 실행(머지 게이트), 화면 시각 품질은 자동 검증 범위 밖.

6. 이번 개선으로 향상된 것

  • 원 함수 확장이 친구 노출을 조용히 넓히는 구조(8/26 사고의 뿌리) 소멸 — 노출은 접근점 장부와 게이트가 명시적으로 소유.
  • Supabase 내부 동작 변화(auth.uid() 구현)에 대한 의존 제거 — 전환 자체가 없다.
  • 사고 대응 수단 유지: 친구 문 실행 권한 회수 = 본인 화면 무중단 긴급 차단.
  • 본인/친구 화면 숫자 동일성이 "같은 엔진"이라는 구조로 보장되고, 그 구조 자체가 테스트 계약이 됐다.

남은 것

  • 내부 기계(통계 잡 처리·인입·정비 ~47곳)의 전환은 이 트랙 범위 밖 — "다른 계정의 호출 응답"이 아닌 서버 자신의 배치 작업(계약 문서 §4에 명시).
  • 그룹 멤버 세션의 동반 RPC strength_set_metrics_map_json은 종전대로 팔로워 게이트(그룹 동료 확장은 별건).