Skip to content

feat: 임베딩 기반 맞춤 추천 추가#84

Open
choihooo wants to merge 14 commits into
devfrom
feat/curation-vector-recommendations
Open

feat: 임베딩 기반 맞춤 추천 추가#84
choihooo wants to merge 14 commits into
devfrom
feat/curation-vector-recommendations

Conversation

@choihooo
Copy link
Copy Markdown
Collaborator

🎯 Summary

이 PR의 목적을 한 줄로 요약해주세요

  • /curation/posts 추천을 임베딩 기반 맞춤 추천으로 전환하고 추천 이유 UI를 추가합니다.

🔴 AS-IS

기존 상태 또는 문제점

  • /curation 추천 정렬이 사용자 관심사와 아이템 태그의 단순 겹침 기준이라 추천 품질이 제한적이었습니다.
  • 새 큐레이션 아이템, 사용자 취향, 포스트를 벡터화해서 관리하는 별도 파이프라인이 없었습니다.
  • /posts에는 최신순/인기순만 있어 사용자 취향 기반으로 글을 발견하기 어려웠습니다.
  • 임베딩 서버 운영 중 발생한 Cloudflare Access, Tunnel, Ollama 403 이슈를 추적할 문서가 없었습니다.

🟢 TO-BE

변경 후 상태 또는 개선점

  • 큐레이션 아이템, 사용자 취향, 포스트 임베딩 생성을 위한 shared 스키마/마이그레이션/유틸을 추가했습니다.
  • bot에 Ollama 호환 임베딩 서비스, 내부 갱신 API, 백필 스크립트, RSS 수집 후 임베딩 갱신 흐름을 추가했습니다.
  • /api/curation?sort=recommended를 벡터 유사도 + 최신성 + 기존 관련도 보정 기반으로 정렬하도록 변경했습니다.
  • /posts맞춤 탭을 추가하고, 관심도순 정렬과 추천 이유/관심도 UI를 맞춤 탭 전용으로 표시합니다.
  • 포스트 카드 높이가 달라도 조회/댓글/리액션/수정/삭제 인터랙션이 카드 하단에 붙도록 UI를 정리했습니다.
  • 임베딩 서버 트러블슈팅 문서를 별도로 추가했습니다.

💬 참고사항

리뷰어가 알아야 할 내용, 논의 포인트, 주의사항 등

  • 임베딩 서버는 EMBEDDING_PROVIDER=ollama, nomic-embed-text, 768차원 기준입니다.
  • Cloudflare Access service token 값은 커밋하지 않았고, env 이름만 추가했습니다.
  • 기존 데이터 백필은 로컬에서 수행해 활성 큐레이션/포스트/멤버 취향 임베딩을 채워둔 상태입니다.
  • 검증 완료:
    • pnpm --filter @blog-study/web typecheck
    • pnpm --filter @blog-study/shared typecheck
    • pnpm --filter @blog-study/bot typecheck
    • pnpm --filter @blog-study/shared test embedding-text.property.test.ts recommendation-reason.property.test.ts

@choihooo choihooo requested a review from bbbang105 as a code owner May 22, 2026 06:44
@vercel
Copy link
Copy Markdown

vercel Bot commented May 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
study-admin-web Ready Ready Preview, Comment May 22, 2026 8:32am

@bbbang105 bbbang105 added 📄 docs 문서 추가 및 수정 🚀 feat 새로운 기능 추가 / 일부 코드 추가 / 일부 코드 수정 (리팩토링과 구분) / 디자인 요소 수정 labels May 22, 2026
Copy link
Copy Markdown
Collaborator Author

@choihooo choihooo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰했습니다. 전체적으로 타입체크/빌드는 통과했고, 임베딩 기반 추천 흐름에서 운영 중 빈 결과나 누락이 생길 수 있는 지점 위주로 봤습니다.

Findings

P1: 큐레이션 임베딩 갱신이 rate limit에 걸려 대량 누락될 수 있습니다

packages/web/src/lib/embedding-refresh.ts에서 큐레이션 크롤 후 최대 100개 item을 bot API로 개별 POST하는데, bot 쪽 packages/bot/src/api-server.tstriggerLimiter가 10 req/min으로 걸려 있습니다. 한 번에 10개 넘게 수집되면 11번째부터 429로 실패해서 대부분 임베딩이 생성되지 않습니다.

bulk endpoint를 만들거나 내부 임베딩 endpoint는 별도 rate limit/배치 처리로 분리하는 게 좋겠습니다.

P1: 추천 탭이 백필/장애 상황에서 빈 화면이 될 수 있습니다

packages/web/src/app/api/curation/route.tspackages/web/src/app/api/posts/route.ts 모두 사용자의 preference embedding만 있으면 바로 vector 추천 path로 들어가고, 이후 content embedding이 없는 row를 IS NOT NULL로 제외합니다.

임베딩은 best-effort/비동기라 초기 배포, 백필 전, provider 장애, 위 rate-limit 상황에서 추천 탭이 비어 보일 수 있습니다. vector 결과가 부족하면 overlap/latest로 채우는 fallback이 필요해 보여요.

P2: 큐레이션 vector 추천 cursor가 시간에 따라 불안정합니다

packages/web/src/app/api/curation/route.ts의 vector 추천 커서가 now() 기반 freshness를 포함한 finalScore를 그대로 저장/비교합니다. 다음 페이지 요청 때 점수가 재계산되면 같은 item도 이전 cursor score보다 작아져 다시 나올 수 있습니다.

keyset pagination에서는 점수가 안정적이어야 해서, cursor에 asOf를 포함해 같은 기준 시각으로 재계산하거나 freshness를 커서 정렬키에서 빼는 쪽이 안전합니다.

Verification

  • pnpm --filter @blog-study/shared typecheck 통과
  • pnpm --filter @blog-study/web typecheck 통과
  • pnpm --filter @blog-study/bot typecheck 통과
  • pnpm --filter @blog-study/shared test 통과: 93 tests
  • pnpm --filter @blog-study/bot test 통과: 150 tests
  • pnpm --filter @blog-study/web test 실패: 테스트 파일 없음으로 Vitest가 code 1 종료
  • pnpm --filter @blog-study/shared build, bot build, web build 통과

@bbbang105 bbbang105 added the 🚨 fix 버그 수정 / 에러 해결 label May 22, 2026
@choihooo
Copy link
Copy Markdown
Collaborator Author

추천 탭 스크린샷

포스트 > 맞춤 탭

포스트 맞춤 탭

큐레이션 > 맞춤 탭

큐레이션 맞춤 탭

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

Labels

📄 docs 문서 추가 및 수정 🚀 feat 새로운 기능 추가 / 일부 코드 추가 / 일부 코드 수정 (리팩토링과 구분) / 디자인 요소 수정 🚨 fix 버그 수정 / 에러 해결

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants