Skip to content

feat(editorial): 매거진 생성 고도화 — 대화형 + 레이아웃 다각화 #448

@cocoyoon

Description

@cocoyoon

PR #446 (#429) 머지 후 follow-up. 매거진 파이프라인의 다음 단계 고도화.

이 issue 는 umbrella — 5개 sub-issue (#547#551) 로 분리되어 개별 추적된다.


Estimation (총 5일)

# Sub-issue 영역 Estimate 의존성
1 #547 — Multi-stage 파이프라인 분해 ai-server 2d (없음 — 토대)
2 #548 — 신규 section type (quote_pull, mood_board) ai-server + web 0.5d Track 1
3 #549 — Chat agent tool 확장 ai-server + api-server (proto) 1d Track 2
4 #550 — Public reader /magazine/[slug] web 1d (없음 — 백엔드 기존)
5 #551 — Published 매거진 재편집 UX 가드 web + api-server 0.5d (없음)

Critical path: Track 1 (2d) → Track 2 (0.5d) → Track 3 (1d) = 3.5d.
Parallelizable: Track 4 (1d) + Track 5 (0.5d) 는 Track 1 과 병렬 가능 → 1인 작업 기준 총 5d 유지, 2인이면 ~3.5d.


현재 상태 (이미 구현됨)

  • Generation pipeline: fetch_sources → compose_layout (단일 Gemini Pro 호출) → generate_thumbnail → publish (draft 저장) (packages/ai-server/src/editorial_article/graph.py:22)
  • Chat agent: Gemini function calling, 7 tools, in-memory mutation (packages/ai-server/src/editorial_article_chat/)
  • Publish to operation: assets → operation snapshot UPSERT (packages/api-server/src/domains/admin/editorial_articles.rs:327, ON CONFLICT DO UPDATE 라 재-publish 안전)
  • Public read endpoint: /api/v1/editorial-articles/{id_or_slug} (packages/api-server/src/domains/editorial_articles_published/)
  • Admin renderer: 4종 section type 지원 (intro / curation_card / spotlight / closing)

한계

  • 단일 LLM 호출이 angle 해석 / 톤 / 섹션 순서 / 카피 를 동시 처리 — 품질 제어 어렵고 부분 재생성 불가
  • Section type 4종 고정 — 매거진 톤이 한 가지뿐
  • Chat tool 이 텍스트 편집 위주 — 솔루션 교체 / post 추가 같은 구조적 변경 불가
  • Public reader 페이지 부재 — 백엔드 endpoint 만 존재
  • Published 매거진 재편집 흐름이 UI 에 없음 — 백엔드 UPSERT 는 안전하나 운영자 가드 부재

Cross-cutting decisions

Feature flag (Track 1 에서 도입)

ENV 4개를 packages/ai-server/src/post_editorial/config.py 에 추가:

  • MAGAZINE_PIPELINE_MODE: single_call (default) | multi_stage
  • MAGAZINE_POLISH_ENABLED: false (default)
  • MAGAZINE_POLISH_TEMPERATURE: 0.4
  • MAGAZINE_MAX_PARALLEL_SECTION_WRITERS: 3

ENV 토글 → 즉시 rollback 가능. percent rollout (editorial_discovery_settings.pipeline_mode_override 컬럼) 은 후속.

Telemetry

  • 각 노드 진입/종료 시 editorial_article_events 에 INSERT (step 컬럼 text 라 DDL 변경 X)
  • 신규 step: classify_template, plan_outline, write_section, validate_sections, polish_layout, assemble, republish
  • LLM cost 는 note jsonb 에 {model, input_tokens, output_tokens} 누적 (/admin/gemini-cost 페이지가 읽음)

Type sync (수동, 4곳 동시 수정)

신규 section type 추가 시:

  1. packages/ai-server/src/editorial_article/models.py (Field description union)
  2. packages/web/lib/hooks/admin/useEditorialArticles.ts:49 (TS union literal)
  3. packages/web/lib/components/admin/editorial/magazine/MagazineRenderer.tsx:59 (switch case)
  4. packages/ai-server/src/editorial_article/prompts/sections/*.py (section writer prompt)

자동 생성 (pydantic → JSON schema → TS) 은 별도 후속 PR.

Proto SOT (Track 3)

양쪽 동시 수정:

  • packages/api-server/proto/ai.proto:259
  • packages/ai-server/src/grpc/proto/inbound/inbound.proto:261

각 패키지의 codegen 재실행.


PR 시퀀스 (의존성 기반)

  1. PR-1 Track 1 (feat(editorial,ai-server): 매거진 생성 파이프라인 multi-stage 분해 (Track 1 of #448) #547) — multi-stage 파이프라인 토대. 3 sub-PR 로 분할 (foundation / nodes / wire-up).
  2. PR-2 Track 2 (feat(editorial,web): 신규 section type quote_pull + mood_board (Track 2 of #448) #548) — 신규 section type. PR-1 의 prompt 모듈 활용.
  3. PR-3a Track 4 (feat(editorial,web): Public reader 페이지 /magazine/[slug] (Track 4 of #448) #550) — public reader. 백엔드 독립, PR-1 과 병렬 가능.
  4. PR-3b Track 5 (feat(editorial,web,api-server): Published 매거진 재편집 UX 가드 (Track 5 of #448) #551) — republish UX 가드. PR-3a 와 병렬.
  5. PR-4 Track 3 (feat(editorial,ai-server,api-server): Chat agent tool 확장 (Track 3 of #448) #549) — chat tool 확장. 신규 type 을 chat 이 다루려면 Track 2 선행.

각 트랙 내부도 sub-PR 로 쪼개 main 항상 green.


Verification (전체 로컬 풀 사이클)

  1. just dev
  2. MAGAZINE_PIPELINE_MODE=multi_stage ENV 로 ai-server 재시작
  3. Admin login → /admin/editorial/magazine/settings discovery enable
  4. Recommendation 1건 approve → events 타임라인에서 step 별 진행 확인 (classify → plan → write × N → validate → [polish] → assemble → thumbnail → publish)
  5. /admin/editorial/magazine/drafts/{id} → MagazineRenderer 표시, 신규 section type 분기 확인
  6. ChatPanel "Rosé 카드의 가방을 다른 걸로 바꿔줘" → swap_solution → 재렌더
  7. Publish → operation snapshot
  8. 새 탭 /magazine/{id} → public reader, OG meta view-source 확인
  9. admin chat 재진입 → RepublishBanner → "intro 톤 더 차분하게" → change_tone → 재렌더
  10. Republish → operation UPSERT, events 에 step='republish' 확인

비용 모니터링: 같은 recommendation 을 single_callmulti_stage 두 번 돌려 /admin/gemini-cost 에서 비교.


Out of scope (별도 추후 검토)

  • 데이터 보강: affiliate_url 파이프라인, solutions.price_amount 정규화, brand metadata 강화
  • 시각 다각화: 동적 accent color, typography variation, gpt-image-2 섹션 illustration
  • 추가 section type: comparison, timeline, interview
  • Chat UX: Streaming response, tool 결과 diff UI, multi-session history
  • 슬러그 enrichment: publish_to_operationtitle → slug 채움
  • Pydantic → TypeScript 자동 생성
  • Cache invalidation webhook (현재 300s ISR)

Related: #429, #446

Metadata

Metadata

Assignees

No one assigned

    Labels

    aiAI/자동화enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions