Skip to content

feat: 저장과 실행 워크플로 (#265) - #270

Open
5solbin wants to merge 5 commits into
devfrom
feat/#265-autoGeneration
Open

feat: 저장과 실행 워크플로 (#265)#270
5solbin wants to merge 5 commits into
devfrom
feat/#265-autoGeneration

Conversation

@5solbin

@5solbin 5solbin commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

요약

이슈 #265 자동 콘텐츠 생성 중 PR 3(저장과 실행 워크플로) — PR 2(#269, Claude 생성 코어)가 이미 dev에 merge된 상태에서 이어서 진행.

  • ContentSeedCandidateQueryService: 최근 활성 게시글 30개 조회, 봇별 상호작용 후보(최근 7일, 실제 사용자 글 -> 이번 실행 봇 글 -> 기존 봇 글 우선순위, 자기 글/기존 투표/기존 댓글 제외, 봇 댓글 한도 초과 게시글 제외, 최근 최상위 댓글 5개 마스킹 첨부)
  • ContentSeedVotePersister: 봇 투표를 MemberVoteOption 관계만 저장하는 부작용 없는 방식으로 저장(공개 카운트 미증가, 포인트 미지급) — 댓글의 선택 옵션 표시는 별도 처리 없이 유지됨을 확인
  • ContentSeedPersistenceService: 생성 항목 1건을 REQUIRES_NEW 독립 트랜잭션으로 저장(기존 VoteService/CommentService 재사용), 뒤 항목 실패가 앞선 성공을 되돌리지 않음
  • ContentSeedOrchestrator: 모든 봇 게시글 생성 -> 전체 상호작용 생성 순서로 오케스트레이션, 항목/배치/봇 단위 실패 격리, 목표에 못 미치면 부족분만 최대 1회 재요청
  • ContentSeedUsageSummary/ContentSeedRunResult: API 호출 횟수·토큰·예상 비용 집계, 품질 거절 사유 요약

이번 PR에는 스케줄러·ADMIN 수동 실행·Discord 알림·운영 환경 기본값(PR 4)이 포함되지 않음 — 아직 이 오케스트레이션을 실제로 호출하는 진입점(스케줄러/API)이 없어서 프로덕션에는 영향 없음.

테스트

  • ./gradlew test 전체 329개 통과, 실패 0

Test plan

  • ./gradlew test 전체 통과 확인
  • CI 통과 확인

최근 활성 게시글 30개(제목+카테고리)와, 봇별 상호작용 후보 게시글(최근 7일,
실제 사용자 글 -> 이번 실행 봇 글 -> 기존 봇 글 우선순위, 자기 글/기존 투표/
기존 댓글 제외, 봇 댓글 한도 초과 게시글 제외, 최근 최상위 댓글 5개 마스킹
첨부)을 조회하는 ContentSeedCandidateQueryService를 추가.
MemberVoteOption 관계만 저장하고 Vote.totalVoteCount/VoteOption.voteCount는
증가시키지 않으며 PointService도 호출하지 않는 ContentSeedVotePersister를 추가.
댓글의 "선택한 옵션" 표시는 CommentRepositoryImpl이 MemberVoteOption을 조인해서
보여주므로 별도 처리 없이 그대로 유지됨을 테스트로 확인.
생성된 콘텐츠 1건(게시글 또는 투표+댓글)을 REQUIRES_NEW 트랜잭션으로 저장하는
ContentSeedPersistenceService를 추가. 게시글은 기존 VoteService.createVote를,
댓글은 기존 CommentService.createComment를 재사용하고, 투표는 PR3-2의
ContentSeedVotePersister로 부작용 없이 저장한다. 이 클래스는 외부 API를 호출하지
않아 DB 트랜잭션이 Claude 호출 시간 동안 열려있지 않으며, 뒤 항목 저장 실패가
앞서 커밋된 항목을 되돌리지 않음을 테스트로 확인.
봇 선정 -> 전체 봇 게시글 생성 -> 전체 봇 상호작용 생성 순서로 진행하는
ContentSeedOrchestrator를 추가. 항목(품질 미달/저장 실패)·배치(Claude 호출
실패)·봇 단위로 실패를 격리해 한 곳의 실패가 나머지 처리를 막지 않는다.
봇별 목표/실제 생성량과 실패 사유를 담는 ContentSeedRunResult/
ContentSeedBatchOutcome/ContentSeedItemFailure 모델을 함께 추가.

봇 페르소나의 관심사 힌트는 DB에 저장되는 값이 아니라서, 시드된 닉네임 5개와
생성 카테고리 5개(FOOD/LOVE/BUY/SPORT/WORRY)가 1:1로 대응한다고 보고 정적
매핑으로 구현함(가정 사항).
봇별 게시글/상호작용 목표에 못 미치면 부족분만 최대 1회 재요청하도록
ContentSeedOrchestrator를 확장. 실행 전체의 Claude API 호출 횟수·입력/출력
토큰·예상 비용(ContentSeedProperties.Pricing 단가 기준)을 집계하는
ContentSeedUsageSummary를 추가하고 ContentSeedRunResult에 포함시킴.
ContentSeedRunResult에는 품질 거절/저장 실패 사유별 개수를 요약하는
rejectionReasonCounts()도 추가.
@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d43452a-bc1a-4b6d-8fb5-86f1cf56ead2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant