내 채널을 등록하면 그 영상이 수집함·칸반에 소재로 섞여 들어갔다. 이미 발행한 영상은 소재가 아니라 성과이므로 아예 분리한다. - ChannelRole.OWN 추가. OWN 채널 영상은 source=OWN 으로 저장되고, 수집함·칸반· 발굴 쿼리는 CHANNEL·SEARCH 화이트리스트라 자동으로 격리된다(쿼리 수정 불필요). /channels 목록에도 안 뜨고 피드에도 안 섞인다. - /my-channel 신설: 성과 요약(구독·총조회·영상평균·최근30일), 성장 추이 차트, 내 영상 목록. - 핵심은 소재별 성과 랭킹(TopicPerformance). 해시태그별 평균 조회수를 채널 평균 대비 배수로 보여준다. 실제 데이터로 유퀴즈 2.43x, 워크맨 0.30x 처럼 갈려서 피드에서 무엇을 자를지 판단하는 근거가 된다. 1편짜리 우연은 2편 미만 컷으로 제외. - 자동 수집·스냅샷 대상에 OWN 포함(findTrackedChannels). 해시태그 역분석의 원천도 MY → OWN 으로 바꿨다. 테스트 8건 추가(TopicPerformance 6, ChannelRole 2) — 총 84건 통과. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| docs | ||
| gradle/wrapper | ||
| src | ||
| .gitignore | ||
| build_log_final.txt | ||
| build_log.txt | ||
| build.gradle | ||
| CLAUDE.md | ||
| dashboard.png | ||
| gradlew | ||
| gradlew.bat | ||
| Jenkinsfile | ||
| README.md | ||
| settings.gradle | ||
| 영상테스트2.mp4 | ||
| 영상테스트.mp4 | ||
📖 개요
h-lab(아티팩트명 yanalyst)은 유튜브 Shorts 데이터를 수집·분석해 떡상(구독자 대비 조회수 폭발) 후보를 골라내고, 자막을 추출·재가공한 뒤 발행까지 추적하는 개인용 SSR 웹 서비스입니다. Spring Boot 백엔드에 Thymeleaf 서버 사이드 렌더링 UI를 사용하며, 모든 화면이 동일한 앱에서 제공됩니다.
라이트/다크 테마 토글을 지원하는 정제된 SaaS UI로, 사이드바 한 곳에서 전체 테마가 전환됩니다.
✨ 주요 기능
| 단계 | 설명 |
|---|---|
| 🛰️ 수집 (Collection) | 등록 채널 동기화 + 조회수 검색 수집. 정기 자동 수집 스케줄러. |
| 🔍 발굴 (Discovery) | 조회수 ÷ 구독자 배율로 떡상 후보 자동 선별. 카테고리·북마크·필터. |
| 🗂️ 큐레이션 (Curation) | 관심 상태(NEW→REVIEWING→TARGET→DONE/EXCLUDED) 칸반 보드 + 드래그 이동. |
| ✂️ 재가공 (Rework) | 영상 업로드 → Whisper 시간싱크 자막 추출 → 말 없는 구간 제거·배속 → SRT+영상 내보내기(CapCut import). 재작성 에디터. |
| 📤 발행 (Publish) | 제목·설명·해시태그·예약 패키지 관리, 발행 추적(업로드는 수동). |
🔁 콘텐츠 파이프라인
수집 발굴/큐레이션 재가공 발행
┌────────┐ ┌────────────┐ ┌──────────────┐ ┌──────────┐
│ CHANNEL│ ──▶ │ 배율 정렬 │ ──▶ │ 자막추출·컷 │ ──▶ │ 제목/태그 │
│ SEARCH │ │ 칸반 보드 │ │ SRT·영상 출력 │ │ 발행 추적 │
└────────┘ └────────────┘ └──────────────┘ └──────────┘
\______________ ChannelVideo (단일 마스터) ______________/
모든 단계는 domain/channel/ChannelVideo 엔티티 하나를 중심으로 돕니다.
🛠 기술 스택
Backend · Spring Boot 3.4.0 / Java 21 · Spring Data JPA · Validation
View · Thymeleaf + Layout Dialect (SSR) · Inter · Lucide Icons · Light/Dark CSS 변수 테마
DB · PostgreSQL (ddl-auto: update) · p6spy · Hypersistence Utils
Docs · SpringDoc OpenAPI (Swagger UI)
Build/Tools · Gradle Wrapper · Lombok · JUnit 5
AI/미디어 엔진(별도 Python 마이크로서비스) · faster-whisper(전사) · ffmpeg(컷·배속·렌더)
🚀 시작하기
요구사항: JDK 21, PostgreSQL 접근 정보. 서버 포트는 8088.
# 실행 (UI + API 모두 http://localhost:8088 에서 제공)
./gradlew bootRun # Windows: gradlew.bat bootRun
# 빌드 / 테스트
./gradlew build
./gradlew test
# 단일 테스트
./gradlew test --tests "com.hlab.yanalyst.domain.channel.SrtFormatterTest"
| 경로 | 설명 |
|---|---|
http://localhost:8088/ |
대시보드 |
http://localhost:8088/collection · /board · /discover |
수집함 · 칸반 · 발굴 |
http://localhost:8088/rework/{id} · /publish |
재가공 · 발행 큐 |
http://localhost:8088/swagger-ui.html |
Swagger UI |
🔐 환경 변수
시크릿은 환경 변수 또는 git-ignored application-local.yml로 주입합니다 (예시: application-local.yml.example).
| 변수 | 용도 |
|---|---|
DB_URL · DB_USERNAME · DB_PASSWORD |
PostgreSQL 접속 |
YOUTUBE_API_KEY |
YouTube Data API |
PYTHON_BASE_URL |
자막/전사/렌더 마이크로서비스 (기본 http://h-python.tolag.shop) |
UPLOAD_MAX_FILE_SIZE |
업로드 영상 최대 크기 (기본 200MB) |
📂 프로젝트 구조
h-lab/
├── src/main/java/com/hlab/yanalyst/
│ ├── domain/ # DDD 스타일 — Entity+Repository+Service+RestController
│ │ ├── channel/ # ChannelVideo(단일 마스터)·수집·큐레이션·재가공·SRT/컷 로직
│ │ ├── category/ publish/ # 분류 · 발행 패키지
│ │ └── production/ # n8n 크롤 랭킹 스냅샷
│ ├── web/ # Thymeleaf 페이지 컨트롤러 + 추가 JSON API
│ ├── service/ # 횡단 서비스 (YouTube 검색 등)
│ └── global/ # config · 공통 응답 · 예외 · 스케줄러
└── src/main/resources/
├── static/css/ # variables.css(테마 토큰) · style.css(컴포넌트)
├── static/js/ # common.js(사이드바·테마 토글)
└── templates/ # layout/base·sidebar + 페이지 HTML
🔌 외부 연동
- Python 마이크로서비스 — YouTube 자막(
/transcript), Whisper 전사(/transcribe), ffmpeg 렌더(/render). - YouTube Data API — 채널·영상 메타 수집 및 조회수 검색 (일일 쿼터 가드).
- n8n Webhook —
production도메인의 랭킹/크롤 데이터 연동.
📝 라이선스
개인용 프로젝트입니다.