Skip to content

woolnd/Yunseul

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

56 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🌠 윀슬 (Yunseul)

별은 μ–Έμ œλ‚˜ 우리λ₯Ό λ³Έλ‹€. μš°λ¦¬κ°€ λ³Ό 수 없을 뿐.

λ‹Ήμ‹ μ˜ 생일별(Birth Star)이 μ§€κΈˆ 이 μˆœκ°„ 지ꡬ μ–΄λ””λ₯Ό λΉ„μΆ”κ³  μžˆμ„κΉŒμš”?
μœ€μŠ¬μ€ κ·Έ 여정을 μ‹€μ‹œκ°„μœΌλ‘œ μΆ”μ ν•˜κ³ , 감정을 λ‹΄μ•„ κΈ°λ‘ν•˜λŠ” 천체 μ—¬ν–‰ λ‹€μ΄μ–΄λ¦¬μž…λ‹ˆλ‹€. Group 20


πŸ“± Core Features

πŸ—ΊοΈ Live Star Tracker

  • MapKit 기반 μ‹€μ‹œκ°„ μ„±ν•˜μ (Sub-stellar Point) μ‹œκ°ν™”
  • 생일 기반 μˆ˜ν˜Έμ„±μ˜ κ³ λ„Β·λ°©μœ„κ° 계산
  • Widget으둜 였늘의 별 μœ„μΉ˜ ν•œλˆˆμ— 확인
  • μ˜€ν”„λΌμΈ 지원: 인터넷 없이도 천체 계산 κ°€λŠ₯

πŸ›‚ Journey Passport

  • 별이 μ§€λ‚˜κ°„ νŠΉλ³„ν•œ μž₯μ†Œλ“€μ„ Core Data 기반으둜 기둝
  • μˆœκ°„μ˜ μ’Œν‘œ, μ‹œκ°„, λ¬΄λ“œλ₯Ό μŠ€νƒ¬ν”„μ²˜λŸΌ μˆ˜μ§‘
  • λ‚˜λ§Œμ˜ 천체 κ΄€μΈ‘ μ•„μΉ΄μ΄λΈŒ ꡬ성
  • 사진 + 짧은 일기둜 μΆ”μ–΅ 보관

πŸ”” Smart Notifications

  • 관심 μ§€μ—­(POI) 등둝 μ‹œ 별이 ν†΅κ³Όν•˜λŠ” μˆœκ°„ μ•Œλ¦Ό
  • λ°±κ·ΈλΌμš΄λ“œ 타이머와 μœ„μΉ˜ μ„Όμ„œλ‘œ μ •ν™•ν•œ 감지
  • μ‹œκ°„λŒ€ μžλ™ λ³€ν™˜(UTC ↔ Local Time)

πŸ› οΈ Tech Stack

Layer Framework Why?
UI Framework SwiftUI + UIKit 메인은 SwiftUI, μ•„μΉ΄μ΄λΈŒ λͺ¨λ“ˆμ€ UIKit (ReactorKit 지원)
State Management TCA (The Composable Architecture) Single Source of Truth νŒ¨ν„΄
Reactive RxSwift μ„Όμ„œ 슀트림 & λ°±κ·ΈλΌμš΄λ“œ 타이머 μ „μ²˜λ¦¬
Data Persistence Core Data μ˜€ν”„λΌμΈ 캐싱 + κ΄€μΈ‘ 기둝 μ €μž₯
Physics Engine SwiftAA Jean Meeus μ•Œκ³ λ¦¬μ¦˜ 기반 μ •λ°€ 천체 μ’Œν‘œ 계산
Mapping MapKit μ„±ν•˜μ  세계 지도 λ Œλ”λ§
Architecture (Sub) ReactorKit μ•„μΉ΄μ΄λΈŒ λͺ¨λ“ˆ 독립 ꡬ성

πŸ”„ Data Flow Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  User Input (Birthday + Location) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ RxSwift Stream     β”‚
    β”‚ Timer + Location   β”‚
    β”‚ Sensor Processing  β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ TCA Reducer        β”‚
    β”‚ Action Handler     β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ SwiftAA Engine     β”‚
    β”‚ (Jean Meeus Algo)  β”‚
    β”‚ ↓ ↓ ↓             β”‚
    β”‚ RA, Dec, Alt, Az   β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚                  β”‚
     β–Ό                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SwiftUI View β”‚  β”‚ Core Data    β”‚
β”‚ MapKit       β”‚  β”‚ Persistence  β”‚
β”‚ Render       β”‚  β”‚ (Manual Save)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ’Ύ Core Data Schema

// 생일별 정보
@Model
final class BirthStar {
    var birthDate: Date
    var constellation: String?
    var cachedEphemeris: [String: Double]?  // 계산 κ²°κ³Ό μΊμ‹œ
    var observations: [ObservationRecord] = []
}

// κ΄€μΈ‘ 기둝 (μŠ€νƒ¬ν”„)
@Model
final class ObservationRecord {
    var timestamp: Date
    var latitude: Double
    var longitude: Double
    var altitude: Double
    var azimuth: Double
    var mood: String?
    var diary: String?
    var imageData: Data?
    
    // μ—­μ°Έμ‘°
    var birthStar: BirthStar?
}

// νŠΉλ³„ν•œ μˆœκ°„ (사진 + 메타데이터)
@Model
final class CapturedMoment {
    var recordedAt: Date
    var imageData: Data
    var location: String?
    var physicsMetadata: String?  // JSON: {ra, dec, mag, etc}
}

πŸ—οΈ Architecture Patterns

TCA (Main Flow)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ AppReducer                          β”‚
β”‚ β”œβ”€ MapFeature                       β”‚
β”‚ β”‚  β”œβ”€ Action: updateStarPosition    β”‚
β”‚ β”‚  └─ State: currentCoordinate      β”‚
β”‚ β”œβ”€ PassportFeature                  β”‚
β”‚ β”‚  β”œβ”€ Action: addObservation        β”‚
β”‚ β”‚  └─ State: observations[]         β”‚
β”‚ └─ SettingsFeature                  β”‚
β”‚    β”œβ”€ Action: updateBirthDate       β”‚
β”‚    └─ State: userPreferences        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

RxSwift (Sensor Layer)

let locationStream = locationManager.asObservable()
    .throttle(.milliseconds(500), scheduler: MainScheduler.instance)
    .map { location in CLLocationCoordinate2D(...) }

let timerStream = Observable<Int>.interval(.seconds(5), scheduler: MainScheduler.instance)
    .flatMap { _ in calculateStarPosition() }

ReactorKit (Archive Module)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ArchiveViewController          β”‚
β”‚ (UIKit + ReactorKit)           β”‚
β”œβ”€ Reactor: ArchiveReactor       β”‚
β”‚  β”œβ”€ State: records[], filter   β”‚
β”‚  β”œβ”€ Action: loadRecords, sort  β”‚
β”‚  └─ Mutation: updateRecords    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🌍 Localization Strategy

Market Concept Tone
πŸ‡°πŸ‡· Korea "μœ„λ‘œμ™€ 감성" β€” 별이 κ±΄λ„€λŠ” μž‘μ€ μœ„λ‘œ λ―Έλ‹ˆλ©€, 닀크 블루, μ‹œμ  ν…μŠ€νŠΈ
πŸ‡―πŸ‡΅ Japan "였늘의 λ³„μš΄μ„Έ" β€” λ³„μ˜ μœ„μΉ˜λ‘œ λŸ­ν‚€ 컬러 μ œμ‹œ κ·€μ—¬μš΄ μ•„μ΄μ½˜, νŒŒμŠ€ν…”, μ μ„±μˆ  톀
πŸ‡ΊπŸ‡Έ USA "Precision Star Tracking" β€” μ²œλ¬Έν•™ 데이터 κ°•μ‘° Sci-Fi UI, ν…Œν¬λ‹ˆμ»¬ λ©”νŠΈλ¦­

πŸ” Privacy & Performance

  • Location: 항상 μ‚¬μš©(Always) κΆŒν•œμœΌλ‘œ λ°±κ·ΈλΌμš΄λ“œ 좔적 (ν•„μš”μ‹œ)
  • Data: λͺ¨λ“  κ΄€μΈ‘ 기둝은 λ””λ°”μ΄μŠ€ 둜컬 μ €μž₯ (ν΄λΌμš°λ“œ 미동기)
  • Offline: SwiftAA μ—”μ§„μœΌλ‘œ 인터넷 없이도 μ •λ°€ 계산 κ°€λŠ₯
  • Battery: 5초 μΈν„°λ²Œ μœ„μΉ˜ μ—…λ°μ΄νŠΈ, Widget은 15λΆ„ λ¦¬ν”„λ ˆμ‹œ

πŸ’‘ Why This Architecture?

문제 ν•΄κ²° 방법
μ„Όμ„œ 데이터 λ…Έμ΄μ¦ˆ RxSwift throttle + debounce
μƒνƒœ λ³΅μž‘λ„ 증가 TCA의 Scope둜 Feature 뢄리
두 κ°€μ§€ μ•„ν‚€ν…μ²˜(TCA + RK) 혼용 λͺ…ν™•ν•œ λͺ¨λ“ˆ 경계: Map/SettingsλŠ” TCA, ArchiveλŠ” RK
κ³ λΉ„μš© 천문 API SwiftAA μ˜€ν”„λΌμΈ 계산 (μœ μ§€λΉ„ 0원)
λ°±κ·ΈλΌμš΄λ“œ μ—…λ°μ΄νŠΈ RxSwift Observable + BGTask μ‘°ν•©

πŸš€ Getting Started

Requirements

  • iOS 16.0+
  • Swift 5.9+
  • CocoaPods / SPM

Installation

pod install
# or
swift package manager

Quick Setup

// BirthStarManager.swift
let manager = BirthStarManager()
manager.setBirthDate(Date(...))
manager.startTracking()  // RxSwift 슀트림 μ‹œμž‘

// MapViewμ—μ„œ κ΄€μ°°
manager.starPositionStream
    .sink { coordinate in
        self.mapView.setCenter(coordinate)
    }
    .store(in: &cancellables)

πŸ“¦ Project Structure

Yunseul/
β”œβ”€β”€ App/
β”‚   β”œβ”€β”€ YunseulApp.swift
β”‚   └── AppDelegate.swift
β”œβ”€β”€ Features/
β”‚   β”œβ”€β”€ Map/
β”‚   β”‚   β”œβ”€β”€ MapReducer.swift
β”‚   β”‚   β”œβ”€β”€ MapView.swift
β”‚   β”‚   └── MapViewModel.swift
β”‚   β”œβ”€β”€ Passport/
β”‚   β”‚   β”œβ”€β”€ PassportReducer.swift
β”‚   β”‚   └── PassportListView.swift
β”‚   β”œβ”€β”€ Archive/
β”‚   β”‚   β”œβ”€β”€ ArchiveViewController.swift
β”‚   β”‚   β”œβ”€β”€ ArchiveReactor.swift
β”‚   β”‚   └── ArchiveCell.swift
β”‚   └── Settings/
β”‚       β”œβ”€β”€ SettingsReducer.swift
β”‚       └── SettingsView.swift
β”œβ”€β”€ Services/
β”‚   β”œβ”€β”€ BirthStarManager.swift
β”‚   β”œβ”€β”€ LocationService.swift
β”‚   └── NotificationService.swift
β”œβ”€β”€ Models/
β”‚   β”œβ”€β”€ BirthStar.swift
β”‚   β”œβ”€β”€ ObservationRecord.swift
β”‚   └── CapturedMoment.swift
β”œβ”€β”€ Utilities/
β”‚   β”œβ”€β”€ SwiftAAWrapper.swift
β”‚   └── CoordinateConverter.swift
└── Resources/
    β”œβ”€β”€ Assets.xcassets
    └── Localizable.strings

🎨 UI Preview

  • Map Screen: 세계 지도 μœ„ λ°˜μ§μ΄λŠ” 별 (μ‹€μ‹œκ°„ μ• λ‹ˆλ©”μ΄μ…˜)
  • Passport List: κΈ°λ‘ν•œ μˆœκ°„λ“€μ„ μΉ΄λ“œ ν˜•μ‹μœΌλ‘œ μ‹œκ°„μˆœ μ •λ ¬
  • Notification: 별이 νŠΉλ³„ν•œ μž₯μ†Œλ₯Ό μ§€λ‚  λ•Œ λ”°λœ»ν•œ λ©”μ‹œμ§€
  • Settings: 생일 μ„€μ •, μ•Œλ¦Ό μ§€μ—­ 등둝, 닀크λͺ¨λ“œ ν† κΈ€

🀝 Contributing

Pull RequestλŠ” μ–Έμ œλ‚˜ ν™˜μ˜ν•©λ‹ˆλ‹€.
이슈 제기 μ‹œ λ‹€μŒμ„ ν¬ν•¨ν•΄μ£Όμ„Έμš”:

  • 버그 μž¬ν˜„ 방법
  • μ˜ˆμƒ vs μ‹€μ œ λ™μž‘
  • λ””λ°”μ΄μŠ€ & iOS 버전

πŸ“„ License

MIT License Β© 2026 Yunseul Project


🌟 λ§ˆμ§€λ§‰μœΌλ‘œ

별은 μ–Έμ œλ‚˜ 우리 곁에 μžˆλ‹€.
μš°λ¦¬κ°€ μ˜¬λ €λ‹€λ³΄μ§€ μ•Šμ•„λ„,
λˆ„κ΅°κ°€μ˜ 탄생일을 쑰용히 λΉ„μΆ”κ³  μžˆλ‹€.

λ‹Ήμ‹ μ˜ 별, μ§€κΈˆ μ–΄λ””λ₯Ό ν–₯ν•΄ κ°€κ³  μžˆλ‚˜μš”?

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages