af-social-scanner — 문서 인덱스

이 프로젝트의 소셜 데이터 수집 파이프라인(Twitter·TikTok·Instagram·Reddit·YouTube·GitHub·Telegram·Website)에 대한 공식 문서가 지금 무엇이고 어디 있는지 답하는 페이지다. 새로 합류한 팀원, 오랜만에 돌아온 자신을 위한 진입점이다.

문서가 왜 세 곳으로 나뉘는가

이 저장소의 문서는 성격이 다른 세 그룹으로 나뉜다. 이 페이지는 그중 guides/(공식 문서)를 위한 진입점이고, 나머지 둘은 필요할 때만 찾아가면 된다.

🟢 guides/ — 공식 문서
지금 코드의 근거이거나, 코드가 직접 인용하거나, 앞으로도 계속 갱신돼야 하는 문서. 이 페이지가 다루는 대상이다. 새 기능이 기존 설계를 바꾸면 여기부터 고친다.
⚪ docs/features/ — 개발 이력
기능을 만들면서 생긴 착수 문서·작업 로그·초안. 그 작업이 있었다는 기록으로서 가치가 있을 뿐, 더 이상 갱신되지 않는다. "왜 이렇게 됐나"가 궁금할 때만 연다.
🔴 docs/archive/ — 폐기됨
더 최신 문서로 명시적으로 대체된 것들(예: 스키마 v4). 대체 문서 매핑표가 있다. 참고 이상의 용도로 쓰지 않는다.
2026-08-14 문서 정리에서 docs/features/ 200개 문서를 전수 조사해 이 세 그룹으로 나눴다. 물리적으로 폴더를 옮긴 것은 guides/로 이동한 것(공식화)archive/로 이동한 것(폐기) 뿐이고, 나머지는 docs/features/에 그대로 있다.

소셜 레코딩 파이프라인 구조

token.flow 이벤트 하나가 들어와서 소셜 데이터가 DB에 저장되기까지, 실은 시간순으로 쌓인 4개 계층과 3개 서브시스템을 거친다. 이름이 비슷해 헷갈리기 쉬워 관계를 다이어그램으로 남긴다.

flowchart TD
    SP["social-sync-pipeline
전송 계층
token.flow 큐 구독 · DTO 파싱 · 저장 없음"] SCHEMA["social-schema-definition
스키마 계층
contents·accounts·venues·token_links 정의"] RP["social-recording-process
오케스트레이션 계층
dedupe → lock → Generator 라우팅 → 저장"] RC["reconcile-token
배치·복구 계층
/reconcile · /retry(1시간 크론)"] AUDIT["social-url-structure-audit
8소셜 URL 구조 실측 감사"] GEN["social-generator
8소셜별 fetch → 스키마 객체 변환"] E1["social-url-entry
URL 유입 창구 일원화"] E2["social-url-dedupe
재사용 캐시(TTL 14일)"] E3["lock-before-execute-recording
토큰 단위 동시성 락"] REFACTOR["social-recording-refactor
전체 관통 사후 수선"] SP --> RP SCHEMA --> RP RP --> RC AUDIT --> GEN GEN --> RP E1 --> E2 --> E3 E3 --> RP REFACTOR -. 검증·수정 .-> SCHEMA REFACTOR -. 검증·수정 .-> RP classDef layer fill:#3b6cff22,stroke:#3b6cff,stroke-width:1.5px; classDef sub fill:#1a9c5322,stroke:#1a9c53,stroke-width:1.5px; classDef refactor fill:#b8720a22,stroke:#b8720a,stroke-width:1.5px,stroke-dasharray:4 3; class SP,SCHEMA,RP,RC layer; class AUDIT,GEN,E1,E2,E3 sub; class REFACTOR refactor;
4계층은 중복 재설계가 아니라 실제로 쌓인 순서다 — app.module.ts가 sync-pipeline과 recording-process를 같은 큐(token.flow)에 동시에 물린다. 각 계층의 정본 문서는 §3~④의 표에서 링크된다.

Generator 실행 결과 → URL 상태(FetchStatus) 전이

③의 8개 Generator 중 하나가 URL 하나를 처리한 결과가 이 상태들 중 하나로 떨어진다. 재시도·크론이 그중 어떤 상태를 다시 여는지도 여기서 정해진다 — 정본은 verification-runbook.md §7.

stateDiagram-v2
    [*] --> pending : 신규 토큰의 URL 목록 선생성
    pending --> ok : 객체를 확정했다
    pending --> not_found : 불렀는데 대상이 없다
    pending --> blocked : 대상 쪽 사정(비공개·초대전용·IP차단)
    pending --> invalid : 200을 받았는데 응답이 계약을 깼다
    pending --> error : 외부 호출 실패 · DB 일시 오류
    pending --> unsupported : 담당 Generator가 없다(호출 0회)
    pending --> skipped_paid : 유료라 안 불렀다(호출 0회)

    not_found --> ok : 재시도로 결과가 바뀐다
    blocked --> ok : 차단이 풀린다
    error --> ok : 일시 오류가 지나간다
    error --> exhausted : attempts가 MAX_ATTEMPTS(5)에 닿았다

    ok --> ok : TTL(14일) 만료 후 재수집 — points가 쌓인다
    unsupported --> ok : 담당 Generator가 생기면
    skipped_paid --> ok : 유료 게이트를 켜면

    invalid --> [*] : 100% 같은 실패다 — 배치가 명시적으로 열어야 한다
    exhausted --> [*] : 상한에 닿았다 — 배치가 명시적으로 열어야 한다
    
⚠️ unsupported·skipped_paidattempted_at이 없어 재시도 백오프를 원리적으로 통과하고, 다시 처리해도 같은 값이 나온다 — 이 둘이 열리는 조건은 거래가 아니라 배포다(Generator를 새로 만들거나 유료 게이트를 켜는 것).
계층/서브시스템정본 문서한 줄 요약
전송docs/features/social-sync-pipeline/be-system-design.mdtoken.flow 구독 + DTO 파싱. 저장 없음(아직 guides로 옮기지 않음 — §7 참고)
스키마schema.htmlcontents·accounts·venues·token_links·metric_series 필드 명세(v5, 2026-08-14 정정 포함)
오케스트레이션service-overview.mdas-built 요약. 설계 시점 문서(HTML 4종)는 docs/features/social-recording-process/에 이력으로 남음
배치/복구reconcile-token.md/reconcile(과거 토큰 채움) · /retry(실패 URL 재시도, 크론)
Generator 8종③ 표소셜별 fetch → Content/Account/Venue 변환
URL 처리 정책url-pipeline.html정규화 → 분류 → fetch 단계별 계약. URL 문자열을 누가 언제 고칠 수 있는지의 정본
URL 3부작url-entry · url-dedupe · lock유입 창구 일원화 → 재사용 캐시(TTL 14일) → 토큰 단위 동시성 락
URL 기록 상태(FetchStatus) state machineverification-runbook.md §7pending→ok/not_found/blocked/invalid/error/unsupported/skipped_paid→exhausted 전이 규칙. tokens.social_urls[].status 어휘의 정본
사후 수선docs/features/social-recording-refactor/런타임 결함 대장(H-*) · 구조 개편(R-*) · 스키마 재확정
횡단 결정 + 인덱스decisions.md · index-audit.html8소셜 공통 규칙(G-1~21) · 인덱스 26개 감사
통합 검증(살아있는 도구)verification-runbook.md · verification-rubric.md실제 소셜 API 응답으로 6개 컬렉션 저장을 검증하는 반복 실행 도구. 스크립트·결과물은 docs/features/recording-integration-verification/(경로 의존이라 그대로 둠)

소셜별 Generator 스펙 8종

어느 소셜이 어떤 벤더로 뭘 만드는지. 단가는 세션 내 실측 비용분석 근거(apify-cost-model.html) 기준.

소셜문서소스 벤더상태핵심 특징
Xx.md twitterapi.io ($0.15~0.20/1000)완료Creator+Content+Venue 전부 갖는 유일한 소셜. 인용/리트윗 사슬 fan-out(깊이 2)
YouTubeyoutube.md무료 Data API v3완료실호출 15 unit 검증. 구독자 큰 채널은 3자리 유효숫자로 반올림돼 옴
Telegramtelegram.md무료 HTML 파싱완료Venue 전용, Content 없음. 가드 포털 재사용 실측(근거)
GitHubgithub.md무료 GitHub API완료repo/owner. fork·archived 플래그로 스캠 위장 탐지
TikToktiktok.md Apify ($0.0047/건)완료프로필/게시물 응답이 같은 평면 구조라 추가 호출 0회
Instagraminstagram.md Apify ($0.0027~0.0054/건)완료게시물 조회 시 작성자 프로필 보충콜 1회 추가
Websitewebsite.md무료 HTTP GET완료sourceType(호출 전)과 패턴(응답 후) 이중 축. 실호출 검증 완료(23토큰)
Redditreddit.md Apify ($0.022/건, 전체 최고가)완료Content/Account를 의도적으로 안 묶음(V-2) — 작성자가 대개 공용 밈 서브레딧의 일반 유저

근거자료 — 코드가 직접 인용하는 문서

아래는 social-url-structure-audit(8소셜 URL 구조 실측 감사)에서 나온 산출물 중, 지금도 fetcher/generator 코드 주석이 직접 인용하는 것만 추렸다. 코드를 고치기 전에 먼저 봐야 하는 문서다.

문서플랫폼코드가 인용하는 곳성격
x.htmlXx/x.types.tssourceType·필드 확정 통합뷰
youtube.htmlYouTubeyoutube/youtube.types.ts동일
github.htmlGitHubgithub/github.types.ts동일
instagram.htmlInstagraminstagram/instagram.types.ts동일
tiktok.htmlTikToktiktok/tiktok.types.ts동일
reddit.htmlRedditreddit/reddit.types.ts (직접 인용 — scaffold JSON 없는 유일한 소셜)동일
website-kinds.htmlWebsitewebsite.consts.ts도메인 5종 분류(툴·소셜·디렉터리·참조·사이트)
website-content-mapping.htmlWebsitewebsite.generator.tsContentInput 추출 규격(패턴 7개)
website-pipeline.htmlWebsite워킹트리 diff와 실시간 대조됨파이프라인 15단계 현황(구현/미구현/제안)
website-qna.mdWebsite위 세 문서의 결정 기록지속 갱신되는 Q&A
apify-cost-model.htmlTikTok·Instagram·RedditApify 실측 usageTotalUsd단가 모델 — Reddit이 비용의 66%
telegram-guard-reuse.htmlTelegramtelegram.fetcher.ts가드 포털 재사용 3종 실측(69채널)
감사 원본 전체(브레인스토밍 과정 포함)는 docs/features/social-url-structure-audit/에 이력으로 남아 있다. 위 12개는 그중 지금도 코드가 참조하는 것만 추린 것이다.

일반 엔지니어링 가이드

소셜 레코딩 파이프라인에 국한되지 않는, 프로젝트 전반의 규칙.

Generator 루브릭
8소셜 Generator가 공통으로 지켜야 하는 R-1~R-18 · token_links 정책
소셜 생성기 착수 프로세스
새 소셜을 추가할 때 뭘 먼저 판단해야 하는지
OOP Programming Guide
객체지향 설계 원칙
MongoDB Schema & Performance Guide
스키마·인덱스·성능 일반 규칙
NestJS SDK Implementation Guide
외부 SDK 래퍼 작성 규칙
Project Mistakes
반복된 실수 패턴 기록

개발 이력 — docs/features/

17개 폴더, 154개 문서. 전부 완료됐거나 진행 중이던 작업의 기록이고 이제 더 갱신되지 않는다. "왜 지금 이 구조가 됐나"가 궁금할 때만 연다. 폐기된 23개는 docs/archive/에 따로 있다.

fetcher-typing-refactor 24
9개 fetcher를 소셜별 자기 타입으로 분리. Telegram·Website 일부 미결
image-asset-fields 14
Content.media_urls·Account.avatar_url 신설, 완료
lock-before-execute-recording 2
정본은 guides로 이동. signatures 등 이력만 남음
narrative-grouping 1
토큰 소셜 콘텐츠를 내러티브 단위로 묶는 설계, 미착수
reconcile-token 12
배치/복구 계층의 HTML 설계문서 등. 정본은 guides로 이동
recording-integration-verification 5
검증 스크립트·results — 정본(runbook·rubric)은 guides로 이동, 경로 의존 있는 것만 남음
social-generator 7
backlog.md + 8소셜 kickoff.html. 정본은 guides로 이동
social-recording-process 12
오케스트레이션 계층 설계 시점 기록. 정본은 guides/service-overview.md
social-recording-refactor 4
파이프라인 전체 사후 수선(R-*·H-*)
social-schema-definition 10
스키마 v3→v4 이력. 정본(v5)은 guides로 이동
social-sync-pipeline 15
전송 계층 설계(token.flow 큐 구독)
social-url-dedupe 2
정본은 guides로 이동. signatures 등 이력만 남음
social-url-entry 1
backlog.md만 남음. 정본은 guides로 이동
social-url-structure-audit 26
8소셜 URL 구조 감사. 정본 다수는 guides/audit-sources로 이동, 나머지는 브레인스토밍 이력
token-image-fields 10
Token.image 필드 설계·구현, 완료
token-image-url-audit 1
Token.image 4계층 추출가능성 감사

유지관리 — 새 작업이 끝나면

이 페이지는 자동으로 갱신되지 않는다. 수동 관리다.

  1. 새 feature 작업이 "공식 문서" 성격(스키마·운영정책·코드가 인용하는 근거자료)을 만들었다면 — 완료 시점에 그 문서를 guides/(적절한 하위폴더)로 옮기고, 이동 전 상대링크를 원 폴더 기준에서 새 위치 기준으로 고친다. 이 페이지 §2~④ 표에 행을 추가한다.
  2. 기존 공식 문서를 대체하는 새 버전이 나왔다면 — 이전 버전을 docs/archive/로 옮기고 docs/archive/README.md에 대체 사유를 한 줄 추가한다. 이 페이지에서 옛 링크를 새 문서로 바꾼다.
  3. 순수 작업 로그·착수 문서라면docs/features/<feature>/에 그대로 둔다. 이 페이지를 고칠 필요는 없다(§⑥은 폴더 단위 요약이라 파일이 늘어도 대개 그대로 맞는다. 폴더 성격 자체가 바뀌면 그때 문구만 수정한다).
  4. 주기적으로 — §④(근거자료) 표의 문서가 실제로 코드에서 아직 인용되는지 가끔 grep으로 확인한다. 인용이 끊겼다면 §⑥ 이력으로 강등하거나 archive로 옮긴다.
아직 guides/로 옮기지 않은 후보: social-sync-pipeline/be-system-design.md(전송 계층 정본), social-recording-refactor/schema-refactor-plan.md(스키마의 "왜"). 스크립트 경로 의존성 때문에 이번 라운드에서는 docs/features/에 남겨뒀다 — 다음 정리 라운드 후보다.