"μΌμμ΄ λ Ήμ λκΉμ§, μ§μ€."
μΌκ³΅μ SNSμμ μ ννλ μΌμ곡λΆλ²μ μ±μΌλ‘ ꡬνν νμ΅ μ§μ€ νμ΄λ¨Έμ λλ€.
λ¨μ μκ°μ 보μ¬μ£Όμ§ μκ³ , μΌμμ΄ λ Ήλ μ λλ©μ΄μ λ§μΌλ‘ μ§μ€μ μ λν©λλ€. μ»΅ μ¬μ΄μ¦λ₯Ό κ³ λ₯΄λ©΄ λλ€ μκ°μ΄ μ€μ λκ³ , μΌμμ΄ λ€ λ ΉμΌλ©΄ κ³΅λΆ λ!
λ¨μ μκ°μ λΉλ°. μΌμμ΄ λ€ λ Ήμ λκΉμ§ μ§μ€νμΈμ.
- μ»΅ μ¬μ΄μ¦(Tall/Grande/Venti)μ λ°λΌ λλ€ μκ° μ€μ
- λ¨μ μκ°/νΌμΌνΈ μΌμ λΉκ³΅κ°
- μΌμμ΄ λ Ήλ κ²λ§ λ³΄κ³ μ§μ€
μ»΅λ§λ€ λ Ήλ μλκ° λ¬λΌμ. Grandeλ μ²μ²ν, Ventiλ λ~ μ²μ²ν.
- 43κ° μΌμ λΈλ‘μ΄ 8λ μ΄μ΄λ‘ μμ°μ€λ½κ² λ Ήμ
- μ»΅ μ¬μ΄μ¦λ³ λΉμ ν μ΄μ§ μ»€λΈ μ μ©
- μλλΆν° λ¬Όμ΄ μ°¨μ€λ₯΄λ μκ°μ νΌλλ°±
μ΄λ² μ£Όμ λ ΉμΈ λ¬Όμ μλμ΄μ λ΄μ보μΈμ.
- μ 리 μλμ΄μ μ±μμ§λ λ¬ΌμμΌλ‘ 곡λΆλ μκ°ν
- μ£Όκ° μ¬λΌμ΄λ μ νμΌλ‘ κ³Όκ±° κΈ°λ‘ νμΈ
- λͺ©νλ μ΄κ³Ό μ νΉλ³ν λ³ν
ν λ¬κ°μ κ³΅λΆ κΈ°λ‘μ νλμ.
- μλ³ μΌμΌ 곡λΆμκ° + λ¬Όμ κΈ°λ‘
- λλλ‘ κ³΅λΆλ μκ°ν
λ ΉμΈ μΌμ μ, μ΄ λ¬Όμ, μ΄ κ³΅λΆμκ°μ νλμ.
- μ 체 ν΅κ³ μμ½
- μ£Όκ° λ° μ°¨νΈ (μ€ν¬λ¦°νμ μ€νμΌ)
μ§μ€μ λμμ£Όλ μμ κΈ°λ₯λ€.
- λ°±μμμ / λΉμ리 / μ²μ리 (AVAudioEngine)
- μ§μ€λͺ¨λ (νλ©΄ κΊΌμ§ λ°©μ§)
- νμ΄λ¨Έ κ²°κ³Ό 곡μ (μΈμ€ν μΉ΄λ)
- μμ ― μ§μ (μ΄λ² μ£Ό λ¬Όμ νμΈ)
IceStudy/
βββ App/
β βββ IceStudyApp.swift # @main μνΈλ¦¬
β
βββ Models/
β βββ CupSize.swift # μ»΅ μ¬μ΄μ¦ enum (Tall/Grande/Venti)
β βββ TemperatureZone.swift # μ¨λ κΈ°λ° λ¬Όμ κ³μ°
β
βββ ViewModels/
β βββ AuthViewModel.swift # μΈμ¦ μν κ΄λ¦¬
β βββ TimerViewModel.swift # νμ΄λ¨Έ λ‘μ§ + λ°±κ·ΈλΌμ΄λ 보μ
β
βββ Views/
β βββ Splash/
β β βββ SplashView.swift # μ€νλμ (2μ΄)
β βββ Onboarding/
β β βββ OnboardingView.swift # μ΅μ΄ 1ν μ¨λ³΄λ©
β βββ Auth/
β β βββ LoginView.swift # Apple λ‘κ·ΈμΈ + μ΄λ©μΌ
β β βββ SignUpView.swift # νμκ°μ
β β βββ NicknameSetupView.swift # λλ€μ μ€μ
β βββ Home/
β β βββ HomeView.swift # μ£Όκ° λμ보λ + μλμ΄
β β βββ CalendarView.swift # μλ³ μΊλ¦°λ
β βββ Timer/
β β βββ IceTimerFlowView.swift # μν κΈ°λ° νλ©΄ μ ν
β β βββ CupSelectionView.swift # μ»΅ μ ν (3μΉ΄λ)
β β βββ TimerRunningView.swift # νμ΄λ¨Έ μ€ν νλ©΄
β β βββ TimerResultView.swift # μλ£/ν¬κΈ° κ²°κ³Ό
β β βββ IceMeltingView.swift # μΌμ λ
Ήλ μ λλ©μ΄μ
β βββ Profile/
β β βββ ProfileView.swift # νλ‘ν ν΅κ³
β β βββ WeeklyChartView.swift # μ£Όκ° λ° μ°¨νΈ
β β βββ SettingsView.swift # μ€μ (λλ€μ/λΉλ°λ²νΈ/οΏ½οΏ½οΏ½ν΄)
β βββ Components/
β βββ MainTabView.swift # 3ν (μλμ΄/μΌμ/λ§μ΄)
β βββ LogoHeaderView.swift # λ‘κ³ ν€λ
β βββ PrimaryButton.swift # κ³΅ν΅ λ²νΌ
β βββ GlassCupShape.swift # μ 리컡 컀μ€ν
Shape
β
βββ Network/
β βββ TokenStorage.swift # Keychain κΈ°λ° JWT μ μ₯
β βββ APIError.swift # μλ¬ νμ
β βββ DTO/ # AuthDTO, SessionDTO, StatsDTO
β βββ API/ # Moya TargetType (Auth/Session/Stats/User)
β βββ Service/ # API μλΉμ€ λ μ΄μ΄
β
βββ Services/
β βββ LocationService.swift # μμΉ μμ² (CLLocationManager)
β βββ WeatherService.swift # μ¨λ μ‘°ν (Open-Meteo)
β βββ WhiteNoiseService.swift # λ°±μμμ/λΉμ리/μ²μ리
β
βββ Utils/
βββ Constants.swift # AppColor, AppFont
βββ NotificationManager.swift # νΈμ μλ¦Ό κ΄λ¦¬
βββ WidgetData.swift # μμ ― λ°μ΄ν° 곡μ
IceStudyWidget/ # μμ ― Extension
βββ IceStudyWidget.swift # μμ ― UI + Timeline
βββ IceStudyWidgetBundle.swift # Widget Bundle
icestudy-api/
βββ src/main/java/com/icestudy/
βββ config/
β βββ SecurityConfig.java # Spring Security μ€μ
β βββ JwtProvider.java # JWT μμ±/κ²μ¦
β βββ JwtAuthenticationFilter.java # μΈμ¦ νν°
β βββ SwaggerConfig.java # API λ¬Έμ
β βββ ScheduleConfig.java # μ€μΌμ€λ§
β
βββ domain/
β βββ auth/ # μΈμ¦ (μ΄λ©μΌ + Apple)
β β βββ AuthController.java
β β βββ AuthService.java
β β βββ AppleTokenVerifier.java
β β βββ dto/
β βββ user/ # μ μ κ΄λ¦¬
β β βββ UserController.java
β β βββ UserService.java
β β βββ dto/
β βββ session/ # κ³΅λΆ μΈμ
β β βββ SessionController.java
β β βββ SessionService.java
β β βββ WaterCalculator.java # λ¬Όμ κ³μ° λ‘μ§
β β βββ dto/
β βββ stats/ # ν΅κ³
β βββ StatsController.java
β βββ StatsService.java
β βββ dto/
β
βββ global/
βββ common/ApiResponse.java # κ³΅ν΅ μλ΅ λνΌ
βββ exception/ # μμΈ μ²λ¦¬
| νλͺ© | κΈ°μ |
|---|---|
| UI | SwiftUI |
| μν€ν μ² | MVVM |
| μ΅μ λ²μ | iOS 17+ |
| λ€νΈμν¬ | Moya + async/await |
| μΈμ¦ | Sign in with Apple + JWT |
| μ μ₯μ | Keychain (ν ν°) + UserDefaults (μ€μ ) |
| μμ ― | WidgetKit + App Group |
| ν¨ν€μ§ λ§€λμ | SPM |
| νλͺ© | κΈ°μ |
|---|---|
| νλ μμν¬ | Spring Boot 3.5.0 |
| μΈμ΄ | Java 17 |
| DB | MySQL 8.x |
| ORM | Spring Data JPA |
| μΈμ¦ | JWT (Access + Refresh Token) |
| λ¬Έμ | Swagger (springdoc-openapi) |
| λ°°ν¬ | Railway (Docker) |
| Method | Path | μ€λͺ |
|---|---|---|
| POST | /api/auth/signup | νμκ°μ |
| POST | /api/auth/login | μ΄λ©μΌ λ‘κ·ΈμΈ |
| POST | /api/auth/apple | Apple λ‘κ·ΈμΈ |
| POST | /api/auth/refresh | ν ν° κ°±μ |
| POST | /api/sessions | μΈμ μμ± |
| PATCH | /api/sessions/{id}/complete | μΈμ μλ£ |
| PATCH | /api/sessions/{id}/abort | μΈμ ν¬κΈ° |
| GET | /api/stats/weekly | μ£Όκ° ν΅κ³ |
| GET | /api/stats/calendar | μκ° μΊλ¦°λ |
| GET | /api/stats/profile | νλ‘ν ν΅κ³ |
| GET | /api/users/me | λ΄ μ 보 μ‘°ν |
| PATCH | /api/users/me | λ΄ μ 보 μμ |
| μ¬μ΄μ¦ | μκ° λ²μ | μ΅λ λ¬Όμ | μ€λͺ |
|---|---|---|---|
| Tall | 30λΆ ~ 1μκ° 30λΆ | 355ml | κ°λ²Όμ΄ κ³΅λΆ |
| Grande | 1μκ° 30λΆ ~ 3μκ° | 473ml | μ§μ€ κ³΅λΆ |
| Venti | 2μκ° ~ 4μκ° | 591ml | κΉμ κ³΅λΆ |
- 1μΈ κ°λ° νλ‘μ νΈ
- iOS: SwiftUI + Moya (SPM)
- Backend: Spring Boot + MySQL (Railway λ°°ν¬)
μ΄ νλ‘μ νΈλ κ°μΈ νλ‘μ νΈλ‘, λ¬΄λ¨ λ³΅μ λ° λ°°ν¬λ₯Ό κΈν©λλ€.
