Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

StreamFix 🎬

ν—₯사고날 μ•„ν‚€ν…μ²˜(Hexagonal Architecture) νŒ¨ν„΄μ„ μ μš©ν•˜μ—¬ μ„€κ³„λœ 슀트리밍 μ„œλΉ„μŠ€ ν”Œλž«νΌμž…λ‹ˆλ‹€. 이 λ¬Έμ„œλŠ” μ‹ κ·œ κ°œλ°œμžκ°€ ν”„λ‘œμ νŠΈμ˜ ꡬ쑰λ₯Ό μ΄ν•΄ν•˜κ³ , 둜컬 ν™˜κ²½μ—μ„œ ν”„λ‘œμ νŠΈλ₯Ό μ‹€ν–‰ν•  수 μžˆλ„λ‘ μ •ν™•ν•œ κ°€μ΄λ“œλ₯Ό μ œκ³΅ν•˜λŠ” 것을 λͺ©ν‘œλ‘œ ν•©λ‹ˆλ‹€.

πŸ—οΈ μ•„ν‚€ν…μ²˜

λ³Έ ν”„λ‘œμ νŠΈλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 핡심 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직(Core)κ³Ό μ™ΈλΆ€ 기술(Adapters)을 λΆ„λ¦¬ν•˜λŠ” ν—₯사고날 μ•„ν‚€ν…μ²˜λ₯Ό λ”°λ¦…λ‹ˆλ‹€. 이 κ΅¬μ‘°λŠ” μœ μ—°ν•˜κ³  ν™•μž₯ κ°€λŠ₯ν•˜λ©°, μœ μ§€λ³΄μˆ˜κ°€ μš©μ΄ν•œ μ‹œμŠ€ν…œμ„ λ§Œλ“œλŠ” 데 도움을 μ€λ‹ˆλ‹€.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Applications                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚    app-api      β”‚              β”‚   app-batch     β”‚       β”‚
β”‚  β”‚   (REST API)    β”‚              β”‚    (Batch Job)  β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β–²
                              β”‚ μ˜μ‘΄μ„± λ°©ν–₯
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           Core                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  core-domain   β”‚<-β”‚ core-service  β”‚->β”‚  core-port   β”‚    β”‚
β”‚  β”‚ (도메인 λͺ¨λΈ)     β”‚  β”‚ (λΉ„μ¦ˆλ‹ˆμŠ€ 둜직)  β”‚  β”‚  (μΈν„°νŽ˜μ΄μŠ€)   β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                          β–²                                  β”‚
β”‚                          β”‚                                  β”‚
β”‚                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                        β”‚
β”‚                     β”‚ core-usecase β”‚                        β”‚
β”‚                     β”‚  (μœ μŠ€μΌ€μ΄μŠ€)   β”‚                        β”‚
β”‚                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β–²
                              β”‚ μ˜μ‘΄μ„± λ°©ν–₯
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Adapters                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚  β”‚  adapter-http  β”‚  β”‚adapter-persistenceβ”‚ β”‚ adapter-redis β”‚β”‚
β”‚  β”‚ (μ™ΈλΆ€ API 연동)  β”‚  β”‚   (DB 연동)        β”‚  β”‚   (μΊμ‹œ 연동)   β”‚β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“¦ λͺ¨λ“ˆ ꡬ쑰

계측 λͺ¨λ“ˆ μ„€λͺ…
Applications app-api REST APIλ₯Ό μ œκ³΅ν•˜λŠ” Spring Boot μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μž…λ‹ˆλ‹€.
app-batch 데이터 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ λ“± 배치 μž‘μ—…μ„ μ²˜λ¦¬ν•˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μž…λ‹ˆλ‹€.
Core core-domain ν”„λ‘œμ νŠΈμ˜ 핡심 도메인 λͺ¨λΈκ³Ό λΉ„μ¦ˆλ‹ˆμŠ€ κ·œμΉ™μ„ μ •μ˜ν•©λ‹ˆλ‹€.
core-port μ™ΈλΆ€ μ‹œμŠ€ν…œ(DB, API λ“±)과의 톡신을 μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€(Port)λ₯Ό μ •μ˜ν•©λ‹ˆλ‹€.
core-service μœ μŠ€μΌ€μ΄μŠ€μ˜ μ‹€μ œ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ κ΅¬ν˜„ν•©λ‹ˆλ‹€.
core-usecase μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ‹œμŠ€ν…œμ— μ–΄λ–€ κΈ°λŠ₯을 μ œκ³΅ν•΄μ•Ό ν•˜λŠ”μ§€ μ •μ˜ν•˜λŠ” μœ μŠ€μΌ€μ΄μŠ€μž…λ‹ˆλ‹€.
Adapters adapter-http μ™ΈλΆ€ API(TMDB, Kakao)μ™€μ˜ 톡신을 κ΅¬ν˜„ν•˜λŠ” μ–΄λŒ‘ν„°μž…λ‹ˆλ‹€.
adapter-persistence λ°μ΄ν„°λ² μ΄μŠ€(MySQL, JPA) 연동을 μ²˜λ¦¬ν•˜λŠ” μ˜μ†μ„± μ–΄λŒ‘ν„°μž…λ‹ˆλ‹€.
adapter-redis 캐싱 처리λ₯Ό μœ„ν•œ Redis 연동 μ–΄λŒ‘ν„°μž…λ‹ˆλ‹€.
Commons stream-fix-commons μ˜ˆμ™Έ 처리 λ“± μ—¬λŸ¬ λͺ¨λ“ˆμ—μ„œ κ³΅ν†΅μœΌλ‘œ μ‚¬μš©λ˜λŠ” μ½”λ“œλ₯Ό ν¬ν•¨ν•©λ‹ˆλ‹€.
Frontend stream-fix-frontend React 기반의 ν”„λ‘ νŠΈμ—”λ“œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μž…λ‹ˆλ‹€.
Infra infra Docker Composeλ₯Ό μ΄μš©ν•΄ κ°œλ°œμ— ν•„μš”ν•œ 인프라(MySQL, Redis)λ₯Ό μ„€μ •ν•©λ‹ˆλ‹€.

πŸ› οΈ 기술 μŠ€νƒ

λ°±μ—”λ“œ (Backend)

  • Java: 21
  • Spring Boot: 3.5.0
  • Spring Data JPA
  • QueryDSL: 5.1.0
  • Gradle: 8.13
  • DB Migration: Flyway
  • Database: MySQL 8.0
  • Cache: Redis
  • Code Formatting: Spotless (google-java-format)

ν”„λ‘ νŠΈμ—”λ“œ (Frontend)

  • React: 19.1.0
  • Axios, Bootstrap

인프라 (Infrastructure)

  • Docker & Docker Compose

상세 버전 μ •λ³΄λŠ” versions.properties 및 각 λͺ¨λ“ˆμ˜ build.gradle.kts 파일, package.json νŒŒμΌμ„ μ°Έκ³ ν•˜μ„Έμš”.

πŸš€ μ‹€ν–‰ κ°€μ΄λ“œ

1. 사전 μš”κ΅¬μ‚¬ν•­

  • Java 21
  • Node.js 16 이상
  • Docker & Docker Compose

2. μ €μž₯μ†Œ 클둠 및 이동

git clone https://github.com/shokoku/stream-fix.git
cd stream-fix

3. 인프라 μ‹€ν–‰

ν”„λ‘œμ νŠΈμ— ν•„μš”ν•œ MySQL, Redis λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό Docker둜 μ‹€ν–‰ν•©λ‹ˆλ‹€.

cd infra
docker-compose up -d

🐳 Docker μ»¨ν…Œμ΄λ„ˆκ°€ μ •μƒμ μœΌλ‘œ μ‹€ν–‰λ˜μ—ˆλŠ”μ§€ ν™•μΈν•˜μ„Έμš”. (docker ps)

4. ν™˜κ²½ λ³€μˆ˜ μ„€μ •

ν”„λ‘œμ νŠΈ 싀행에 ν•„μš”ν•œ ν™˜κ²½ λ³€μˆ˜λ₯Ό μ„€μ •ν•©λ‹ˆλ‹€. μƒ˜ν”Œ νŒŒμΌμ„ λ³΅μ‚¬ν•˜μ—¬ μ‹€μ œ 값을 μž…λ ₯ν•˜μ„Έμš”.

1) λ°±μ—”λ“œ ν™˜κ²½λ³€μˆ˜ (.env) 루트 경둜의 .env.sample νŒŒμΌμ„ .env둜 λ³΅μ‚¬ν•œ ν›„, μ•„λž˜ ν•­λͺ©λ“€μ„ μžμ‹ μ˜ ν™˜κ²½μ— 맞게 μˆ˜μ •ν•©λ‹ˆλ‹€.

# 1. .env 파일 생성
cp .env.sample .env

# 2. .env 파일 μˆ˜μ •
vi .env
# .env
KAKAO_CLIENT_ID=your-kakao-client-id
KAKAO_CLIENT_SECRET=your-kakao-client-secret
KAKAO_REDIRECT_URL=http://localhost:3000/login/oauth2/code/kakao

JWT_SECRET=your-jwt-secret-key-that-is-long-enough-to-be-secure

2) TMDB API Key μ„€μ • μ˜ν™” 데이터 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ— ν•„μš”ν•œ TMDB API ν‚€λ₯Ό μ„€μ •ν•©λ‹ˆλ‹€.

# 1. adapter-http-property.yml 파일 생성
cp stream-fix-adapters/adapter-http/src/main/resources/adapter-http-property-sample.yml \
   stream-fix-adapters/adapter-http/src/main/resources/adapter-http-property.yml

# 2. adapter-http-property.yml 파일 μˆ˜μ •
vi stream-fix-adapters/adapter-http/src/main/resources/adapter-http-property.yml
# adapter-http-property.yml
tmdb:
  auth:
    access-token: your-tmdb-access-token

5. λ°±μ—”λ“œ μ‹€ν–‰

IntelliJ IDEA와 같은 IDEμ—μ„œ StreamFixApplication.javaλ₯Ό 직접 μ‹€ν–‰ν•˜κ±°λ‚˜, ν„°λ―Έλ„μ—μ„œ Gradle λͺ…λ Ήμ–΄λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

# API μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰
./gradlew :stream-fix-apps:app-api:bootRun

β˜• 졜초 μ‹€ν–‰ μ‹œ μ˜μ‘΄μ„±μ„ λ‹€μš΄λ‘œλ“œν•˜λ―€λ‘œ μ‹œκ°„μ΄ λ‹€μ†Œ μ†Œμš”λ  수 μžˆμŠ΅λ‹ˆλ‹€.

6. ν”„λ‘ νŠΈμ—”λ“œ μ‹€ν–‰

λ³„λ„μ˜ 터미널을 μ—΄μ–΄ ν”„λ‘ νŠΈμ—”λ“œ 개발 μ„œλ²„λ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€.

# ν”„λ‘ νŠΈμ—”λ“œ ν΄λ”λ‘œ 이동
cd stream-fix-frontend

# μ˜μ‘΄μ„± μ„€μΉ˜
npm install

# 개발 μ„œλ²„ μ‹€ν–‰
npm start
  • ν”„λ‘ νŠΈμ—”λ“œ μ„œλ²„λŠ” http://localhost:3000 μ—μ„œ μ‹€ν–‰λ©λ‹ˆλ‹€.

7. (선택) 배치 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰

TMDBμ—μ„œ μ˜ν™” 정보λ₯Ό 가져와 λ°μ΄ν„°λ² μ΄μŠ€μ— μ €μž₯ν•˜λŠ” 배치 μž‘μ—…μ„ μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

# app-batch λͺ¨λ“ˆ μ‹€ν–‰
./gradlew :stream-fix-apps:app-batch:bootRun

πŸ“‹ API μ—”λ“œν¬μΈνŠΈ

Method URL μ„€λͺ… 인증 ν•„μš”
POST /api/v1/user/register 일반 νšŒμ›κ°€μž…μ„ μ§„ν–‰ν•©λ‹ˆλ‹€. No
POST /api/v1/user/login 이메일과 λΉ„λ°€λ²ˆν˜Έλ‘œ λ‘œκ·ΈμΈν•©λ‹ˆλ‹€. No
POST /api/v1/user/callback 카카였 OAuth 인증 μ½œλ°±μ„ μ²˜λ¦¬ν•©λ‹ˆλ‹€. No
GET /api/v1/movie/client/{page} μ™ΈλΆ€(TMDB)μ—μ„œ μ˜ν™” λͺ©λ‘μ„ μ‘°νšŒν•©λ‹ˆλ‹€. Yes
POST /api/v1/movie/search DB에 μ €μž₯된 μ˜ν™” λͺ©λ‘μ„ μ‘°νšŒν•©λ‹ˆλ‹€. Yes
POST /api/v1/movie/{movieId}/download νŠΉμ • μ˜ν™”λ₯Ό λ‹€μš΄λ‘œλ“œν•©λ‹ˆλ‹€. Yes
POST /api/v1/movie/{movieId}/like νŠΉμ • μ˜ν™”μ— 'μ’‹μ•„μš”'λ₯Ό ν‘œμ‹œν•©λ‹ˆλ‹€. Yes
GET /api/v1/sample μƒ˜ν”Œ APIλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€. Yes

πŸ”§ 개발 κ·œμΉ™ 및 κ°€μ΄λ“œ

μ½”λ“œ ν¬λ§·νŒ…

ν”„λ‘œμ νŠΈμ—λŠ” Spotless ν”ŒλŸ¬κ·ΈμΈμ΄ μ μš©λ˜μ–΄ μžˆμ–΄, 컀밋 전에 μ½”λ“œλ₯Ό google-java-format μŠ€νƒ€μΌμ— 맞게 정리해야 ν•©λ‹ˆλ‹€. μ•„λž˜ λͺ…령을 μ‹€ν–‰ν•˜μ—¬ μ½”λ“œ μŠ€νƒ€μΌμ„ μ μš©ν•˜μ„Έμš”.

./gradlew spotlessApply

Git 브랜치 μ „λž΅

Git-Flow λ˜λŠ” GitHub Flow와 같은 브랜치 μ „λž΅μ„ λ”°λ₯΄λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€. 브랜치 이름은 λͺ©μ μ„ λͺ…ν™•νžˆ λ‚˜νƒ€λ‚΄λ„λ‘ μž‘μ„±ν•©λ‹ˆλ‹€.

  • feature: feature/κΈ°λŠ₯-이름 (예: feature/login-api)
  • bugfix: bugfix/버그-μˆ˜μ •-λ‚΄μš© (예: bugfix/fix-movie-like-error)
  • docs: docs/λ¬Έμ„œ-μ—…λ°μ΄νŠΈ-λ‚΄μš© (예: docs/update-readme)
  • refactor: refactor/λ¦¬νŒ©ν† λ§-λ‚΄μš©

❓ νŠΈλŸ¬λΈ”μŠˆνŒ… κ°€μ΄λ“œ

  • Q: bootRun μ‹€ν–‰ μ‹œ Could not find... μ—λŸ¬κ°€ λ°œμƒν•΄μš”.

    • A: Gradle μ˜μ‘΄μ„±μ„ μ œλŒ€λ‘œ λ‹€μš΄λ‘œλ“œν•˜μ§€ λͺ»ν–ˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. IDE의 Gradle νƒ­μ—μ„œ 'Reload All Gradle Projects'λ₯Ό μ‹€ν–‰ν•˜κ±°λ‚˜, ν„°λ―Έλ„μ—μ„œ ./gradlew clean buildλ₯Ό μ‹€ν–‰ν•΄ λ³΄μ„Έμš”.
  • Q: 카카였 둜그인 μ‹œ λ¦¬λ‹€μ΄λ ‰νŠΈ URI 였λ₯˜κ°€ λ°œμƒν•΄μš”.

    • A: 카카였 개발자 μ½˜μ†”μ— λ“±λ‘λœ Redirect URI와 .env 파일의 KAKAO_REDIRECT_URL이 μΌμΉ˜ν•˜λŠ”μ§€ ν™•μΈν•˜μ„Έμš”. (κΈ°λ³Έκ°’: http://localhost:3000/login/oauth2/code/kakao)
  • Q: 포트 좩돌(Port already in use)이 λ°œμƒν•΄μš”.

    • A: λ°±μ—”λ“œ(8080), ν”„λ‘ νŠΈμ—”λ“œ(3000), MySQL(3306), Redis(6379) ν¬νŠΈκ°€ λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ‚¬μš© 쀑인지 ν™•μΈν•˜κ³ , ν•„μš” μ‹œ ν•΄λ‹Ή ν”„λ‘œμ„ΈμŠ€λ₯Ό μ’…λ£Œν•˜κ±°λ‚˜ application.yml, docker-compose.yml νŒŒμΌμ—μ„œ 포트λ₯Ό λ³€κ²½ν•˜μ„Έμš”.
  • Q: ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ API 호좜 μ‹œ 403 Forbidden μ—λŸ¬κ°€ λ°œμƒν•΄μš”.

    • A: 둜그인 ν›„ 받은 JWT 토큰이 HTTP μš”μ²­ ν—€λ”μ˜ Authorization에 Bearer {token} ν˜•μ‹μœΌλ‘œ μ˜¬λ°”λ₯΄κ²Œ ν¬ν•¨λ˜μ—ˆλŠ”μ§€ ν™•μΈν•˜μ„Έμš”.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages