Pickeλ λ Όμμ μΈ μ£Όμ μ λν΄ μλ‘ λ€λ₯Έ "κ΄μ "μ λλκ³ , μ μ κ° μ견 λκ²°(λ°°ν)Β·ν¬νΒ·λκΈλ‘ μν΅νλ μμ λμ€μ»€μ μ±μ λλ€. λ΄λ μ΄μ μ΄ μλ μλλ¦¬μ€ μ½ν μΈ , μ±ν₯ μ§λ¨("μ² νμ μ ν") κ²°κ³Ό 곡μ , μΆμμ²΄ν¬ μ€νΈλ¦Β·ν¬μΈνΈ 보μ λ± κ²μ΄λ―ΈνΌμΌμ΄μ μμλ‘ λ¦¬ν μ μ μ λν©λλ€.
- ν¨ν€μ§λͺ
:
com.picke.app - Gradle λ£¨νΈ νλ‘μ νΈλͺ
:
SwypApp(ꡬνλͺ SWYP μμ μ μ΄λ¦μ΄ λ¨μμμ, GitHub μ‘°μ§λSWYP-Find)
| κΈ°λ₯ | μ€λͺ |
|---|---|
| λ°°ν (Battle) | νΉμ μ£Όμ μ λν μ견 λκ²° μ½ν μΈ . ν¬ν(Vote)μ λκΈ(Comment)λ‘ μ°Έμ¬, "μ€λμ λ°°ν"(TodayBattle) λ° μ μ κ° μ§μ λ°°νμ λ§λλ κΈ°λ₯(λ§μ΄νμ΄μ§ λ΄ λ°°ν λ§λ€κΈ°) ν¬ν¨ |
| κ΄μ (Perspective) | μ£Όμ μ λν μλ‘ λ€λ₯Έ μκ°μ μ μ/νμνλ μ½ν μΈ |
| μλλ¦¬μ€ (Scenario) | μ€λμ€ λ΄λ μ΄μ μ΄ ν¬ν¨λ μ€ν 리ν μ½ν μΈ . μ¬μ ν κ΄μ /λ°°νλ‘ μ°κ²°λλ νλ¦ |
| μ² νμ μ ν (Philosopher type) | μ±ν₯ μ§λ¨ κ²°κ³Όλ₯Ό μ 곡νκ³ κ³΅μ (λ₯λ§ν¬ /recap/)ν μ μλ λ°μ΄λ΄ κΈ°λ₯ |
| μΆμμ²΄ν¬ (Attendance) | μΌμΌ μΆμ 체ν¬, μ£Όκ° μ€νΈλ¦ λ±μ§, 리μλ μ§κΈ. μ΅κ·Ό κ°μ₯ νλ°ν κ°λ°λ κΈ°λ₯ |
| ν΄/ν΄μ¦ (PollQuiz) | λ°°νΒ·μλ리μ€μ μ°κ³λ ν¬ν/ν΄μ¦ |
| λ§μ΄νμ΄μ§ | νλ‘ν, ν¬μΈνΈ(μΈμ± μ¬ν), 곡μ§, μλ¦Ό μ€μ , νν΄, νλ λ΄μ(ν λ‘ /μ½ν μΈ ) λ± |
| ν | λ² μ€νΈ/μ κ·/μ€λμ ν½/νΈλ λ© μ½ν μΈ νλ μ΄μ |
| νμ (Explore) | μ½ν μΈ νμ |
| μλ¦Ό | FCM νΈμ (λ°°ν/κ΄μ /κ³΅μ§ μλ¦Ό), λ₯λ§ν¬ λΌμ°ν |
| λ‘κ·ΈμΈ/곡μ | μΉ΄μΉ΄μ€Β·κ΅¬κΈ μμ λ‘κ·ΈμΈ, μΉ΄μΉ΄μ€ν‘Β·μΈμ€νκ·Έλ¨ κ³΅μ |
λ¨μΌ :app λͺ¨λ ꡬ쑰μ΄λ©° (λ©ν°λͺ¨λ μλ), Clean Architecture (data / domain / presentation) 3κ³μΈ΅μ κΈ°λ₯(feature) λ¨μλ‘ λλ ꡬ쑰μ
λλ€. Jetpack Compose κΈ°λ° UI, MVVM ν¨ν΄μ μ¬μ©ν©λλ€.
app/src/main/java/com/picke/app/
βββ SwypApplication.kt # Hilt μ§μ
μ , Kakao SDK μ΄κΈ°ν, FCM μ±λ μ€μ
βββ MainActivity.kt
βββ analytics/ # Mixpanel νΈλνΉ ν¬νΌ
βββ di/ # Hilt λͺ¨λ (Network, Api, Repository, AdMob, Mixpanel)
βββ data/
β βββ local/ # λ‘컬 μ μ₯μ (EncryptedSharedPreferences)
β βββ model/ # DTO
β βββ remote/ # Retrofit API μΈν°νμ΄μ€ (κΈ°λ₯λ³ 1κ°μ©), AuthInterceptor, TokenAuthenticator
β βββ repository/ # RepositoryImpl (κΈ°λ₯λ³)
βββ domain/
β βββ model/ # λλ©μΈ λͺ¨λΈ. "XxxBoard" λ€μ΄λ° 컨벀μ
μ¬μ© (μ: AttendanceBoard, BattleBoard)
β βββ repository/ # Repository μΈν°νμ΄μ€
β βββ usecase/ # κΈ°λ₯λ³ UseCase (μ΅κ·Ό 리ν©ν°λ§λ¨: refactor/usecase-layer)
βββ notification/ # FCMService
βββ ui/ # Compose νλ©΄. κΈ°λ₯λ³ ν¨ν€μ§, κ°κ° Screen + ViewModel + UiState (+ Skeleton) ꡬμ±
β βββ attendance/, battleentry/, comment/, component/, explore/,
β βββ home/, login/, main/, my/, onboarding/, perspective/,
β βββ recommend/, scenario/, splash/, theme/, todaybattle/, vote/, alarm/
βββ util/
μ°Έκ³ μ¬ν
- Room μμ‘΄μ±μ΄ λ²μ μΉ΄νλ‘κ·Έμλ μμΌλ μ€μ
app/build.gradle.ktsμμλ μ£Όμ μ²λ¦¬λμ΄ μμ΅λλ€ β νμ¬ λ‘컬 DB λ―Έμ¬μ© - AdMob μ°λ μ½λλ μ‘΄μ¬νμ§λ§
SwypApplication.ktλ±μμ λΉνμ±ν(μ£Όμ μ²λ¦¬)λ μν
μΈμ΄ / λΉλ
- Kotlin 2.0.21 (JVM target 17)
- AGP 9.0.1, Gradle 9.1.0
- compileSdk 36 / minSdk 26 / targetSdk 35
UI
- Jetpack Compose (Compose BOM 2024.10.01), Material3 β XML λ·° λ―Έμ¬μ©
- Navigation Compose 2.8.5
- Coil 2.7.0 (μ΄λ―Έμ§), Media3 ExoPlayer/UI 1.4.1 (μλλ¦¬μ€ μ€λμ€ μ¬μ)
μν€ν μ² / DI
- Hilt 2.59.2 + KSP 2.0.21-1.0.28
- Clean Architecture (data/domain/ui), Paging3 3.3.2/3.4.2
λ€νΈμνΉ
- Retrofit 2.11.0 + Gson, OkHttp 4.12.0
λ‘컬 μ μ₯
- androidx-security-crypto (EncryptedSharedPreferences) β Room/DataStore λ―Έμ¬μ©
μΈμ¦ / μμ
- Kakao SDK 2.20.1, Google Play Services Auth 21.0.0
Firebase / μλ¦Ό
- Firebase BOM 33.5.1 (Realtime Database, Dynamic Links, FCM)
λΆμ / λͺ¨λν°λ§
- Mixpanel 7.5.0, Sentry 5.8.0
κ΄κ³ (νμ¬ λΉνμ±ν)
- Google Play Services Ads (AdMob) 23.6.0
ν μ€νΈ
- JUnit4, MockK 1.13.13, kotlinx-coroutines-test, Espresso, Compose UI Test
λΉλ μ μλ νμΌμ κ°μ μ±μμΌ ν©λλ€ (λ λ€ .gitignoreμ ν¬ν¨λμ΄ μ μ₯μμ μμ):
**local.properties**μ νμν ν€:
KAKAO_DEBUG_APPKEY=...
GOOGLE_WEB_CLIENT_ID=...
ADMOB_APP_ID=...
ADMOB_REWARDED_AD_UNIT_ID=...
MIXPANEL_PROJECT_TOKEN=...
SENTRY_DSN=...
# release μλͺ
μ©
storeFile=...
storePassword=...
keyAlias=...
keyPassword=...
sentry.properties: ProGuard λ§€ν μ
λ‘λμ© Sentry μΈμ¦ ν ν° νμ
λΉλ variantλ³ BASE_URL
debug:https://dev.picke.store/release:https://picke.store/(minify + shrink νμ±ν, μλͺ νμ)
νμ¬ GitHub Actions λ± CI μ€μ μμ.