SwiftUI와 TCA(The Composable Architecture)를 기반으로 만든 영화 예매 iOS 애플리케이션입니다. TMDB(The Movie Database)의 공개 API를 활용해 상영 중·개봉 예정·인기 영화 정보를 제공하며, Supabase 인증을 통해 이메일 및 애플·구글·카카오 소셜 로그인을 지원합니다. 예매 정보는 로컬(UserDefaults)에 저장되고, 자체 디자인 시스템으로 일관된 UI/UX를 유지합니다.
- 단일 앱에서 영화 발견 → 상세 조회 → 좌석 선택 및 예매 → 예매 내역 관리까지 완결된 사용자 여정을 제공합니다.
- 소셜 로그인과 로컬 계정을 모두 지원해 다양한 이용자 접근성을 확보했습니다.
- SwiftUI + TCA 조합으로 명확한 상태 관리와 모듈화된 UI 구성을 지향하며, Feature 단위의 독립적인 개발·테스트가 가능합니다.
- 스플래시 & 세션 관리: 앱 시작 시 Splash 화면에서 Supabase 세션과 토큰 만료 시간을 검사해 로그인 여부에 따라 인증 플로우 또는 메인 탭으로 전환합니다.
- 다중 로그인 옵션: 이메일, 애플, 구글, 카카오 로그인을 제공하며 PKCE 기반 Supabase OAuth와 Nonce 관리로 보안을 강화했습니다.
- 영화 탐색: TMDB API를 호출해 Now Playing, Coming Soon, Popular 섹션을 동시에 불러오고, 실패 시 재시도 알림을 제공합니다. 요청은
withThrowingTaskGroup으로 병렬 처리합니다. - 검색 최적화: 로컬에 캐시된 영화 리스트를 활용해 디바운스 검색으로 빠른 응답을 제공하고, 빈 검색어 입력 시 즉시 결과를 초기화합니다.
- 예매 시나리오: 영화 상세 → 극장/시간 선택 → 인원 수 입력 → 예매 완료 알림까지 플로우를 제공합니다. 예매 성공 시 선택 내역과 금액을 안내하는 Alert를 띄웁니다.
- 티켓 관리: UserDefaults 기반 저장소를 통해 예매 내역을 조회·삭제하고, 예매 삭제 성공 시 로컬 상태를 즉시 갱신합니다.
- 마이 페이지: 마지막 로그인 이력과 로그인 공급자를 노출하고 Supabase 로그아웃을 수행합니다. 로그아웃 시 팝업 확인 뒤 세션을 종료합니다.
- 앱 실행: Splash 애니메이션이 진행되며 Supabase 세션을 확인합니다.
- 세션 판별: 기존 세션이 유효하면 토큰을 갱신하거나 메인 탭으로 이동하고, 없으면 AuthCoordinator가 표시됩니다.
- 로그인/회원가입: 이메일 또는 소셜 로그인으로 인증을 진행합니다. 회원가입 성공 시 사용자 정보가
UserEntity로 공유됩니다. - 홈 탭: 영화 섹션을 스크롤로 탐색하고, 영화 선택 시 상세 화면으로 이동합니다.
- 상세 & 예매: 추가 정보를 확인한 뒤 예매 버튼을 통해 극장/시간/인원 선택 화면으로 이동합니다.
- 예매 완료: 예매 정보를 저장하고 완료 알림을 확인합니다. 예매 내역은 BookingList에서 확인합니다.
- 마이 페이지: 계정 정보, 로그인 타입을 확인하고 필요 시 로그아웃합니다.
- SplashFeature: 세션 점검, 페이드 아웃 애니메이션, 로그인 여부 판단.
- AuthCoordinator: 로그인/회원가입 플로우 관리, 소셜 인증 후 메인 탭 전환.
- MainTabFeature: 홈, 검색, 예매 내역, 마이 페이지 탭을 관리하고 TCA 스코프를 분배합니다.
- MovieListFeature: 영화 목록 섹션과 오류 처리, 영화 선택 액션을 담당합니다.
- MovieDetailFeature: 영화 상세 정보, 장르, 줄거리, 별점 표시 및 예매 화면 라우팅을 담당합니다.
- MovieBookFeature: 극장/상영 시간 불러오기, 인원 수 조절, 총액 계산, 예매 완료 Alert를 제공합니다.
- BookingListFeature: 저장된 예매 목록을 표시하고 삭제 요청을 처리합니다.
- MyPageFeature: 사용자 프로필, 로그인 제공자, 로그아웃 확인 팝업을 제공합니다.
- UI 레이어: SwiftUI, TCA(Perception 지원)로 화면 구성 및 상태 관리.
- 의존성 주입 및 상태 공유: TCA
Dependencies, WeaveDI,@Shared스토리지 조합. - 백엔드 & 인증: Supabase Client, PKCE 기반 OAuth, 커스텀 URL 스킴
movieBooking://login-callback/. - 네트워크 계층: URLSession, 커스텀
TargetType/NetworkProvider, LoggerEventMonitor. - 데이터 계층: Actor 기반 Repository, DTO ↔ Domain 매퍼, UserDefaults 기반 Local DataSource.
- 디자인 시스템: Pretendard 가변 폰트, 컬러 토큰, 카드·버튼 등 공통 UI 컴포넌트.
- 테스트: swift-testing(
@Test) 기반 네트워크, 데이터 매퍼, 세션 로직 단위 테스트.
TCA Feature → Domain UseCase → Data Repository → DataSource 구조로 레이어를 분리했습니다. 각 Feature는 Reducer 단위로 작성되며, UseCase와 Repository는 Dependencies 및 WeaveDI를 통해 주입됩니다.
MovieBooking/
├─ App/ # 앱 진입점, AppReducer, DI 부트스트랩
├─ Feature/ # 기능별 TCA Reducer & View (Auth, MovieList 등)
├─ Domain/ # Entity, UseCase, Repository 프로토콜
├─ Data/ # Repository 구현, DataSource, DTO/Request 정의
├─ NetworkService/ # HTTP Core, Provider, Error, 로깅
├─ DesignSystem/ # 색상·폰트·공통 컴포넌트
├─ Resources/ # Info.plist, Assets, FontAsset
├─ Utill/ # Utility, Validation, Navigation 확장
├─ MovieBookingTests/ / MovieBookingUITests/
└─ Config/ # Dev/Release xcconfig (Supabase Key, URL)
- Feature Reducer가 액션을 받아 도메인 UseCase를 호출합니다.
- UseCase는 의존성 주입으로 전달받은 Repository에 작업을 위임합니다.
- Repository는 DataSource를 통해 네트워크 또는 로컬(UserDefaults)에서 데이터를 읽고 씁니다.
- DataSource에서 받은 DTO를 Domain Entity로 변환해 Feature 상태에 반영합니다.
- 필요 시 Repository는 결과를 캐시해 검색이나 상세 조회 속도를 높입니다.
- Splash 단계에서 Supabase 세션 유무를 먼저 확인하고, 만료 임박 시
refreshSession을 호출합니다. - 소셜 로그인은 Supabase OAuth Provider(애플·구글·카카오)를 사용하며, Kakao 인증을 위해 Info.plist에 URL 스킴을 등록했습니다.
- 로그인 성공 시
UserEntity를@Shared(.inMemory)로 저장해 탭 간 상태를 공유합니다.
- 모든 API 요청은
NetworkProvider를 통해 이루어지며,TargetType프로토콜로 HTTP Method, Path, Parameters를 정의합니다. - LoggerEventMonitor가 요청/응답 로깅을 담당하고,
NetworkError로 에러 유형을 명확하게 분류합니다. - TMDB 영화 데이터는
APIConfiguration에서 baseURL과 API Key를 관리하며, JSON Key는convertFromSnakeCase전략으로 디코딩합니다.
- Pretendard Variable 폰트를 번들에 포함해 Weight/Size 조합을 세밀하게 조정합니다.
DesignSystem/Color모듈에서 색상 토큰을 정의하고, 재사용 가능한 카드·버튼 컴포넌트를 제공합니다.@SharedStorage로 저장된 테마나 사용자 정보에 따라 UI 요소를 업데이트할 수 있도록 설계했습니다.
MovieBookingTests/NetworkTests는 실제 REST Endpoint를 대상으로 HTTP Method, Parameter Encoding, 에러 핸들링을 검증합니다.MovieBookingTests/DataSourceTests는 TMDB 응답을 Mocking하여 DTO ↔ Domain 변환을 확인합니다.MovieBookingTests/SessionTest는 Supabase 세션 Mapper와 만료 처리 로직을 테스트합니다.- Feature Reducer는 TCA의
TestStore를 사용해 상태 전이 검증을 확장할 수 있도록 설계되어 있습니다.
- 저장소를 클론합니다.
git clone <repo-url> cd MovieBooking
MovieBooking.xcodeproj를 Xcode 16 이상에서 엽니다. (swift-testing 사용을 위해 16 버전 이상 권장)- 스킴
MovieBooking을 선택하고 iOS 16.6 이상 시뮬레이터에서 실행합니다.
- Supabase 세션은
SplashFeature에서 초기 확인 후 토큰 만료 여부에 따라refreshSession을 호출합니다. - 영화 목록은
withThrowingTaskGroup으로 병렬 호출하여 로딩 시간을 줄였으며, 실패 시AlertState로 재시도 버튼을 제공합니다. - 예매 흐름은 로컬
BookingRepository(UserDefaults 기반)로 구현되어 실제 결제 없이 플로우만 시뮬레이션합니다. @Shared프로퍼티 래퍼를 통해 로그인 정보(UserEntity)를 Feature 간에 공유합니다.- DesignSystem 모듈은 색상·폰트 토큰과 공용 카드/버튼 컴포넌트를 포함합니다.