Skip to content

종목 등록 프로시저 확립 · 정체성 체계 재설계 (2026-09-01)

  • 기간: 2026-09-01 (설계 대화·오너 결정 D1~D11 + 구현, 1세션)
  • 랜딩: PR #1068 (Phase 1) · PR #1070 (Phase 2·3 묶음) · PR #1072 (Phase 4-1) — 마이그레이션 20260901990000~993000, Production 적용·포스트체크 완료
  • 설계서: 이슈 #1060 본문 (오너 결정 D1~D8) + Phase 4 결정(D9~D11)·완료 쓰레드
  • 정본: supabase/migrations/20260901992000_brid_label_normalization_v1.sql (BRID 라벨 헌법·공식 전문 주석)
  • 도구: 없음 (신규 절차 없음 — §15 랜딩 직렬화·§16 검증 리듬 준수)
  • 게이트: pgTAP exercise_registration_identity_v2(20) · session_origin_columns_v1(6) · session_brid_issuance(21로 확장) + 구 BRID 계약 단언 5개 파일 갱신
  • 버그리포트: 없음 (구조 결함 예방 트랙 — 무음 전신 강등은 사고 보고 전 수리)
  • 계약: 관리자 등록 폼 필수 6항목(한글명·분류·기록 필드·타겟 부위 비율·움직임 패턴·[맨몸]체중 계수) / BRID 분류 라벨 헌법 3조 + 고정 5조각 문법

Phase 현황

Phase내용상태
Phase 1등록 본체 재구성 — 정체성 직발급·특성 직접 수신·이름 유일성·관리자 폼 개편✅ PR #1068 (단독 랜딩 — §16 지시 전)
Phase 2세션 출처 컬럼 이전 — 유입 경위를 정체성 문자열에서 분리✅ PR #1070
Phase 3BRID 라벨 정규화 — 분류 라벨 헌법 시행·수호 홀쭉화·slug 행동 소비처 정리✅ PR #1070
Phase 4-1세션 정체성 직발급 — 발급 통일 철학(D9·D10) 완결✅ PR #1072

1. 배경

관리자 종목 상세에서 타겟 부위·기능 분류·기록 필드가 전부 "—"로 비는 종목이 발견됐다(2026-08-31 오너 보고). 조사 결과 표시 문제가 아니라 등록 절차가 그 값들을 입력받을 수 없는 구조였고, 절차를 확립하는 설계 대화가 정체성(UUID·BRID·slug) 체계 재설계까지 확장됐다. 오너 결정 8건(D1~D8)이 이슈 본문에 기록됐다.

2. 문제 제기

등록이 핵심 특성을 못 받는다 — 무음 전신 강등

등록 함수는 타겟 부위 비율·움직임 패턴·기록 필드를 받지 않았다. 대신 "메인 타겟 부위" 텍스트를 7단어 표(가슴/등/어깨/팔/하체/코어/전신)에 대조했는데, 폼 안내문은 "대퇴사두, 둔근"처럼 근육명을 유도했다. 유저 예시: 관리자가 벤치프레스류 머신을 등록하며 부위 칸에 "대흉근"이라 적으면, 오류 없이 전신 100%·전신협응으로 분류되고 그 종목으로 운동한 유저의 리포트 육각형에서 가슴 볼륨이 전신으로 샌다. 거리+시간+칼로리 3원자 기계(로잉머신류)는 측정 단위 한 단어로 표현이 안 돼 등록 자체가 불가능했다.

정체성이 이름에 얽혀 있다

종목 UUID가 이름/slug의 해시로 발급됐다. 이름 정규화 규칙을 바꾸면 재발행 문제가 생기고, 개명이 정체성과 얽히며, 정식(slug 원문)과 커스텀(한글 압축 키)의 규칙이 서로 달랐다. 세션 쪽은 local:local-workout: 말더듬, group-board:<그룹>:<날짜>: 업무 정보 내장 등 정체성 문자열에 잡다한 정보가 세들어 살았고, 보드 완료 인원 매칭이 그 문자열 앞부분 대조로 돌았다(한 글자 어긋나면 무음 누락).

3. 해결 방안

원칙(오너 결정): 정체성 = 무작위 UUID 하나(D1). 중복 방지는 전담 장치(D2 — 요청 영수증·이름 압축 키 유일성). 유입 경위는 컬럼(D3). 기존 UUID 전량 유지(D4). BRID는 분류 라벨 헌법 3조(D5 — ①UUID를 감싸 역할 표시 ②키로 사용 금지 ③정책 따라 재구성 가능) + 고정 5조각 문법(D6 — brid:<타입>:<출처>:<소유자>:<UUID>). 등록 필수 6항목(D7). slug·메인/보조 타겟 부위·측정 단위 입력·BRID 해시 파생 퇴역(D8).

접근: Phase 1은 등록 함수·관리자 폼(클라+서버), Phase 2는 서버 단독(세션 정체성이 아직 source_ref 해시라 클라 송신 불변 — 트리거 파생으로 구·신 클라 모두 수용), Phase 3은 라벨 정규화 트리거 + 전 행 백필.

4. 적용한 내용

Phase 1 — 등록 본체 (PR #1068)

  • 등록 함수 v2: UUID 직발급, target_muscles·movement_pattern 직접 수신(구 페이로드는 종전 파생), 이름 압축 키 유일성(정식 전역/커스텀 유저별, 한·영·표기까지), 정식 client_request_id 필수, slug 자동 생성
  • 관리자 폼: 기록 필드 토글·부위 비율 편집기(합계 100 실시간 검증)·움직임 패턴 선택 신설, 측정 단위·메인/보조 타겟 부위 입력 퇴역. 편집 경로에서 세 특성 수정 가능
  • 작업 중 드러난 것: ① 정체성 수호 트리거가 직발급을 거부(1차 CI 적발) — 과도기 라벨 수용 v2로 갱신 ② 커스텀 생성 화면은 부위 픽커 6단어가 전부 파생 표 안이라 변경 불요 판정

Phase 2 — 세션 출처 컬럼 (PR #1070)

  • sessions.origin_kind/origin_ref 신설 + 파생 트리거(group-board 접두어 → 컬럼 이관, 명시 출처 우선, 형식 불량 = 출처 없음·저장 비차단) + 백필(잔존 0 포스트체크)
  • 보드 완료 매칭: 접두어 스캔 → 출처 컬럼 조회. 기존 보드 계보 pgTAP 8단언 무변경 통과 = 행동 보존 증명

Phase 3 — BRID 라벨 정규화 (PR #1070)

  • 라벨 v1을 정규화 트리거로 시행: 기입값이 무엇이든 현행 공식으로 덮어씀. generated 컬럼 대신 트리거를 택한 근거 — 과거 시드·인입 엔진이 brid를 직접 기입하며, generated는 그 전부를 오류로 만든다(거대 함수 재발행 강제). 정책 개정 = 공식 교체 + 재백필 1회
  • 종목·세션 전 행 라벨 일제 전환(UUID 불변 — 재발행 아님). 수호 홀쭉화(brid 조항 퇴역), 구 형식 CHECK 2종 제거, 클라 slug 행동 소비처 정리
  • 작업 중 드러난 것: 구 BRID 계약을 단언하던 pgTAP이 5개 파일에 흩어져 있었다(CI가 3회에 걸쳐 적발) — 전부 라벨 계약으로 갱신. ci-wait가 푸시 직후 옛 run을 붙잡는 경합 2회(SHA 명시 대기로 우회)

5. 적용 결과

항목
부위 텍스트 미매칭 시무음 전신 100% 강등입력 단계 검증 오류(원인 문구)
부위 비율(60/25/15) 입력불가등록·편집 모두 가능
3원자 유산소 기계 등록불가가능
정식 등록 필수 입력영문 slug 필수한글명만으로 가능(slug 자동)
이름 변경과 정체성해시로 얽힘무관(자유 변경)
보드 완료 매칭문자열 접두어 대조(형식 어긋나면 무음 누락)출처 컬럼 조회
BRID3계보 이형 문자열, id와 해시로 결합고정 5조각 라벨, 전 행 단일 문법, 정규화 우회 불가
미검증관리자 폼 실화면 조작감(자동 e2e 없음 — 시각 품질은 사람 눈 영역)

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

  • 등록 절차가 계약이 됐다: 필수 6항목이 폼·컨트롤러·서버 3층에서 같은 검증으로 관통되고, 조용히 잘못 분류되는 경로가 소멸했다
  • 정체성·이름·라벨의 역할 분리가 구조로 고정됐다: 정체성은 불변 UUID, 이름은 자유(유일성은 압축 키 전담), 라벨은 정책 따라 갈아끼우는 파생값 — "재발행"이라는 개념 자체가 사라짐
  • 확장 원칙이 명문화됐다: 새 기능은 라벨 조각을 늘리지 않고 ①어휘 추가 ②출처 종류 추가로만 흡수(세션 공유·그룹 소유 개체가 와도 문법 불변)

Phase 4 (추가 오너 결정 D9~D11, 2026-09-01)

세션 해시 유지 상신은 반려됐다 — D9: UUID·BRID가 발급되는 모든 개체는 동일 철학(무작위 직발급·중복 수렴은 전담 장치·라벨은 파생). D10으로 세션 정체성 트리거를 직발급 v3으로 교체 — 실측상 저장 엔진(자연키 명시 조회+잠금+영수증)·인입 엔진(자연키 upsert)·유니크 인덱스가 이미 해시에 무의존이라 겉동작 불변(오프라인 재전송 = 여전히 한 세션). D11로 외부 인입 자리표시 종목은 현행 유지 + "무작위 발행 간주" — 파이프라인 밖에서 그 id를 재계산·해석하는 소비처 0(라벨 정규화로 봉인)이므로 대형 인입 엔진 재구조는 하지 않는다.

작업 중 드러난 것: 4-1 랜딩 CI에서 CASE-001·004가 "통계 드레인 무발화"로 케이스를 옮겨 다니며 실패. main 대조 실행(그린)·페이지 스냅샷·DB 왕복 프로브로 앱·서버 정상을 증명한 뒤, 원인을 즉시 저장(#1017) 이후 낡아 있던 e2e 관찰 리셋 배치(저장 유발 클릭 뒤)로 확정 — 직발급으로 세션 insert가 근소하게 빨라지며 잠복 경합이 상시 노출된 것. 리셋을 저장 유발 클릭 앞(CASE-002·015와 동일 배치)으로 교정했다.

남은 것

  • slug·primary_part·secondary_parts·measurement_type 컬럼 드롭: 배포 클라이언트가 직접 select하는 컬럼이라 read 호환 창(#524 generated 미러 전략) 필요 — 별도 후속 트랙
  • 클라이언트의 출처 명시 전송(보드 접두어 내장 중단): 세션 공유 기능 설계와 한 묶음이 자연스러움