Skip to content

SWYP-Find/Picke-iOS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

71 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Picke iOS

κ°€μΉ˜κ΄€ μΆ©λŒμ—μ„œ μ‹œμž‘ν•˜λŠ” 1:1 μ² ν•™ λ°°ν‹€ ν”Œλž«νΌ, Picke

Platform Language iOS Xcode TCA Tuist Fastlane

🎯 Features | πŸ— Architecture | πŸš€ Quick Start | πŸ” OAuth Flow


πŸ“– ν”„λ‘œμ νŠΈ μ†Œκ°œ

Picke λŠ” μΌμƒμ˜ κ°€μΉ˜κ΄€ 차이λ₯Ό 1:1 ν† λ‘ μœΌλ‘œ ν’€μ–΄λ‚΄λŠ” λͺ¨λ°”일 ν† λ‘ Β·νˆ¬ν‘œ ν”Œλž«νΌμž…λ‹ˆλ‹€. "였늘의 λ°°ν‹€" μ£Όμ œμ— λŒ€ν•œ 사전·사후 νˆ¬ν‘œ, μ‹€μ‹œκ°„ 1:1 μ±„νŒ… ν† λ‘ , 그리고 리캑 μΉ΄λ“œκΉŒμ§€ ν•œ νλ¦„μœΌλ‘œ μ΄μ–΄μ§‘λ‹ˆλ‹€.

πŸ’‘ μ™œ λ§Œλ“€μ—ˆλ‚˜? SNS 의 단방ν–₯ 의견 ν‘œμΆœ λŒ€μ‹ , μ§§κ³  λͺ…ν™•ν•œ 1:1 토둠을 톡해 "λ‚΄κ°€ μ™œ κ·Έλ ‡κ²Œ μƒκ°ν•˜λŠ”μ§€" λ₯Ό μ •λ¦¬ν•˜κ³  λ‹€λ₯Έ κ°€μΉ˜κ΄€μ„ λ§ˆμ£Όν•˜λŠ” κ²½ν—˜μ„ μ œκ³΅ν•©λ‹ˆλ‹€.

πŸ›  Setup

AI 도ꡬ 연동

ν”„λ‘œμ νŠΈ κ·œμΉ™μ€ AGENTS.md / CLAUDE.md 에 μ •μ˜λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

ln -s AGENTS.md CLAUDE.md

✨ μ£Όμš” κΈ°λŠ₯

πŸ” μ†Œμ…œ 둜그인 (server-mediated OAuth)

  • Google / Kakao: WKWebView 기반 authorize β†’ code κ°€λ‘œμ±„κΈ° β†’ λ°±μ—”λ“œ 토큰 κ΅ν™˜
  • Apple Sign-In: ASAuthorizationAppleIDProvider λ„€μ΄ν‹°λΈŒ 톡합
  • μžλ™ 토큰 κ°±μ‹ : AccessTokenCredential JWT exp λ””μ½”λ”© + 만료 5λΆ„ μ „ μžλ™ refresh
  • 401 μžλ™ 처리: AuthInterceptor κ°€ 401 감지 β†’ refresh μ‹œλ„ β†’ μ‹€νŒ¨ μ‹œ μžλ™ λ‘œκ·Έμ•„μ›ƒ μ•Œλ¦Ό λ°œμ†‘

πŸ₯Š 였늘의 λ°°ν‹€

  • 사전 νˆ¬ν‘œ β†’ 1:1 μ±„νŒ… ν† λ‘  β†’ 사후 νˆ¬ν‘œ 의 ν•œ 흐름
  • μž¬νˆ¬ν‘œ 둜 κ°€μΉ˜κ΄€μ΄ λ°”λ€Œμ—ˆλŠ”μ§€ 좔적
  • 리캑 μΉ΄λ“œ μžλ™ 생성 + 곡유

πŸ’¬ ν† λ‘  / λŒ“κΈ€

  • μ±„νŒ…λ°©ν˜• 1:1 ν† λ‘ 
  • μ½˜ν…μΈ λ³„ λŒ“κΈ€Β·λŒ€λŒ“κΈ€
  • 신고·차단

🧭 탐색 / ν™ˆ

  • νλ ˆμ΄νŒ…λœ ν™ˆ ν”Όλ“œ
  • μΉ΄ν…Œκ³ λ¦¬Β·νƒœκ·Έ 탐색
  • ν† ν”½ 검색

πŸ‘€ λ§ˆμ΄νŽ˜μ΄μ§€

  • λ‚΄ μ½˜ν…μΈ  ν™œλ™ / ν† λ‘  기둝
  • λ‚˜μ˜ μ² ν•™μž μœ ν˜•
  • 포인트 λ‚΄μ—­ / μ•Œλ¦Ό / μ„€μ •

πŸ— ν”„λ‘œμ νŠΈ μ•„ν‚€ν…μ²˜

🎯 Clean Architecture Γ— Tuist λ©€ν‹° λͺ¨λ“ˆ

Picke-iOS/
β”œβ”€β”€ πŸ“± Projects/
β”‚   β”œβ”€β”€ App/                       # 메인 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ νƒ€κ²Ÿ
β”‚   β”‚   β”œβ”€β”€ Sources/
β”‚   β”‚   β”‚   β”œβ”€β”€ Application/       # AppDelegate, SceneDelegate
β”‚   β”‚   β”‚   β”œβ”€β”€ Di/                # WeaveDI 등둝 (DiRegister, AppPresentationContextProvider)
β”‚   β”‚   β”‚   β”œβ”€β”€ Reducer/           # TCA Root AppReducer
β”‚   β”‚   β”‚   └── View/              # Root Views
β”‚   β”‚   └── Derived/               # Tuist 생성 plist
β”‚   β”‚
β”‚   β”œβ”€β”€ Presentation/              # 🎨 UI Layer
β”‚   β”‚   β”œβ”€β”€ Auth/                  # 둜그인 / 코디넀이터 / Toast
β”‚   β”‚   β”œβ”€β”€ Home/                  # ν™ˆ ν”Όλ“œ / νλ ˆμ΄νŒ… / μŠ€μΌˆλ ˆν†€
β”‚   β”‚   β”œβ”€β”€ MainTab/               # νƒ­ λΌμš°νŒ… / GNB
β”‚   β”‚   β”œβ”€β”€ Splash/                # μŠ€ν”Œλž˜μ‹œ
β”‚   β”‚   └── Presentation/          # 곡톡 ν”„λ ˆμ  ν…Œμ΄μ…˜ μœ ν‹Έ
β”‚   β”‚
β”‚   β”œβ”€β”€ Domain/                    # πŸ”₯ Business Logic Layer
β”‚   β”‚   β”œβ”€β”€ Entity/                # Auth / Home / OAuth / Error 도메인 μ—”ν‹°ν‹°
β”‚   β”‚   β”œβ”€β”€ DomainInterface/       # Auth / Home / OAuth Repository + Manager μΈν„°νŽ˜μ΄μŠ€
β”‚   β”‚   └── UseCase/               # AuthUseCaseImpl, UnifiedOAuthUseCase, Provider/{Apple,Google,Kakao}
β”‚   β”‚
β”‚   β”œβ”€β”€ Data/                      # πŸ“‘ Data Layer
β”‚   β”‚   β”œβ”€β”€ Model/                 # BaseResponseDTO / AuthΒ·Home DTO + Entity Mapper
β”‚   β”‚   β”œβ”€β”€ API/                   # PieckeDomain, AuthAPI, HomeAPI, BaseAPI
β”‚   β”‚   β”œβ”€β”€ Service/               # AuthService / HomeService (BaseTargetType), μš”μ²­ λ°”λ””
β”‚   β”‚   └── Repository/            # AuthΒ·Home RepositoryImpl + OAuth Repository
β”‚   β”‚       β”œβ”€β”€ Auth/              # Interceptor, RefreshToken Session, Pool, MoyaProvider ν™•μž₯
β”‚   β”‚       └── OAuth/             # Apple / Google / Kakao / Web OAuth κ΅¬ν˜„
β”‚   β”‚
β”‚   β”œβ”€β”€ Network/                   # 🌐 Network Layer
β”‚   β”‚   β”œβ”€β”€ Networking/            # λ„€νŠΈμ›Œν¬ ν΄λΌμ΄μ–ΈνŠΈ export
β”‚   β”‚   β”œβ”€β”€ Foundations/           # APIHeader / TokenProviding / KeychainTokenProvider
β”‚   β”‚   └── ThirdPartys/           # AsyncMoya / WeaveDI λ“± SPM μž¬λ…ΈμΆœ
β”‚   β”‚
β”‚   └── Shared/                    # πŸ”§ Shared Layer
β”‚       β”œβ”€β”€ DesignSystem/          # 곡톡 UI / 컬러 / 이미지 / Toast
β”‚       β”œβ”€β”€ Shared/                # 곡유 λͺ¨λΈΒ·ν™•μž₯
β”‚       β”œβ”€β”€ ThirdParty/            # μ¨λ“œνŒŒν‹° 래퍼
β”‚       └── Utill/                 # 곡톡 μœ ν‹Έλ¦¬ν‹°
β”‚
β”œβ”€β”€ πŸ”§ Tuist/
β”‚   β”œβ”€β”€ Package.swift              # SPM μ˜μ‘΄μ„± μ •μ˜
β”‚   └── ProjectDescriptionHelpers/ # λͺ¨λ“ˆ ν…œν”Œλ¦Ώ / Plist 헬퍼
└── 🧩 Plugins/
    β”œβ”€β”€ DependencyPlugin/          # λͺ¨λ“ˆ μ˜μ‘΄μ„± 헬퍼 (.Data / .Domain / .Network ...)
    β”œβ”€β”€ DependencyPackagePlugin/   # SPM μ˜μ‘΄μ„± 헬퍼 (.SPM.asyncMoya ...)
    └── ProjectTemplatePlugin/     # ProjectConfig / Project.makeModule

πŸ›οΈ Clean Architecture Pattern

graph TD
    A[🎨 Presentation Layer] --> B[πŸ”₯ Domain Layer]
    B --> C[πŸ“‘ Data Layer]
    D[🌐 Network Layer] --> C
    E[πŸ”§ Shared Layer] --> A
    E --> B
    E --> C

    A -.-> F[SwiftUI Views]
    A -.-> G[TCA Reducers]
    B -.-> H[UseCases]
    B -.-> I[Entities]
    C -.-> J[Repositories]
    C -.-> K[API Services]
Loading

πŸ•ΈοΈ TuistSpider ν™•μž₯ λ·°

λ ˆμ΄μ–΄λ³„λ‘œ λ¬Άμ–΄ λ³΄κ±°λ‚˜(Grouped) λͺ¨λ“  λͺ¨λ“ˆμ„ 펼쳐 λ³Έ(Expanded) μ‹œκ°ν™”μž…λ‹ˆλ‹€. (TuistSpider κ²°κ³Ό)

Grouped Expanded

πŸ”„ μ˜μ‘΄μ„± λ°©ν–₯ 원칙

Presentation β†’ Domain (UseCase / Entity)
       ↓
Domain/UseCase β†’ Domain (Interface / Entity)
       ↓
Data/Repository β†’ Domain (Interface / Entity) + Data (Model + Service + API)
       ↓
Data/Service β†’ Data (API) + Network/Foundations (APIHeader) + Domain/Entity (μš”μ²­ 식별값)
       ↓
Network/Foundations β†’ Network/ThirdPartys (AsyncMoya, WeaveDI)

핡심 섀계 원칙

  • βœ… Presentation 은 Domain UseCase / Entity 만 직접 μ°Έμ‘°
  • βœ… Domain 은 μ™ΈλΆ€ 계측에 μ˜μ‘΄ν•˜μ§€ μ•ŠλŠ” 순수 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직
  • βœ… Data/Repository λŠ” Domain μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„, DTO ↔ Entity λ§€ν•‘ λ‹΄λ‹Ή
  • βœ… Data/Service λŠ” endpoint / header / method / parameter μ •μ˜λ§Œ λ‹΄λ‹Ήν•˜κ³  DTO Model 에 μ˜μ‘΄ν•˜μ§€ μ•ŠμŒ
  • βœ… λͺ¨λ“  데이터 흐름은 Domain 을 μ€‘μ‹¬μœΌλ‘œ μ§„ν–‰

πŸ” OAuth 인증 ν”Œλ‘œμš°

Google / Kakao β€” WKWebView server-mediated OAuth

μ•±
  β”‚  authorize URL (response_type=code, redirect_uri=https://picke.store/oauth/<p>)
  β–Ό
WKWebView (OAuthWebViewController)
  β”‚  μ‚¬μš©μž λ™μ˜ β†’ ꡬ글/μΉ΄μΉ΄μ˜€κ°€ redirect_uri 둜 302
  β”‚  WKNavigationDelegate.decidePolicyFor κ°€ picke.store/oauth/<p>?code=... κ°€λ‘œμ±„κΈ°
  β”‚  decisionHandler(.cancel)   ← 401 응닡 솑신 차단
  β–Ό
authorizationCode μΆ”μΆœ β†’ dismiss
  β–Ό
UnifiedOAuthUseCase
  β”‚  POST /api/v1/auth/login/<provider>
  β”‚  body: { authorizationCode, redirectUri }
  β–Ό
AuthRepositoryImpl
  β”‚  BaseResponseDTO<LoginDataDTO> λ””μ½”λ”© β†’ LoginEntity
  β–Ό
KeychainManager μ €μž₯ + AuthSessionManager.credential κ°±μ‹ 

Apple β€” λ„€μ΄ν‹°λΈŒ Sign-In

ASAuthorizationAppleIDProvider 둜 받은 credential / nonce / authorizationCode λ₯Ό κ·ΈλŒ€λ‘œ λ°±μ—”λ“œμ— 전달.

토큰 μžλ™ κ°±μ‹ 

  • AccessTokenCredential κ°€ access token JWT 의 exp λ₯Ό λ””μ½”λ”©ν•΄ 만료 μ‹œμ  보관
  • AuthInterceptor.adapt μ—μ„œ 만료 5λΆ„ 전이면 TokenRefreshManager κ°€ λ‹¨μΌν™”λœ refresh μˆ˜ν–‰
  • 401 응닡 μ‹œ retry 둜 토큰 κ°±μ‹  ν›„ μž¬μ‹œλ„, μ‹€νŒ¨ μ‹œ NSNotification.refreshTokenExpired λ°œμ†‘ + μžλ™ λ‘œκ·Έμ•„μ›ƒ

πŸ›  기술 μŠ€νƒ

Core Technologies

  • 🎯 Architecture: The Composable Architecture (TCA)
  • πŸ“¦ Modularization: Tuist 4.x (Micro Feature Architecture)
  • πŸ’‰ Dependency Injection: WeaveDI 3.4.1
  • πŸ”€ Navigation: TCAFlow (μ»€μŠ€ν…€)
  • ⚑ Concurrency: Swift Concurrency (async/await)

πŸ“š μ£Όμš” 라이브러리

🎯 μ•„ν‚€ν…μ²˜ & μƒνƒœ 관리

  • ComposableArchitecture β€” 단방ν–₯ μƒνƒœ 관리
  • TCAFlow ⭐️ β€” TCA 기반 ν™”λ©΄ μ „ν™˜ / λ„€λΉ„κ²Œμ΄μ…˜ (μ»€μŠ€ν…€)
  • WeaveDI ⭐️ β€” μ˜μ‘΄μ„± μ£Όμž… μ»¨ν…Œμ΄λ„ˆ (μ»€μŠ€ν…€)

πŸ” 인증 & λ³΄μ•ˆ

  • AuthenticationServices β€” Apple Sign-In, ASWebAuthenticationSession
  • WebKit β€” WKWebView 기반 server-mediated OAuth (Google / Kakao)
  • AppAuth-iOS β€” OAuth 2.0 / OpenID Connect ν΄λΌμ΄μ–ΈνŠΈ (μ˜΅μ…˜)

🌐 λ„€νŠΈμ›Œν‚Ή

  • AsyncMoya ⭐️ β€” async/await 기반 HTTP ν΄λΌμ΄μ–ΈνŠΈ (μ»€μŠ€ν…€)
  • Alamofire / Moya β€” AsyncMoya 의 기반 μŠ€νƒ

🎨 UI & UX

  • SwiftUI β€” μ„ μ–Έν˜• UI
  • SDWebImageSwiftUI β€” 비동기 이미지 λ‘œλ”© / 캐싱

πŸ”₯ λ°±μ—”λ“œ / 뢄석

πŸ›  개발 도ꡬ & μœ ν‹Έλ¦¬ν‹°

πŸ“Š λ‘œκΉ… & 디버깅

  • LogMacro β€” μ»€μŠ€ν…€ λ‘œκΉ… 맀크둜
  • IssueReporting β€” 개발 단계 이슈 좔적
  • XCTestDynamicOverlay β€” ν…ŒμŠ€νŠΈ ν™˜κ²½ μ˜€λ²„λ ˆμ΄

⚑ μ„±λŠ₯ & λ™μ‹œμ„±

  • Clocks β€” μ‹œκ°„ κ΄€λ ¨ μœ ν‹Έλ¦¬ν‹°
  • ConcurrencyExtras β€” Swift Concurrency ν™•μž₯
  • Swift 6.0 β€” μ΅œμ‹  Swift μ–Έμ–΄ κΈ°λŠ₯

πŸ”§ λΉŒλ“œ & 배포

  • Tuist β€” ν”„λ‘œμ νŠΈ 생성 / λͺ¨λ“ˆ μ˜μ‘΄μ„± 관리
  • Swift Package Manager β€” νŒ¨ν‚€μ§€ μ˜μ‘΄μ„± 관리
  • fastlane β€” μžλ™ν™”λœ λΉŒλ“œ / 배포 (μ˜ˆμ •)

πŸ“± 지원 ν™˜κ²½

  • πŸ’» Xcode: 16.0 이상
  • πŸ“± iOS: 17.0 이상
  • ⚑ Swift: 6.0 이상
  • πŸ”§ Tuist: 4.x 이상

πŸš€ λΉ λ₯Έ μ‹œμž‘

βœ… ν•„μˆ˜ μš”κ΅¬μ‚¬ν•­

  • πŸ’» Xcode: 16.0 이상
  • πŸ“± iOS: 17.0 이상
  • ⚑ Swift: 6.0 이상
  • πŸ”§ Tuist: 4.x 이상

πŸ›  μ„€μΉ˜ 및 μ‹€ν–‰

1️⃣ μ €μž₯μ†Œ 클둠

git clone https://github.com/Roy-wonji/Picke-iOS.git
cd Picke-iOS

2️⃣ Tuist μ„€μΉ˜

curl -Ls https://install.tuist.io | bash

3️⃣ ν”„λ‘œμ νŠΈ λΉŒλ“œ / 생성

# 전체 μ›Œν¬ν”Œλ‘œμš° (ꢌμž₯)
./make build      # clean β†’ install β†’ generate

# 단계별 μ‹€ν–‰
./make clean      # λΉŒλ“œ μ‚°μΆœλ¬Ό 정리
./make install    # SPM μ˜μ‘΄μ„± μ„€μΉ˜
./make generate   # Xcode ν”„λ‘œμ νŠΈ 생성

4️⃣ Xcode μ—΄κΈ°

open Picke.xcworkspace

βš™οΈ ν™˜κ²½ μ„€μ •

λ‹€μŒ 킀듀을 Picke-Dev.xcconfig / Picke-Stage.xcconfig / Picke-Prod.xcconfig 에 μ±„μ›Œμ£Όμ„Έμš”.

BASE_URL              = picke.store
GOOGLE_CLIENT_ID      = YOUR_GOOGLE_WEB_CLIENT_ID
GOOGLE_IOS_CLIENT_ID  = YOUR_GOOGLE_IOS_CLIENT_ID
REVERSED_CLIENT_ID    = YOUR_REVERSED_CLIENT_ID
KAKAO_REST_API_KEY    = YOUR_KAKAO_REST_API_KEY

🌐 OAuth 사전 등둝

Provider redirect_uri λΉ„κ³ 
Google https://picke.store/oauth/google Web client ID + Google Cloud Console 등둝 ν•„μš”
Kakao https://picke.store/oauth/kakao Kakao Developers μ½˜μ†” 등둝 ν•„μš”
Apple (λ„€μ΄ν‹°λΈŒ) App Store Connect β†’ Sign in with Apple

πŸ› οΈ μ£Όμš” λͺ…λ Ήμ–΄

πŸ”„ κΈ°λ³Έ μ›Œν¬ν”Œλ‘œμš°

./make build      # 전체 λΉŒλ“œ ν”„λ‘œμ„ΈμŠ€ (ꢌμž₯)
./make generate   # ν”„λ‘œμ νŠΈ μƒμ„±λ§Œ
./make clean      # λΉŒλ“œ μ‚°μΆœλ¬Ό 정리
./make install    # μ˜μ‘΄μ„± μ„€μΉ˜

🚨 문제 ν•΄κ²°

tuist clean       # Tuist μΊμ‹œ 정리
./make clean      # λͺ¨λ“  λΉŒλ“œ 파일 정리

πŸ” μ½”λ“œ ν’ˆμ§ˆ / κ·Έλž˜ν”„

tuist graph       # μ˜μ‘΄μ„± κ·Έλž˜ν”„ 생성
tuist test        # 전체 ν…ŒμŠ€νŠΈ μ‹€ν–‰

πŸ“„ λΌμ΄μ„ μŠ€

이 ν”„λ‘œμ νŠΈλŠ” MIT λΌμ΄μ„ μŠ€ ν•˜μ— λ°°ν¬λ©λ‹ˆλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ LICENSE νŒŒμΌμ„ μ°Έκ³ ν•˜μ„Έμš”.

πŸ‘₯ νŒ€ & ν¬λ ˆλ”§

πŸ’» κ°œλ°œνŒ€

  • iOS Lead Developer: μ„œμ›μ§€ (@Roy-wonji)

πŸ›  기술 μŠ€νƒ

  • iOS: Swift Xcode Fastlane

  • Server: AWS EC2 AWS Swagger

  • Design: Figma

  • VCS: Git GitHub

πŸˆβ€β¬› Git 브랜칭 μ „λž΅

1️⃣ Git Branching Strategy

  • main: ν”„λ‘œλ•μ…˜ 배포용
  • develop: 개발 톡합 브랜치
  • feature/*: κΈ°λŠ₯별 개발 브랜치
  • fix/*: 버그 ν”½μŠ€ 브랜치

πŸ“‹ μ›Œν¬ν”Œλ‘œμš°

  1. develop μ—μ„œ feature/ 브랜치 생성
  2. κΈ°λŠ₯ 개발 β†’ 자체 컀밋 λ‹¨μœ„ SRP 뢄리
  3. feature/ β†’ develop Pull Request, μ½”λ“œ 리뷰
  4. develop β†’ main 배포 Pull Request

✍️ 컀밋 λ©”μ‹œμ§€

  • ν•œκ΅­μ–΄ μ‚¬μš©
  • κ΄€λ ¨ GitHub 이슈 번호 λ§€μΉ­ (예: #20 #2)
  • ν˜•μ‹: <type>: <μš”μ•½> #<issue>
  • feat / fix / refactor / chore / docs / test

πŸ“ž 문의 및 지원


Made with ❀️ by Picke Team

Star this repo

About

Picke iOS

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors