# sort 현재 기준서 — 패키지 v226

전체 진행률: 63% (`test_list.md` 완료 12 / 전체 19)
문서 체계: 100%
마우스 제어 폐기: 100%
SQLite 기본 구조: 100%
공통 MEDIA_SAVED 로컬 처리: 100%
MySQL 추가 구조: 100%
IG·WS 공통 완료 코드 연결: 100%
IG·WS 실제 Windows 검증: 0%
로컬 repository·페이지 조회: 0%
서버 동기화 API: 0%
회원·그룹·연구 기능: 0%
P2P·포인트: 0%

## 1. 절대 원칙

- 자동·수동 다운로드 모두 OS 마우스, 원점, hover 검증, Heart8772를 사용하지 않는다.
- 다운로드 시작 방식은 유지할 수 있지만, 파일 저장 완료 이후 처리는 반드시 공통 `MEDIA_SAVED` 흐름으로 합친다.
- 버전은 실제 수정된 모듈만 변경한다. 무관한 파일·테스트의 버전 문자열만 바꾸지 않는다.
- 패키지 ZIP 버전과 개별 모듈 버전은 구분한다. v226에서는 실제 수정된 IG만 갱신하고 WS·Shared·Auto·RTC는 기존 버전을 유지한다.
- 완료된 일회성 테스트는 누적하지 않는다. 현재 기능을 지키는 고정 이름 최소 회귀 테스트만 유지한다.
- 실제 Windows·Chrome·MySQL 서버 로그가 없는 항목은 `[검증대기]` 또는 `[예정]`으로 둔다.
- 삭제 대상은 현재 사용자 지시 기준으로 최종 ZIP에서 제외한다.
- 서버에는 MP4/JPG 원본과 사용자 로컬 절대경로·상대경로를 저장하지 않는다.
- 실패·불확실 상태를 성공으로 기록하지 않는다.

## 2. 현재 실행 구조

- `Auto8700`: 실행 버전 `2.3.8.223`; Chrome·CDP·WS·RTC 서비스 관리
- `IG_StYellow`: 실행 버전 `2.3.8.226`; Instagram DOM 분석, 메인 주입 오버레이 `IG <account>` 표시, 직접 URL 다운로드 시작, source mode·batch/job/event 식별정보 전달
- `WS8771`: 실행 버전 `2.3.8.225`; 파일 확인·해시·JSON·ECharts 후 Shared `MEDIA_SAVED` 기록과 기존 서버 동기화
- `RTC8790_8791`: 기존 v141 유지; 이번 작업에서 수정하지 않음
- `Shared/storage`: SQLite 스키마 v2, MySQL v45+v46 추가형 마이그레이션, 공통 저장 함수
- `Heart8772`: 폐기 및 ZIP 제외

### 메인 주입 계정 표시 기준

- 게시물 계정명이 있으면 첫 통계 라벨을 `IG <account>`로 표시한다. 예: `IG double_king0.1`.
- 게시물 계정명이 없으면 기존처럼 `IG`만 표시한다.
- Top/순위 라벨이 활성화된 경우 기존 `No 000 / account / kind` 표시를 유지한다.

## 3. 저장 폴더 기준

```text
상위폴더/
├─ _St/
│  ├─ Auto8700/
│  ├─ IG_StYellow/
│  ├─ WS8771/
│  ├─ RTC8790_8791/
│  └─ Shared/
└─ _StDown/
   └─ instagram/
      ├─ account_a/
      │  ├─ 원래파일명.mp4
      │  └─ 원래파일명.jpg
      ├─ account_a.html
      └─ 사용자집계명.html
```

- 실제 파일은 `_StDown/instagram/<account>/`에 원래 파일명으로 저장한다.
- 계정별 HTML은 `_StDown/instagram/<account>.html`이다.
- 사용자 집계명은 폴더명이 아니라 집계 정의·HTML 파일명이다.
- 파일 정체성은 폴더명이 아니라 `platform + shortcode + asset_kind + media_index`와 해시로 판단한다.
- 서버에는 로컬 경로를 보내지 않는다.

## 4. 다운로드 3종과 공통 완료 처리

기존 주요 다운로드 방식:

```text
1. Down all medias
2. Top sorted 다운로드
3. Down filtered medias
```

추가로 카드 개별 다운로드와 대본 요청 다운로드도 같은 완료 처리에 연결한다.

`source_mode` 고정값:

```text
MANUAL_SINGLE
BULK_ALL
BULK_FILTERED
TOP_SORTED
TRANSCRIPT_REQUEST
```

최종 공통 흐름:

```text
다운로드 시작
→ download_batch / download_job 기록
→ Chrome 다운로드
→ WS 파일 완료 확인·MD5/SHA-256 계산
→ sidecar·JSON·ECharts 보고서 갱신
→ Shared MEDIA_SAVED 기록
→ media_assets AVAILABLE
→ posts MEDIA_AVAILABLE
→ download_job/batch 상태 갱신
→ sync_queue 등록
→ p2p_inventory 보유 상태 갱신
→ 대본 추출 가능 상태 표시
```

- 전체·필터·Top·개별·대본 요청은 시작 조건만 다르고 저장 완료 처리는 같다.
- `TOP_SORTED`만 `rank_no`가 필수 후보이며, 전체·개별은 `NULL`일 수 있다.
- 같은 `event_uuid` 재전송은 중복 이벤트·중복 동기화 큐를 만들지 않는다.
- 로컬 이벤트에는 등록된 저장 루트 아래 상대경로를 기록하지만, 서버 동기화 payload에서는 모든 로컬 경로를 제외한다.
- 권장 저장 위치는 `_StDown/instagram`이다. 기존 Chrome 다운로드가 다른 로컬 루트에 저장되면 파일을 임의 이동하지 않고 그 실제 루트를 로컬 SQLite에 추가 등록한다.
- Shared 기록 실패 시 다운로드 자체를 성공으로 위장하지 않고 응답을 `partial`로 반환한다.

## 5. SQLite 현재 구조

### v1 기반

- 수집자·장치 로컬 프로필
- 저장 루트
- 계정·수집 조건
- 게시물·최신 통계·통계 이력
- 미디어 자산·대본·후킹
- 카테고리·태그·메모·평가·댓글
- 집계 정의
- P2P 보유 캐시
- 동기화 큐·포인트 원장 캐시

### v2 추가

- `download_batches`: 전체/필터/Top 등 한 번의 다운로드 묶음
- `download_jobs`: 게시물·자산별 다운로드 작업
- `media_saved_events`: 공통 파일 저장 완료 이벤트
- `record_media_saved()`: 자산·게시물·job·batch·P2P·sync_queue 공통 완료 트랜잭션
- `record_downloaded_file()`: 실제 파일 경로에서 계정·게시물·저장 루트·batch/job을 확보한 뒤 공통 완료 함수를 호출
- `ensure_download_batch()`, `ensure_download_job()`: IG에서 받은 client key를 로컬 DB ID로 멱등 연결
- 경로 이탈 방지, 이벤트 재전송 중복 방지, batch 요청 파일 수 충족 전 `RUNNING` 유지, sync payload 경로 제외

## 6. MySQL 현재 구조

### v45

- 회원·장치·그룹·가입 관계
- 계정·수집 조건·게시물·통계
- 자산·장치 보유 정보
- 대본·후킹·카테고리·평가·댓글
- 집계·작업 lease·동기화·포인트 원장

### v46

- `collector_download_batches`
- `collector_download_jobs`
- `collector_media_saved_events`
- `device_id + client_event_id` 중복 방지
- 서버 저장 항목: 게시물·자산 ID, source mode, 파일명, 크기, MD5/SHA-256, 완료 시각, 회원·장치
- 서버 비저장 항목: MP4/JPG 원본, 로컬 절대경로, 로컬 상대경로

적용 순서:

```text
migration_v45_from_yellow_v44.sql
→ migration_v46_media_saved_flow.sql
```

실제 운영 DB에는 아직 적용하지 않았다.

## 7. 관찰·다운로드·대본 정책

대부분 게시물은 메타데이터만 관찰한다.

```text
관찰: URL, shortcode, 계정, 날짜, 조회수, 좋아요, 댓글, 섬네일 URL, 캡션
다운로드: 인기 조건, 사용자의 직접 선택, 대본 요청 시
대본: 로컬 파일 → 그룹 P2P → Drive/기타 보유처 → 최종적으로 원본 URL
```

계정별로 다음 값을 독립 설정한다.

```text
lookback_days
sort_by
observation_limit
download_policy
download_limit
transcript_policy
visibility
```

파일이 없는 `METADATA_ONLY` 상태는 정상 상태다.

## 8. 로컬·서버 역할

### 로컬 SQLite

- 개인·상세 데이터
- 로컬 파일 연결
- 전체 통계 이력
- 개인 카테고리·메모·평가
- 다운로드 작업·이벤트
- 미전송 변경분 sync_queue

### 중앙 MySQL/PHP

- 수집자·장치 인증 및 공개 식별
- 그룹·권한·공개범위
- 공유 가능한 최신 게시물·통계·URL·대본
- 자산 해시·보유 장치·전송 티켓
- 작업 claim/lease
- 검증된 포인트 원장

조회 우선순위:

```text
로컬 SQLite/파일
→ 중앙 서버의 최신 공유 결과
→ 그룹 P2P
→ Drive/기타 공유 저장소
→ Instagram 원본
```

## 9. 수집자·장치·그룹 계획

- 서버가 영문·숫자 4자리 수집자 코드를 발급하고 최초 확정 후 고정한다.
- 수집자 표시 이름은 최초 입력 후 수정 가능하다.
- 공개 표시는 `표시 이름 [수집자코드]`를 사용한다.
- 4자리 코드는 표시·검색용이며 인증은 서버 발행 device token으로 한다.
- 한 수집자에 여러 `computer_id` 장치를 연결할 수 있다.

그룹 역할:

```text
OWNER       그룹장
VICE_OWNER  부그룹장
MANAGER     운영진
MEMBER      일반회원
```

그룹 기능 계획:

- 그룹 생성·소개·홍보·모집
- 자유 가입·승인 가입·초대 전용·비공개
- 가입 신청·수락·거절·탈퇴·퇴장·재가입 제한
- 그룹장 권한 이전
- 공동 수집 계정·작업 담당·그룹 연구 자료

## 10. 공개범위 기준

```text
PRIVATE  본인만
GROUP    지정 그룹
PUBLIC   전체 서비스 사용자
```

- 새 계정·카테고리·메모·평가·댓글은 기본 `PRIVATE`다.
- 그룹 가입만으로 개인 자료가 자동 공개되지 않는다.
- 공개 범위는 계정·게시물·카테고리·메모·평가·댓글·대본별로 독립 관리한다.
- 전체 공개 전 확인을 거친다.
- 공유 후 이미 받은 로컬 파일은 회수할 수 없음을 안내한다.

## 11. 연구·후킹·검색 계획

한 게시물은 여러 카테고리·태그를 가질 수 있다.

검색 대상:

```text
계정명
게시물 설명·캡션
대본
후킹 문장
카테고리·태그
평가글
평가 작성자 이름·수집자코드
메모·댓글
```

후킹 구조:

- 대본 추출 후 첫 2~3초를 AI 후보로 제시
- 사람이 시작·종료 시각과 문장을 확정·수정
- `AUTO_SUGGESTED`, `HUMAN_CONFIRMED`, `HUMAN_EDITED`, `REJECTED` 구분
- 카드에서는 짧은 후킹만 표시하고 클릭 시 전체 문장·대본·평가·통계를 펼친다.
- 문제 제기형, 숫자형, 질문형, 반전형, 경고형 등 다중 유형 지정
- 후킹 평가와 예측 점수는 실제 통계와 분리 저장
- 예측과 실제 조회수·시간당 성장·반응률 차이를 누적 분석

평가글은 작성자의 표시 이름과 수집자 코드를 보여주고, DB 관계는 내부 회원 ID로 유지한다.

## 12. P2P·포인트 후속 계획

- P2P는 자산 ID로 요청하고 제공 장치의 SQLite가 실제 경로를 해석한다.
- 동시 업로드 수·대역폭·큐를 제한한다.
- 직접 P2P 실패 시 다른 보유자·Drive·원본 순으로 fallback한다.
- 포인트는 실제 SHA-256·크기 검증 완료 후만 정산한다.
- 요청 시 escrow, 성공 시 요청자 차감·제공자 적립, 실패 시 환불한다.
- 자기 거래·중복 등록·가짜 전송·오염 파일은 보상하지 않는다.
- 초기 포인트는 출금 불가 내부 크레딧으로 운영한다.

## 13. 단계별 MVP

1. **기반 정리 `[완료]`**: 마우스 계층 폐기, 폴더명 변경, SQLite v1, MySQL v45
2. **공통 다운로드 저장 기반 `[코드반영·단위검증 완료]`**: SQLite v2, MySQL v46, `record_media_saved()`
3. **IG·WS 연결 `[코드반영·자동검증 완료 / Windows 검증대기]`**: 전체·필터·Top·개별 다운로드 완료를 공통 함수에 연결
4. **로컬 데이터 MVP**: 계정·수집조건·게시물·통계 repository와 페이지 조회
5. **관찰 수집 MVP**: 영상 없이 메타데이터와 통계 수집
6. **선택 다운로드·대본 MVP**: 인기 조건·수동 선택·대본 요청 다운로드
7. **서버 동기화 MVP**: 수집자 코드·장치 토큰·변경분 업로드·재시도
8. **그룹·공개범위 MVP**: 그룹 생성·가입·권한·공유
9. **연구 MVP**: 카테고리·태그·메모·평가·댓글·후킹·검색
10. **후속**: P2P·포인트·부정사용 방지·운영 부하 검증

## 14. 현재 검증대기와 다음 단일 목표

실제 Windows에서 아래를 각 1회 이상 실행해 로그를 확인해야 한다.

```text
카드 개별 다운로드 → MANUAL_SINGLE
Down all medias → BULK_ALL
Down filtered medias → BULK_FILTERED
Top sorted 자동 → TOP_SORTED
```

완료 로그 기준:

```text
MEDIA_SAVED_OK
storage_ok=true
media_saved.event_id 존재
SQLite media_saved_events 1건
동일 event 재처리 시 중복 sync_queue 없음
```

다음 코딩 단일 목표는 **로컬 계정·게시물·통계 repository와 페이지 단위 조회**다. 실제 Windows 검증 전에는 현재 연결 기능을 `[검증대기]`로 유지한다.

다음 목표에서 제외:

- 실제 MySQL 서버 적용
- 회원·그룹 UI
- P2P 전송
- 포인트 정산
- Whisper 실행
