Spotify 데이터를 기반으로 음악 티어메이커를 만들기 위한 Spring Boot 백엔드입니다.
현재 MVP의 핵심 범위는 Spotify 아티스트/앨범/트랙 조회 API입니다. 티어리스트 도메인과 OAuth2 로그인 관련 코드는 일부 존재하지만, 컨트롤러와 로그인 플로우는 현재 비활성화되어 있습니다.
| 영역 | 사용 기술 |
|---|---|
| Language | Kotlin 2.2.21, JDK 21 |
| Framework | Spring Boot 3.5.10, Spring MVC |
| Data | Spring Data JPA, PostgreSQL (현재 비활성화) |
| Cache | Redis |
| External API | Spotify Web API |
| HTTP Client | WebClient, Kotlin Coroutines |
| Resilience | Resilience4j RateLimiter |
| Security | Spring Security, CORS |
| Build | Gradle Wrapper |
- Spotify 아티스트 검색
- 아티스트 인기 트랙 조회
- 아티스트 앨범 목록 조회
- 앨범 수록곡 조회
- Spotify access token Redis 캐싱
- 앨범/트랙 조회 결과 Redis 캐싱
- Spotify API rate limit 대응
- 커스텀 페이지네이션 및 정렬 파라미터 검증
src/main/kotlin/backend
├── auth # 회원, 권한, OAuth2 사용자 서비스
├── common # 공통 설정, 예외 처리, 페이지네이션, 상수
├── config # Web MVC, Resilience4j 설정
├── spotify # Spotify API 연동, DTO, 컨트롤러, 서비스
└── tierlist # 티어리스트 도메인, 서비스, 저장소
- JDK 21
- Redis
- Spotify Developer App의
client_id,client_secret
애플리케이션 기본 포트는 10001입니다.
루트 디렉터리에 .env 파일을 생성합니다.
Copy-Item .env.example .envmacOS/Linux 환경에서는 다음 명령을 사용할 수 있습니다.
cp .env.example .env개발 환경에서 필요한 기본 값은 다음과 같습니다.
SPRING_PROFILES_ACTIVE=dev
DEV_REDIS_HOST=localhost
DEV_REDIS_PORT=6379
SPOTIFY_CLIENT_ID=your_spotify_client_id
SPOTIFY_CLIENT_SECRET=your_spotify_client_secret운영 프로필(prod)에서는 다음 값도 필요합니다.
PROD_REDIS_HOST=prod-redis-host
PROD_REDIS_PORT=6379
PROD_REDIS_PASSWORD=secure_redis_passwordDB 관련 환경 변수는 .env.example에 보존되어 있지만 현재 MVP에서는 사용하지 않습니다.
Redis를 먼저 실행한 뒤 애플리케이션을 시작합니다.
.\gradlew.bat bootRunmacOS/Linux 환경에서는 다음 명령을 사용할 수 있습니다.
./gradlew bootRun정상 실행 후 기본 API 주소는 다음과 같습니다.
http://localhost:10001/api
.\gradlew.bat testmacOS/Linux:
./gradlew test이미지를 빌드합니다.
docker build -t rithmify-be .컨테이너 실행 예시:
docker run --rm -p 10001:10001 --env-file .env rithmify-beDockerfile은 SPRING_PROFILES_ACTIVE=prod를 기본값으로 사용합니다. 로컬 .env만으로 컨테이너를 실행하려면 운영용 Redis 환경 변수를 함께 준비하거나 실행 시 프로필을 dev로 덮어써야 합니다.
docker run --rm -p 10001:10001 --env-file .env -e SPRING_PROFILES_ACTIVE=dev rithmify-beBase URL:
/api
GET /api/spotify/search/artists?query={query}응답 예시:
[
{
"id": "0TnOYISbd1XYRBk9myaseg",
"name": "Pitbull",
"images": [
{
"url": "https://i.scdn.co/image/...",
"height": 640,
"width": 640
}
],
"genres": ["dance pop", "miami hip hop"]
}
]GET /api/spotify/artists/{artistId}/top-tracks응답 예시:
[
{
"id": "0dA2Mk56wEzDgegdC6R17Y",
"name": "Timber",
"artistName": "Pitbull, Kesha",
"albumName": "Meltdown",
"imageUrl": "https://i.scdn.co/image/...",
"releaseDate": "2013-01-01",
"durationMs": 204160
}
]GET /api/spotify/artists/{artistId}/albums?page=0&size=20&sort=release_date&direction=desc쿼리 파라미터:
| 이름 | 기본값 | 설명 |
|---|---|---|
page |
0 |
0부터 시작하는 페이지 번호 |
size |
20 |
페이지 크기. 허용 범위: 1-100 |
sort |
없음 | 허용 값: name, release_date |
direction |
asc |
허용 값: asc, desc |
응답은 Spring Page<AlbumResponse> 형태입니다.
{
"content": [
{
"id": "4aawyAB9vmqN3uQ7FjRGTy",
"name": "Global Warming",
"images": [
{
"url": "https://i.scdn.co/image/...",
"height": 640,
"width": 640
}
],
"releaseDate": "2012-11-16",
"totalTracks": 12
}
],
"totalElements": 1,
"totalPages": 1,
"size": 20,
"number": 0
}GET /api/spotify/albums/{albumId}/tracks응답 예시:
[
{
"id": "3BovdzfaX4jb5KFQwoPfAw",
"name": "Give Me Everything",
"artistName": "Pitbull, Ne-Yo, Afrojack, Nayer",
"albumName": "Planet Pit",
"imageUrl": "https://i.scdn.co/image/...",
"releaseDate": "2011-06-17",
"durationMs": 251067
}
]- Spotify access token은 Redis의
spotify:access_token키에 저장됩니다. - 아티스트 앨범 목록은
spotify:v4:artist:{artistId}:albums키로 24시간 캐싱됩니다. - 앨범 수록곡은
spotify:v4:album:{albumId}:tracks키로 24시간 캐싱됩니다. - Spotify API 호출은 30초당 50회로 제한됩니다.
- Spotify가
429 Too Many Requests를 반환하면Retry-After헤더를 기준으로 최대 3회 재시도합니다.
공통 에러 응답 형식:
{
"code": "COMMON_400_003",
"message": "유효하지 않은 페이지네이션 필드입니다: sort"
}주요 에러:
| 코드 예시 | HTTP 상태 | 의미 |
|---|---|---|
COMMON_400_003 |
400 | 페이지네이션 또는 정렬 파라미터 오류 |
SPOTIFY_502_001 |
502 | Spotify API 호출 실패 |
COMMON_500_001 |
500 | 서버 내부 오류 |
다음 기능은 코드 일부가 존재하지만 현재 HTTP API로 노출되어 있지 않습니다.
- PostgreSQL/JPA 기반 DB 기능
/api/tier-lists티어리스트 생성/조회 컨트롤러- Spotify OAuth2 로그인 플로우
관련 코드는 유지되어 있으므로 기능을 다시 열 때는 다음 파일을 우선 확인하면 됩니다.
src/main/kotlin/backend/RithmifyBeApplication.ktsrc/main/kotlin/backend/tierlist/controller/TierListController.ktsrc/main/kotlin/backend/tierlist/service/TierListService.ktsrc/main/kotlin/backend/common/config/SecurityConfig.ktsrc/main/kotlin/backend/auth/service/CustomOAuth2UserService.kt
docs/api_documentation.mddocs/coding_style_preferences.mddocs/llm_development_workflow.md