종목 등록 프로시저 확립 · 정체성 체계 재설계 (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 3 | BRID 라벨 정규화 — 분류 라벨 헌법 시행·수호 홀쭉화·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 자동) |
| 이름 변경과 정체성 | 해시로 얽힘 | 무관(자유 변경) |
| 보드 완료 매칭 | 문자열 접두어 대조(형식 어긋나면 무음 누락) | 출처 컬럼 조회 |
| BRID | 3계보 이형 문자열, 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 미러 전략) 필요 — 별도 후속 트랙
- 클라이언트의 출처 명시 전송(보드 접두어 내장 중단): 세션 공유 기능 설계와 한 묶음이 자연스러움