Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
0d10000
[추가] 숨 버전2를 위한 Pretandard 타이포그래피 추가
hyeonsik971029 Sep 8, 2025
e42cf0c
[추가] 기존 스타일과 v2 스타일을 분리
hyeonsik971029 Sep 8, 2025
3210c42
[변경] 기존 타이포그래피와 분기 처리
hyeonsik971029 Sep 8, 2025
f42dd64
[추가] 숨 버전2를 위한 색상 추가
hyeonsik971029 Sep 8, 2025
097aa7d
[추가] 숨 버전2를 위한 아이콘 추가
hyeonsik971029 Sep 8, 2025
07cf054
[추가] 숨 버전2를 위한 이미지 및 로고 추가
hyeonsik971029 Sep 10, 2025
7a86f51
[변경] 기존 로고 초기화 방식 변경
hyeonsik971029 Sep 10, 2025
e325f64
[변경] v2 업데이트에 따른 이미지 초기화 방식 분기 처리
hyeonsik971029 Sep 10, 2025
a794dd3
[변경] 숨 버전2 업데이트를 위한 Dialog 업데이트
hyeonsik971029 Sep 10, 2025
9a54f96
[변경] 숨 버전2를 위한 LaunchScreen 업데이트
hyeonsik971029 Sep 10, 2025
a8bce8a
[변경] SwiftLint 적용
hyeonsik971029 Sep 10, 2025
9d3fa2f
[변경] 숨 버전2를 위한 SOMButton 업데이트
hyeonsik971029 Sep 11, 2025
9573c75
[추가] 온보딩 화면을 위한 이미지 추가
hyeonsik971029 Sep 11, 2025
6fc7950
[변경] 숨 버전2를 위한 온보딩 화면 업데이트
hyeonsik971029 Sep 11, 2025
2d45fdd
[추가] 온보딩 화면에서 팝업 표시 중복 삭제
hyeonsik971029 Sep 11, 2025
87f3bc0
[변경] SOMButton highlighted 색상 변경
hyeonsik971029 Sep 11, 2025
5916c72
[변경] 숨 버전2를 위한 회원가입(이용약관) 업데이트
hyeonsik971029 Sep 11, 2025
92f2d62
[추가] MARK 주석 공백 추가
hyeonsik971029 Sep 11, 2025
e54a5c4
[변경] 숨 버전2를 위한 SOMNavigationBar 업데이트
hyeonsik971029 Sep 11, 2025
603a50a
[변경] 숨 버전2를 위한 회원가입(닉네임) 업데이트
hyeonsik971029 Sep 11, 2025
cdd273f
[변경] SOMButton 업데이트
hyeonsik971029 Sep 12, 2025
1bb52c0
[추가] 숨 버전2를 위한 프로필 이미지 추가
hyeonsik971029 Sep 12, 2025
4f1fd61
[변경] 숨 버전2를 위한 프로필 설정 화면 업데이트
hyeonsik971029 Sep 12, 2025
ceec9d7
[추가] 팝업을 위한 SwiftEntryKit 추가
hyeonsik971029 Sep 12, 2025
e53288e
[추가] 로딩 뷰를 위한 lottie 및 json 추가
hyeonsik971029 Sep 12, 2025
2006b8a
[변경] 오타 수정
hyeonsik971029 Sep 12, 2025
2bea0eb
[추가] LaunchScreen 딜레이 추가
hyeonsik971029 Sep 12, 2025
b031ca1
[추가] 온보딩 완료 화면을 위한 이미지 추가
hyeonsik971029 Sep 12, 2025
2f6f4b5
[추가] 숨 버전2를 위한 회원가입 완료 화면 추가
hyeonsik971029 Sep 12, 2025
ecad252
[추가] 계정 이관 코드 화면을 위한 아이콘 추가
hyeonsik971029 Sep 12, 2025
01af17c
[변경] 숨 버전2를 위한 계정 이관 코드 입력 화면 업데이트
hyeonsik971029 Sep 12, 2025
8478b99
[변경] 오타 수정
hyeonsik971029 Sep 12, 2025
87a5530
[추가] 계정 이관 코드 입력 실패 팝업 추가
hyeonsik971029 Sep 12, 2025
16f14cc
[변경] 개발 서버 endpoint 변경
hyeonsik971029 Sep 12, 2025
ef1ad64
[변경] RxSwift 병합 오퍼레이터 변경
hyeonsik971029 Sep 12, 2025
44801da
[변경] 앱 아이콘 변경
hyeonsik971029 Sep 12, 2025
cdb5a4e
[변경] 온보딩 로직 변경
hyeonsik971029 Sep 13, 2025
18c2d52
[변경] 이용약관 선택 시 애니메이션 삭제
hyeonsik971029 Sep 13, 2025
891b65b
[추가] 프로필 이미지 업로드 화면 에러 핸들링 추가
hyeonsik971029 Sep 14, 2025
9fb61dc
[수정] 온보딩 화면 및 로직 수정
hyeonsik971029 Sep 14, 2025
f19dabc
[변경] 폰트 폴더 위치 변경
hyeonsik971029 Sep 15, 2025
7afbbf1
[수정] SwiftLint 룰 적용
hyeonsik971029 Sep 16, 2025
62e1f95
[추가] 온보딩/회원가입/알림 DTO/Model 추가
hyeonsik971029 Sep 16, 2025
fbde5da
[변경] Managers 폴더 변경
hyeonsik971029 Sep 16, 2025
ee918cc
[변경] 숨 버전2를 위한 Request 변경
hyeonsik971029 Sep 19, 2025
2fbcb4f
[변경] 숨 버전2를 위한 모델 변경
hyeonsik971029 Sep 19, 2025
a8db104
[추가] 의존성 주입 컨테이너 추가
hyeonsik971029 Sep 19, 2025
4efa74e
[변경] 숨 버전2를 위한 매니저 변경
hyeonsik971029 Sep 19, 2025
eb6a901
[추가] 클린 아키텍처 적용
hyeonsik971029 Sep 19, 2025
e087fa4
[변경] 숨 버전2를 위한 온보딩/회원가입 업데이트
hyeonsik971029 Sep 19, 2025
6181efc
[추가] 파이어베이스 콘솔 로그 출력 감소
hyeonsik971029 Sep 19, 2025
7a11d7f
[변경] App 및 Base 업데이트
hyeonsik971029 Sep 19, 2025
25df7a2
[변경] 로딩 뷰 크기 변경
hyeonsik971029 Sep 19, 2025
9e7c844
[변경] 주석 뎁스 변경
hyeonsik971029 Sep 19, 2025
ecf35f0
[변경] xcode 계정 변경
hyeonsik971029 Sep 19, 2025
5b6d38d
[변경] 네비게이션 뒤로가기 제스처 등록 위치 변경
hyeonsik971029 Sep 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions SOOUM/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ def pods
pod 'Then', '~> 3.0.0'
pod 'Kingfisher', '~> 7.10.0'
pod 'YPImagePicker', '~> 5.2.2'
pod 'SwiftEntryKit', '~> 2.0.0'

pod 'CocoaLumberjack/Swift', '~> 3.7.2'

pod 'lottie-ios'
end

target 'SOOUM-Dev' do
Expand Down
10 changes: 9 additions & 1 deletion SOOUM/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ PODS:
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- Kingfisher (7.10.2)
- lottie-ios (4.5.1)
- nanopb (2.30910.0):
- nanopb/decode (= 2.30910.0)
- nanopb/encode (= 2.30910.0)
Expand All @@ -153,6 +154,7 @@ PODS:
- RxSwift (6.8.0)
- SnapKit (5.7.1)
- SteviaLayout (5.1.2)
- SwiftEntryKit (2.0.0)
- SwiftLint (0.56.2)
- Then (3.0.0)
- WeakMapTable (1.2.0)
Expand All @@ -168,12 +170,14 @@ DEPENDENCIES:
- Firebase/Crashlytics (~> 10.22.0)
- Firebase/Messaging (~> 10.22.0)
- Kingfisher (~> 7.10.0)
- lottie-ios
- ReactorKit (~> 3.2.0)
- RxCocoa (~> 6.8.0)
- RxGesture (~> 4.0.4)
- RxKeyboard (~> 2.0.0)
- RxSwift (~> 6.8.0)
- SnapKit (~> 5.7.1)
- SwiftEntryKit (~> 2.0.0)
- SwiftLint (~> 0.56.2)
- Then (~> 3.0.0)
- YPImagePicker (~> 5.2.2)
Expand All @@ -196,6 +200,7 @@ SPEC REPOS:
- GoogleDataTransport
- GoogleUtilities
- Kingfisher
- lottie-ios
- nanopb
- PromisesObjC
- PromisesSwift
Expand All @@ -208,6 +213,7 @@ SPEC REPOS:
- RxSwift
- SnapKit
- SteviaLayout
- SwiftEntryKit
- SwiftLint
- Then
- WeakMapTable
Expand All @@ -230,6 +236,7 @@ SPEC CHECKSUMS:
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
Kingfisher: 99edc495d3b7607e6425f0d6f6847b2abd6d716d
lottie-ios: 248b380fa1b97d18e792c37d90da7ab2aa0d6562
nanopb: 438bc412db1928dac798aa6fd75726007be04262
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
Expand All @@ -242,11 +249,12 @@ SPEC CHECKSUMS:
RxSwift: 4e28be97cbcfeee614af26d83415febbf2bf6f45
SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
SteviaLayout: 05424e528d643657d39ce72c786e4adf13cfc5f2
SwiftEntryKit: 61b5fa36f34a97dd8013e48a7345bc4c4720be9a
SwiftLint: bd7cfb914762ab5f0cbb632964849571db075706
Then: 844265ae87834bbe1147d91d5d41a404da2ec27d
WeakMapTable: 05c694ce8439a7a9ebabb56187287a63c57673d6
YPImagePicker: afc81b3cffab05a6e7261c5daf80dc31b4e917b4

PODFILE CHECKSUM: 77a47a04877511a9af2378cb76d7e51ca6d46f27
PODFILE CHECKSUM: f064785e258ff9ada0428a59015c8a3fd3ccfe5d

COCOAPODS: 1.16.2
638 changes: 580 additions & 58 deletions SOOUM/SOOUM.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@
<CommandLineArguments>
<CommandLineArgument
argument = "-FIRDebugEnabled"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "-FIRDebugDisabled"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
Expand Down
37 changes: 18 additions & 19 deletions SOOUM/SOOUM/App/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import CocoaLumberjack
@main
class AppDelegate: UIResponder, UIApplicationDelegate {

let provider: ManagerProviderType = ManagerProviderContainer()
let appDIContainer: AppDIContainerable = AppDIContainer()

/// APNS 등록 완료 핸들러
var registerRemoteNotificationCompletion: ((Error?) -> Void)?
Expand All @@ -45,9 +45,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// Initalize token
self.initializeTokenWhenFirstLaunch()

// Set managers
self.provider.initialize()

FirebaseApp.configure()
// 파이어베이스 Meesaging 설정
Messaging.messaging().delegate = self
Expand Down Expand Up @@ -108,13 +105,13 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
let userInfo: [AnyHashable: Any] = response.notification.request.content.userInfo
if let infoDic = userInfo as? [String: Any] {
let info = NotificationInfo(infoDic)
// 계정 이관 성공 알림일 경우 (런치 화면 > 온보딩 화면), 아닐 경우 메인 홈 탭바 화면 전환
self.provider.pushManager.setupRootViewController(info, terminated: info.isTransfered)
}
// let userInfo: [AnyHashable: Any] = response.notification.request.content.userInfo
// if let infoDic = userInfo as? [String: Any] {
//
// let info = NotificationInfo(infoDic)
// // 계정 이관 성공 알림일 경우 (런치 화면 > 온보딩 화면), 아닐 경우 메인 홈 탭바 화면 전환
// self.provider.pushManager.setupRootViewController(info, terminated: info.isTransfered)
// }

completionHandler()
}
Expand Down Expand Up @@ -154,7 +151,8 @@ extension AppDelegate: MessagingDelegate {
apns: deviceToken,
fcm: Messaging.messaging().fcmToken
)
self.provider.networkManager.registerFCMToken(with: current, #function)
let provider = self.appDIContainer.rootContainer.resolve(ManagerProviderType.self)
provider.networkManager.registerFCMToken(with: current, #function)

self.registerRemoteNotificationCompletion?(nil)
}
Expand All @@ -165,7 +163,8 @@ extension AppDelegate: MessagingDelegate {
apns: messaging.apnsToken,
fcm: fcmToken
)
self.provider.networkManager.registerFCMToken(with: current, #function)
let provider = self.appDIContainer.rootContainer.resolve(ManagerProviderType.self)
provider.networkManager.registerFCMToken(with: current, #function)
}
}

Expand All @@ -190,12 +189,12 @@ extension AppDelegate {
}

private func setupOnboardingWhenTransferSuccessed(_ userInfo: [AnyHashable: Any]?) {
guard let infoDic = userInfo as? [String: Any] else { return }
// guard let infoDic = userInfo as? [String: Any] else { return }

let info = NotificationInfo(infoDic)
if info.isTransfered {
self.provider.pushManager.setupRootViewController(info, terminated: true)
}
// let info = NotificationInfo(infoDic)
// if info.isTransfered {
//
// self.provider.pushManager.setupRootViewController(info, terminated: true)
// }
}
}
24 changes: 12 additions & 12 deletions SOOUM/SOOUM/App/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
guard let windowScene = (scene as? UIWindowScene) else { return }
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }

window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
self.window = UIWindow(frame: windowScene.coordinateSpace.bounds)
self.window?.windowScene = windowScene

let viewController = LaunchScreenViewController()
viewController.reactor = LaunchScreenViewReactor(provider: appDelegate.provider)
viewController.reactor = LaunchScreenViewReactor(dependencies: appDelegate.appDIContainer)

window?.rootViewController = viewController
window?.backgroundColor = .white
window?.makeKeyAndVisible()
self.window?.rootViewController = viewController
self.window?.backgroundColor = .white
self.window?.makeKeyAndVisible()

/// 앱이 완전히 종료되었을 때 push notification에 대한 응답을 했을 때 실행할 코드 작성
if let response: UNNotificationResponse = connectionOptions.notificationResponse {
let userInfo: [AnyHashable: Any] = response.notification.request.content.userInfo
// let userInfo: [AnyHashable: Any] = response.notification.request.content.userInfo

if let infoDic: [String: Any] = userInfo as? [String: Any] {
let info = NotificationInfo(infoDic)
appDelegate.provider.pushManager.setupRootViewController(info, terminated: true)
}
// if let infoDic: [String: Any] = userInfo as? [String: Any] {
//
// let info = NotificationInfo(infoDic)
// appDelegate.provider.pushManager.setupRootViewController(info, terminated: true)
// }
}
}

Expand Down
14 changes: 10 additions & 4 deletions SOOUM/SOOUM/Base/BaseNavigationViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,13 @@ class BaseNavigationViewController: BaseViewController {
$0.trailing.equalTo(self.navigationBar.snp.trailing)
$0.height.equalTo(1.4)
}
// 로딩 뷰는 항상 최상단에 표시
self.view.bringSubviewToFront(self.loadingIndicatorView)
}

override func bind() {
super.bind()

self.navigationController?.delegate = self
self.navigationController?.interactivePopGestureRecognizer?.delegate = self

self.backButton.rx.tap
.subscribe(with: self) { object, _ in
object.navigationPop(
Expand Down Expand Up @@ -147,7 +146,14 @@ class BaseNavigationViewController: BaseViewController {

extension BaseNavigationViewController: UIGestureRecognizerDelegate {

public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return self.navigationPopGestureEnabled
}

func gestureRecognizer(
_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer
) -> Bool {
return self.navigationPopGestureEnabled
}
}
Expand Down
8 changes: 8 additions & 0 deletions SOOUM/SOOUM/Base/BaseViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ import RxSwift
import SnapKit
import Then

import Lottie


class BaseViewController: UIViewController {

var disposeBag = DisposeBag()

let activityIndicatorView = SOMActivityIndicatorView()
let loadingIndicatorView = SOMLoadingIndicatorView()

private(set) var isEndEditingWhenWillDisappear: Bool = true

Expand Down Expand Up @@ -58,6 +61,11 @@ class BaseViewController: UIViewController {
$0.centerX.equalTo(self.view.safeAreaLayoutGuide.snp.centerX)
$0.centerY.equalTo(self.view.safeAreaLayoutGuide.snp.centerY)
}

self.view.addSubview(self.loadingIndicatorView)
self.loadingIndicatorView.snp.makeConstraints {
$0.edges.equalToSuperview()
}

self.bind()

Expand Down
30 changes: 30 additions & 0 deletions SOOUM/SOOUM/Base/DIContainer/BaseAssembler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// BaseAssembler.swift
// SOOUM
//
// Created by 오현식 on 9/17/25.
//

import Foundation

/// 여러 의존성 등록 로직을 한 곳에 모아 관리하는 책임을 가집니다.
protocol BaseAssemblerable: AnyObject {
/// 추가 의존성을 `rootContainer`에 등록합니다.
/// - Parameter container: 의존성을 등록 혹은 반환합니다.
///
/// ```
/// DataSource: container.register(AnyDataSource.self) { _ in
/// AnyDataSourceImpl()
/// }
/// Repository: container.register(AnyRespository.self) { resolver in
/// AnyRespositoryImpl(resolver.resolve(AnyDataSource.self))
/// }
/// UseCase: container.register(AnyUseCase.self) { resolver in
/// AnyUseCaseImpl(resolver.resolve(AnyRespository.self))
/// }
/// Reactor: container.register(AnyReactor.self) { resolver in
/// AnyReactor(resolver.resolve(AnyUseCase.self))
/// }
/// ```
func assemble(container: BaseDIContainerable)
}
65 changes: 65 additions & 0 deletions SOOUM/SOOUM/Base/DIContainer/BaseDIContainer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// BaseDIContainer.swift
// SOOUM
//
// Created by 오현식 on 9/17/25.
//

import Foundation

/// DI 컨테이너가 수행해야 할 기능을 정의하는 프로토콜입니다.
/// `register`: 의존성을 등록합니다.
/// `resolve`: 등록된 의존성을 반환합니다.
protocol BaseDIContainerable: AnyObject {

/// 서비스 타입과 해당 서비스를 생성하는 클로저(factory)를 등록합니다.
/// - Parameters:
/// - type: 등록할 서비스의 프로토콜 타입입니다.
/// - factory: 서비스를 생성하는 클로저입니다. 이 클로저는 자기 자신(컨테이너)을 파라미터로 받아,
/// 다른 의존성을 해결(resolve)하는 데 사용할 수 있습니다.
func register<Service>(_ type: Service.Type, factory: @escaping (BaseDIContainerable) -> Service)

/// 등록된 서비스 타입의 인스턴스를 반환합니다.
/// - Parameter type: 해결(resolve)하려는 서비스의 프로토콜 타입입니다.
/// - Returns: 등록된 서비스의 인스턴스를 반환합니다. 만약 등록되지 않았다면 앱이 강제 종료됩니다. (개발 단계에서 의존성 설정 오류를 빠르게 파악하기 위함)
func resolve<Service>(_ type: Service.Type) -> Service
}

/// `BaseDIContainerable`의 실제 구현 클래스입니다.
final class BaseDIContainer: BaseDIContainerable {

// 부모 컨테이너에 대한 참조입니다.
private let parent: BaseDIContainerable?
// 등록된 서비스의 생성 클로저(factory)를 저장하는 딕셔너리입니다.
// 키는 서비스 타입의 이름(String), 값은 Any를 반환하는 클로저입니다.
private var factories: [String: (BaseDIContainerable) -> Any] = [:]

/// 초기화 시 부모 컨테이너를 주입받을 수 있습니다.
/// - Parameter parent: 부모 컨테이너. nil일 경우, 최상위 컨테이너가 됩니다.
init(_ parent: BaseDIContainerable? = nil) {
self.parent = parent
}

func register<Service>(_ type: Service.Type, factory: @escaping (BaseDIContainerable) -> Service) {
let key = String(describing: type)
self.factories[key] = factory
}

func resolve<Service>(_ type: Service.Type) -> Service {
let key = String(describing: type)
// 1. 현재 컨테이너에서 의존성 해결을 시도합니다.
if let factory = self.factories[key] {
// factory는 (DIContainerProtocol) -> Any 타입을 가지므로,
// 실제 서비스 타입(Service)으로 캐스팅하여 반환합니다.
// register 함수에서 타입을 보장하므로 강제 캐스팅(!)이 안전합니다.
return factory(self) as! Service
}
// 2. 현재 컨테이너에서 찾지 못했고, 부모가 있다면 부모에게 해결을 위임합니다.
if let parent = self.parent {
return parent.resolve(type)
}

// 해당 의존성이 등록되지 않은 경우, 개발자가 실수를 바로 인지할 수 있도록 fatalError를 발생시킵니다.
fatalError("Dependency for \(key) not registered.")
}
}
Loading
Loading