달려는 러닝 기록을 관리하고 랭킹을 제공하는 백엔드 서비스입니다.
- Java: 17
- Spring Boot: 4.0.0
- Spring Data JPA: 데이터베이스 접근
- MySQL: 데이터베이스
- JWT: 인증 토큰 관리
- Lombok: 보일러플레이트 코드 감소
- Gradle: 빌드 도구
spring-boot-starter-data-jpa: JPA 및 데이터베이스 지원spring-boot-starter-webmvc: REST API 지원spring-boot-starter-validation: 요청 데이터 검증io.jsonwebtoken:jjwt: JWT 토큰 생성/검증com.nimbusds:nimbus-jose-jwt: Apple OAuth 토큰 검증
src/main/java/com/ohgiraffers/dalryeo/
├── auth/ # 인증 관련
│ ├── controller/ # AuthController
│ ├── dto/ # 요청/응답 DTO
│ ├── entity/ # User 엔티티
│ ├── exception/ # 예외 처리
│ ├── jwt/ # JWT 토큰 관리
│ ├── oauth/ # Apple OAuth 검증
│ ├── repository/ # UserRepository
│ └── service/ # AuthService
├── onboarding/ # 온보딩 관련
│ ├── controller/ # OnboardingController
│ ├── dto/ # 요청/응답 DTO
│ └── service/ # OnboardingService
├── record/ # 러닝 기록 관련
│ ├── controller/ # RecordController
│ ├── dto/ # 요청/응답 DTO
│ ├── entity/ # RunningRecord 엔티티
│ ├── repository/ # RunningRecordRepository
│ └── service/ # RecordService
├── analysis/ # 분석 관련
│ ├── controller/ # AnalysisController
│ ├── dto/ # 요청/응답 DTO
│ └── service/ # AnalysisService
├── ranking/ # 랭킹 관련
│ ├── controller/ # RankingController
│ ├── dto/ # 요청/응답 DTO
│ └── service/ # RankingService
└── common/ # 공통 클래스
└── CommonResponse.java # 공통 응답 형식
- Apple OAuth 로그인
- JWT 토큰 기반 인증
- Refresh Token 재발급
- 로그아웃 및 회원 탈퇴
- 닉네임 중복 체크
- 온보딩 정보 저장 (닉네임, 성별, 생년월일, 키, 몸무게, 프로필 이미지)
- 예상 티어 계산
- 러닝 기록 저장
- 주간 요약 정보 조회
- 주간 기록 목록 조회
- 전체 기록 조회 (페이징, 정렬, 기간 필터)
- 기록 상세 조회
- 점수 기반 주간 랭킹
- 거리 기반 주간 랭킹
POST /auth/oauth/apple
Content-Type: application/json
{
"identityToken": "xxx.yyy.zzz"
}응답:
{
"success": true,
"data": {
"accessToken": "jwt-access",
"refreshToken": "jwt-refresh",
"isNewUser": true
}
}POST /auth/token/refresh
Content-Type: application/json
{
"refreshToken": "string"
}POST /auth/logout
Authorization: Bearer {accessToken}DELETE /auth/withdraw
Authorization: Bearer {accessToken}GET /onboarding/nickname/check?nickname=abcPOST /onboarding
Authorization: Bearer {accessToken}
Content-Type: application/json
{
"nickname": "서현",
"gender": "F",
"birth": "2020-01-01",
"height": 177,
"weight": 77,
"profileImage": null
}POST /onboarding/estimate-tier
Content-Type: application/json
{
"distanceKm": 3.2,
"paceSecPerKm": 350
}POST /records
Authorization: Bearer {accessToken}
Content-Type: application/json
{
"platform": "IOS",
"distanceKm": 5.01,
"durationSec": 1600,
"avgPaceSecPerKm": 320,
"avgHeartRate": 148,
"caloriesKcal": 340,
"startAt": "2025-11-12T07:00:00",
"endAt": "2025-11-12T07:26:40"
}GET /records/summary
Authorization: Bearer {accessToken}GET /records/weekly
Authorization: Bearer {accessToken}GET /analysis/records?page=1&sort=latest&period=monthly
Authorization: Bearer {accessToken}쿼리 파라미터:
page: 페이지 번호 (기본값: 1)sort: 정렬 옵션 (latest,oldest,distance)period: 기간 필터 (monthly또는 미지정 시 전체)
GET /analysis/records/{recordId}
Authorization: Bearer {accessToken}GET /ranking/weekly/scoreGET /ranking/weekly/distancesrc/main/resources/application.properties 파일에 다음 설정을 추가하세요:
spring.application.name=dalryeo
# 데이터베이스 설정
spring.datasource.url=jdbc:mysql://localhost:3306/your_database
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# JPA 설정
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
# JWT 설정
jwt.secret=your-secret-key-change-this-in-production-use-long-random-string
jwt.access-token-expiration=3600000
jwt.refresh-token-expiration=604800000프로덕션 환경에서는 반드시 jwt.secret 값을 강력한 랜덤 문자열로 변경하세요.
MySQL에서 데이터베이스를 생성합니다:
CREATE DATABASE dalryeo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;./gradlew build./gradlew bootRun또는 IDE에서 DalryeoApplication.java를 실행합니다.
애플리케이션이 실행되면 기본적으로 http://localhost:8080에서 접근할 수 있습니다.
id: 사용자 ID (PK)apple_id: Apple ID (UNIQUE)refresh_token: Refresh Tokenis_withdrawn: 탈퇴 여부nickname: 닉네임 (UNIQUE)gender: 성별 (F/M)birth: 생년월일height: 키weight: 몸무게profile_image: 프로필 이미지 URLcurrent_tier: 현재 티어current_tier_grade: 현재 티어 등급tier_score: 티어 점수created_at: 생성일시updated_at: 수정일시
id: 기록 ID (PK)user_id: 사용자 ID (FK)platform: 플랫폼 (IOS/ANDROID)distance_km: 거리 (km)duration_sec: 시간 (초)avg_pace_sec_per_km: 평균 페이스 (초/km)avg_heart_rate: 평균 심박수calories_kcal: 소모 칼로리start_at: 시작 시간end_at: 종료 시간created_at: 생성일시updated_at: 수정일시
-
Apple OAuth 검증: 현재
AppleOAuthValidator는 기본적인 토큰 파싱만 수행합니다. 프로덕션 환경에서는 Apple의 공개키를 사용하여 실제 서명 검증을 구현해야 합니다. -
JWT Secret: 프로덕션 환경에서는 반드시 강력한 랜덤 문자열로 변경하세요.
-
데이터베이스:
spring.jpa.hibernate.ddl-auto=update는 개발 환경용입니다. 프로덕션에서는validate또는none을 사용하세요. -
티어 계산 로직:
OnboardingService의calculateTier()메서드는 예시 구현입니다. 실제 비즈니스 로직에 맞게 수정이 필요합니다.
| 코드 | 설명 |
|---|---|
| AC-003 | OAuth 토큰 검증 실패 |
| AC-004 | refreshToken 불일치 |
| AC-006 | refreshToken 만료 또는 탈퇴된 사용자 |
대부분의 API는 JWT Access Token이 필요합니다. 요청 헤더에 다음과 같이 포함하세요:
Authorization: Bearer {accessToken}
이 프로젝트는 내부 사용을 위한 프로젝트입니다.