# 🎬 h-lab Β· `yanalyst` **유튜브 데이터λ₯Ό μˆ˜μ§‘Β·λΆ„μ„ν•˜κ³ , 떑상 μ˜μƒμ„ λ°œκ΅΄ν•΄ μž¬κ°€κ³΅Β·λ°œν–‰κΉŒμ§€ μž‡λŠ” 1인 μ½˜ν…μΈ  νŒŒμ΄ν”„λΌμΈ**
![Java](https://img.shields.io/badge/Java-21-ED8B00?style=for-the-badge&logo=openjdk&logoColor=white) ![Spring Boot](https://img.shields.io/badge/Spring_Boot-3.4.0-6DB33F?style=for-the-badge&logo=springboot&logoColor=white) ![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=for-the-badge&logo=postgresql&logoColor=white) ![Thymeleaf](https://img.shields.io/badge/Thymeleaf_SSR-005F0F?style=for-the-badge&logo=thymeleaf&logoColor=white) ![Gradle](https://img.shields.io/badge/Gradle-02303A?style=flat-square&logo=gradle&logoColor=white) ![Swagger](https://img.shields.io/badge/OpenAPI-SpringDoc-85EA2D?style=flat-square&logo=swagger&logoColor=black) ![Lombok](https://img.shields.io/badge/Lombok-BC4521?style=flat-square) ![Whisper](https://img.shields.io/badge/faster--whisper-FFD21E?style=flat-square&logo=openai&logoColor=black) ![FFmpeg](https://img.shields.io/badge/FFmpeg-007808?style=flat-square&logo=ffmpeg&logoColor=white) ![License](https://img.shields.io/badge/use-personal-lightgrey?style=flat-square)
--- ## πŸ“– κ°œμš” **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**. ```bash # μ‹€ν–‰ (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` λ„λ©”μΈμ˜ λž­ν‚Ή/크둀 데이터 연동. ## πŸ“ λΌμ΄μ„ μŠ€ 개인용 ν”„λ‘œμ νŠΈμž…λ‹ˆλ‹€.
Built with Spring Boot Β· Thymeleaf Β· faster-whisper Β· ffmpeg