feat(cafe24): 읽기 지연 보정("마지막 쓰기가 권위") + 상품 정보 패널

증상: 상세페이지를 적용해도 편집기에 수정 전 소스가 보이고 한참 뒤에야
반영됨. 원인은 우리 캐시가 아니라(전부 no-store) 카페24 관리자 API 가 PUT
뒤 한동안 GET 에서 예전 값을 돌려주는 읽기 지연. 예전 코드는 2.4초만
기다린 뒤 GET 값을 그대로 믿어 예전 소스 표시·지문 충돌 오판·예전 값
백업이 생겼다.

- 상세설명: 쓰기 성공 시 MANUAL/SCHEDULED revision 을 기준으로, 카페24 값이
  유예시간 안의 revision 중 하나와 같으면 지연(pending)으로 보고 마지막
  쓰기를 표시·지문 기준으로 쓴다. 모르는 값이면 외부 변경(external).
  store.resolve_description / db.revision_digests(md5) / 배너 2종.
- 적용(apply)은 유효 현재값으로 BACKUP·지문 대조·변경없음 판정. 재조회
  확인 결과는 감사로그에만 남긴다.
- 스칼라(상품명·가격·이미지·진열/판매): PUT 응답을 cafe24_products.
  last_write_snapshot(JSONB, 마이그레이션 004)에 남기고 GET 의 updated_date
  가 그보다 이전이면 스냅샷으로 덮어씀. 옵션/품목도 섹션별 스냅샷.
- 3분할 화면: 목록 | 편집기 | 상품 정보 패널(_side.html, /pane 이 두 조각을
  한 응답으로). routes_product_info.py JSON API — 상품명/판매가/공급가/
  소비자가, 대표이미지 업로드(POST /admin/products/images → PUT detail_image
  + image_upload_type=A), 옵션 생성/이름·썸네일·표시방식 수정/삭제, 품목
  자체코드·추가금액·진열·판매 일괄 수정. 화면은 PUT 응답으로 그린다.
- client.delete/timeout, products.upload_images·options·variants 래퍼.
- 유닛테스트 21건 추가(88 통과), 문서(CAFE24_MODULE 3-3/3-4, DATABASES,
  .env.example CAFE24_READ_LAG_GRACE_MIN) 갱신.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-18 18:07:42 +09:00
parent 8ea0db9245
commit 40766d805d
21 changed files with 2782 additions and 99 deletions
+3 -1
View File
@@ -303,7 +303,7 @@ DDL: `scripts/sql/cafe24_db_init.sql` (멱등). DB·역할(`cafe24_app`)·테이
| 테이블 | 용도 |
| --- | --- |
| `cafe24_oauth_tokens` | 쇼핑몰별 OAuth 토큰(`mall_id` UNIQUE). access/refresh 는 **Fernet 암호문**으로 저장. 상품관리 + 향후 주문관리가 공유 |
| `cafe24_products` | 상품 캐시(`product_no` UNIQUE). 목록/검색 속도용이며 source of truth 는 언제나 카페24 |
| `cafe24_products` | 상품 캐시(`product_no` UNIQUE). 목록/검색 속도용이며 source of truth 는 언제나 카페24. `last_write_snapshot`(JSONB, 마이그레이션 004) 에 카페24 PUT 응답을 섹션별(`product`/`options`/`variants`)로 남겨 **읽기 지연**(PUT 뒤 GET 이 한동안 예전 값을 돌려줌) 동안 화면 기준으로 쓴다 |
| `cafe24_product_revisions` | 상세페이지 HTML 버전(append-only). `revision_type` SYNC/DRAFT/**BACKUP**/MANUAL/SCHEDULED/ROLLBACK |
| `cafe24_product_schedules` | 예약 작업. `status` PENDING/PROCESSING/SUCCESS/FAILED/CANCELLED, 재시도·자동종료·복원 대상 포함 |
| `cafe24_audit_logs` | 누가 무엇을 바꿨나. worker 수행분은 `actor='SCHEDULER'` |
@@ -315,6 +315,8 @@ DDL: `scripts/sql/cafe24_db_init.sql` (멱등). DB·역할(`cafe24_app`)·테이
- 예약의 `restore_revision_id`**예약 실행 순간** 만든 BACKUP 을 가리킨다(예약 생성 시점 값이 아님).
- 일괄 예약은 상품 1건당 1행 + 공통 `parent_job_id` — 한 상품 실패가 나머지를 막지 않는다.
- 토큰 암호화 키는 `.env``CAFE24_TOKEN_SECRET`. **값을 바꾸면 기존 토큰을 복호화할 수 없어 카페24 재연결이 필요하다.**
- 기존 운영 DB 에는 마이그레이션 002·003·004 를 순서대로 적용한다(전부 멱등):
`docker exec -i postgres-db psql -U postgres -d cafe24_db < scripts/sql/cafe24_db_004_write_snapshot.sql`
### 운영 서버 초기화 (1회, 사용자 승인 후)