docs: 탈퇴 처리에 AI 파생 데이터 무효화 추가 (§3.6) - #14
Conversation
AI 파트 지적 반영. §3.6 처리 대상 표에 record·context 소프트 삭제는 있었으나 AI 파생 데이터 처리가 빠져 있었다. - ai.context_ai_state — 두 status를 CANCELLED로 전이 - ai.context_embedding — is_deleted = true 표시 물리 삭제(파기)가 아니라 무효화 표시다. CANCELLED는 진행 중인 AI 작업을 취소해 늦게 도착한 결과의 저장을 막고, is_deleted는 검색 제외와 물리 삭제 대상 식별을 담당한다. 물리 삭제 시점은 개인정보 정책 소관이라 명세 밖이다. 두 컬럼 모두 Spring이 변경한다(05 §12.3). ai.context_keyword는 keyword_status CANCELLED로 조회에서 자동 제외되므로 별도 처리가 필요 없다(05 §9). 근거는 07_ERD §5이며, Record 삭제(5.6·5.7)에도 같은 처리가 적용된다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
AI 파트 회신 반영.
- CANCELLED 전이에 가드를 걸지 않는다. COMPLETED·FAILED도 덮는다(05 §11.1).
context_keyword에는 is_deleted에 해당하는 컬럼이 없어 키워드 조회 제외를
오직 keyword_status = CANCELLED가 담당한다. COMPLETED를 남기면 임베딩
검색에서는 걸러지지만 키워드 조회에서 탈퇴 사용자의 키워드가 노출된다
- is_deleted UPDATE의 영향 행이 0이어도 오류로 처리하지 않는다.
Embedding 생성 전에 삭제된 경우가 정상 경로다
- 05 §7의 embedding_status IN ('PENDING','PROCESSING') 가드는 FastAPI의
작업 선점용이라 Spring의 CANCELLED 전이와 무관하다. 혼동을 막기 위해
실행할 SQL을 그대로 명시했다
- Finalizer가 CANCELLED를 FAILED로 덮을 수 없다는 반대 방향 보호도 기재
- context_keyword 자동 제외 근거를 §9에서 §9·§11.2로 보강
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@colosair 답변 감사합니다. 두 건 다 반영했습니다. ②
|
| 테이블 | 현재 | 필요 |
|---|---|---|
ai.context_embedding |
백엔드 DELETE만 | 백엔드 UPDATE (is_deleted) |
ai.context_ai_state |
행 없음 | 행 추가 + 백엔드 UPDATE (두 status) |
ai.context_keyword |
백엔드 DELETE만 | 백엔드 쓰기 없음, 읽기 조인만 |
06의 "즉시 파기"·"HNSW" 서술(§1.1, §2.x, §6.x, §7.x 네 군데)도 같은 정정 대상입니다.
back#28의 제 서술은 별도로 정정 코멘트를 달았습니다. 근거로 삼은 게 06 §1.3이었어서, 그 문서가 고쳐지면 같은 오해가 반복되지 않을 것 같습니다.
리뷰 요청 드렸습니다. 확인 부탁드립니다.
colosair
left a comment
There was a problem hiding this comment.
AI 파트입니다. 확인이 늦었습니다 — 승인합니다.
코드와 대조했습니다. 문서가 선언한 *"CANCELLED가 다른 모든 상태보다 우선한다"*가 실제로 강제됩니다.
# app/repository/ai_state_repo.py
async def complete(...): WHERE context_id = $1 AND {col} = 'PROCESSING'
async def fail(...): WHERE context_id = $1 AND {col} = 'PROCESSING'
"""PROCESSING 가드로 CANCELLED를 덮지 않는다."""백엔드가 CANCELLED로 전이한 뒤에는 워커의 완료·실패 쓰기가 전부 rowcount 0으로 떨어집니다. try_start()도 status IN ('PENDING','PROCESSING')이라 재선점하지 못합니다. fail()의 docstring에 그 의도가 명시돼 있습니다.
COMPLETED도 덮는다는 판단이 맞습니다. context_keyword에 is_deleted에 해당하는 컬럼이 없어 키워드 조회 제외를 keyword_status가 단독으로 담당한다는 근거도 정확합니다. COMPLETED를 남기면 임베딩 검색에서는 걸러지지만 키워드 조회에서 노출된다는 지적 그대로입니다.
is_deleted UPDATE의 영향 행이 0이어도 정상이라는 것도 맞습니다. 워커의 context_embedding UPSERT는 ON CONFLICT (context_id) DO UPDATE로 embedding·embedding_profile만 덮고 is_deleted는 건드리지 않으므로, 늦게 도착한 INSERT가 무효화 표시를 되돌리지 않습니다.
소유 경계도 Team-PinLog/back#61에 답한 내용과 일치합니다. 두 컬럼은 백엔드가 직접 씁니다(06 §1.3 쓰기 매트릭스). AI 파트가 추가로 구현할 것은 없습니다 — 차단 방어선이 이미 코드에 있고, 빠진 것은 플래그를 켜는 쪽뿐이었습니다.
참조 절 번호도 확인했습니다. 05 §9·§11.1·§11.2·§12·§12.3·§6.4가 현재 main에서 전부 유효합니다. 방금 병합된 docs#21이 §14 위주로 고쳐 절 번호가 밀리지 않았습니다.
관측 한계 하나만 기록해 둡니다. 이 PR의 문제는 아닙니다.
경합으로 rowcount가 0이 될 때 — 즉 취소가 진행 중이던 작업을 실제로 잘랐을 때 — 워커가 아무 로그도 남기지 않습니다. 동작은 안전하지만 사후에 *"취소가 무엇을 잘랐는지"*를 확인할 방법이 없습니다. AI 파트의 관측 공백이고 dev 배포 계약(Team-PinLog/ai#32)에서 인프라에 이미 고지했습니다.
배경
AI 담당자 지적으로
08 §3.6 회원 탈퇴의 처리 대상 표에 AI 파생 데이터 처리가 빠져 있는 것을 확인했습니다.record·context소프트 삭제만 적혀 있어, 그대로 구현하면 임베딩과 AI 작업 상태가 방치됩니다.변경
§3.6처리 표에 두 행을 추가하고, 상세 소절을 신설했습니다.ai.context_ai_stateCANCELLED로 전이ai.context_embeddingis_deleted = true표시물리 삭제가 아니라 무효화 표시라는 점을 명시했습니다.
CANCELLED— 진행 중인 AI 작업을 취소해 늦게 도착한 결과가 저장되는 것을 차단is_deleted— 검색 제외 + 물리 삭제 대상 식별덧붙인 것:
ai.context_keyword는 별도 처리 불필요 —keyword_status가CANCELLED가 되면 조회에서 자동 제외됩니다 (05 §9)근거는
07_ERD §5 삭제 방식 요약입니다.이 PR 범위 밖 —
06_데이터모델에 남은 문제AI 담당자가 이미 정정 요청했다고 하셨는데, "즉시 파기"·"HNSW" 문구 외에 하나가 더 있습니다.
06 §1.3쓰기 매트릭스가 백엔드 권한을 이렇게 규정합니다.ai.context_embeddingai.context_keyword그런데 실제로 백엔드가 해야 하는 것은 UPDATE(
is_deleted = true, status →CANCELLED)입니다. 그리고ai.context_ai_state가 매트릭스에 아예 없습니다.문구 수정만으로는 안 되고 권한 계약 자체가 바뀌어야 합니다.
ai.context_embedding— 백엔드 UPDATE 필요 (is_deleted)ai.context_ai_state— 매트릭스에 행 추가 + 백엔드 UPDATE 필요 (두 status)ai.context_keyword— 백엔드 쓰기 불필요. 읽기 조인만06은 제 소유가 아니라 손대지 않았습니다. 정정하실 때 이 부분도 함께 봐주세요.🤖 Generated with Claude Code