Skip to content

[Feat] Splash view UI 구현#36

Merged
choijungp merged 6 commits intodevelopfrom
feat/splash-view
Aug 5, 2025
Merged

[Feat] Splash view UI 구현#36
choijungp merged 6 commits intodevelopfrom
feat/splash-view

Conversation

@choijungp
Copy link
Copy Markdown
Contributor

@choijungp choijungp commented Aug 5, 2025

🌁 Background

Splash View에 Lottie를 띄워봤어요 ~~

📱 Screenshot

iPhone SE3 iPhone 13 mini iPhone 16 Pro
Simulator Screenshot - iPhone SE (3rd generation) - 2025-08-05 at 19 05 12 Simulator Screenshot - iPhone 13 mini - 2025-08-05 at 19 04 32 Simulator Screenshot - iPhone 16 Pro - 2025-08-05 at 19 03 09

Simulator Screen Recording - iPhone 13 mini - 2025-08-05 at 19 35 52

👩‍💻 Contents

  • Lottie 라이브러리 의존성 추가
  • logo image asset 추가
  • SplashView UI 수정

✅ Testing

스플래쉬 잘 뜨나 확인해봤슨

📝 Review Note

  • 첨에는 json 파일이 2.3MB 였거든요 ?? 그러다보니까 push가 안되는거에요 ..
  • 용량이 크다고 푸시 안되는 것은 첨 알았어요 ....
  • 그래서 이전 커밋으로 rebase 하려다가 약간 꼬여서 파일 교체 커밋이 2번 생김 .....

  • 애니메이션이 1번은 동작하고 다음 뷰로 넘어갔으면 좋겠는데 화면 전환 로직을 현재 SceneDelegate가 하고 있으니 ...
    이것을 어찌할까 고민이 됩니다 !!!

Summary by CodeRabbit

  • 신규 기능

    • 앱에 Lottie 기반의 애니메이션 스플래시 화면이 추가되었습니다.
    • 스플래시 화면 하단에 새로운 로고 이미지가 표시됩니다.
  • 스타일

    • 런치 스크린에서 기존 텍스트와 회색 배경이 제거되어 깔끔한 흰색 배경으로 변경되었습니다.
  • 기타

    • Lottie 외부 라이브러리가 프로젝트에 추가되었습니다.
    • 스플래시 애니메이션 완료 후 로그인 상태에 따라 화면 전환이 이루어집니다.

@choijungp choijungp requested a review from taipaise August 5, 2025 10:36
@choijungp choijungp self-assigned this Aug 5, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Aug 5, 2025

Walkthrough

런치 스크린에서 기존의 텍스트 뷰와 컨테이너가 제거되었고, Presentation 모듈에 Lottie 의존성이 추가되었습니다. 새로운 로고 이미지 에셋과 이를 불러오는 코드가 추가되었으며, SplashView는 정적 이미지 대신 Lottie 애니메이션과 로고 이미지로 대체되었습니다. SceneDelegate에서 SplashViewDelegate를 구현해 애니메이션 완료 후 로그인 상태에 따라 화면 전환 로직이 이동되었습니다. 관련 패키지 의존성 파일도 업데이트되었습니다.

Changes

Cohort / File(s) Change Summary
런치 스크린 뷰 제거
Projects/App/Resources/LaunchScreen.storyboard
컨테이너 뷰와 "Bitnagil" 텍스트, 관련 제약조건 모두 삭제. 메인 뷰만 남음.
Lottie 의존성 추가
Projects/Presentation/Project.swift, Tuist/Package.swift, Tuist/Package.resolved
Presentation 타겟과 패키지 매니페스트에 Lottie 외부 의존성 추가. 패키지 해시와 버전 명시.
로고 에셋 추가
Projects/Presentation/Resources/Images.xcassets/bitnagil_logo.imageset/Contents.json
새로운 bitnagil_logo 에셋(1x, 2x, 3x) 추가.
로고 그래픽 코드 추가
Projects/Presentation/Sources/Common/DesignSystem/BitnagilGraphic.swift
BitnagilGraphic enum에 logoGraphic(UIImage) 정적 프로퍼티 추가.
SplashView 리팩토링 및 애니메이션 적용
Projects/Presentation/Sources/Common/View/SplashView.swift
정적 이미지뷰 대신 LottieAnimationView로 splash.json 애니메이션 재생, 하단에 로고 이미지뷰 추가 및 레이아웃 변경. SplashViewDelegate 프로토콜과 delegate 속성 추가.
SceneDelegate 리팩토링
Projects/App/Sources/SceneDelegate.swift
SplashViewDelegate 구현 추가, splash 애니메이션 완료 후 로그인 토큰 재발급 및 화면 전환 로직 이동. 초기 rootViewController 설정 단순화.

Sequence Diagram(s)

sequenceDiagram
    participant App as App Launch
    participant SceneDelegate
    participant SplashView
    participant LottieAnimationView
    participant LogoImageView
    participant UserDataRepository
    participant TabBarView
    participant IntroView

    App->>SceneDelegate: scene(_:willConnectTo:options:)
    SceneDelegate->>SplashView: SplashView 생성 및 delegate 할당
    SceneDelegate->>SplashView: SplashView를 rootViewController로 설정
    SplashView->>LottieAnimationView: splash.json 로드 및 재생 시작
    SplashView->>LogoImageView: bitnagil_logo 이미지 로드 및 표시
    LottieAnimationView->>SplashView: 애니메이션 완료 콜백
    SplashView->>SceneDelegate: splashView(_:isCompletedAnimated:) 호출
    SceneDelegate->>UserDataRepository: 로그인 토큰 재발급 비동기 실행
    UserDataRepository-->>SceneDelegate: 로그인 상태 반환
    SceneDelegate->>TabBarView/IntroView: 로그인 여부에 따라 rootViewController 교체
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰
런치 스크린은 깔끔히 비워내고,
Lottie 애니메이션 춤을 추네!
로고는 빛나고, Splash는 새로워,
SceneDelegate도 똑똑하게 바뀌었지.
토끼가 뛰어올라 환호하네,
Bitnagil의 시작, 더욱 빛나리라!
✨🐇🎉

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/splash-view

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary or @coderabbitai 요약 to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
Projects/Presentation/Resources/Images.xcassets/bitnagil_logo.imageset/Contents.json (1)

1-23: 1x 해상도 이미지 포함은 앱 용량 증가 요인 — 실제 필요성 재검토 권장

iOS 디바이스는 레티나 스크린이 일반적이므로 1× 리소스는 거의 사용되지 않습니다. 필요 없다면 1× 파일을 제거해 앱 번들 크기를 줄일 수 있습니다.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0315ddb and c092eb4.

⛔ Files ignored due to path filters (3)
  • Projects/Presentation/Resources/Images.xcassets/bitnagil_logo.imageset/bitnagil_logo.png is excluded by !**/*.png
  • Projects/Presentation/Resources/Images.xcassets/bitnagil_logo.imageset/bitnagil_logo@2x.png is excluded by !**/*.png
  • Projects/Presentation/Resources/Images.xcassets/bitnagil_logo.imageset/bitnagil_logo@3x.png is excluded by !**/*.png
📒 Files selected for processing (7)
  • Projects/App/Resources/LaunchScreen.storyboard (0 hunks)
  • Projects/Presentation/Project.swift (1 hunks)
  • Projects/Presentation/Resources/Images.xcassets/bitnagil_logo.imageset/Contents.json (1 hunks)
  • Projects/Presentation/Sources/Common/DesignSystem/BitnagilGraphic.swift (1 hunks)
  • Projects/Presentation/Sources/Common/View/SplashView.swift (1 hunks)
  • Tuist/Package.resolved (1 hunks)
  • Tuist/Package.swift (1 hunks)
💤 Files with no reviewable changes (1)
  • Projects/App/Resources/LaunchScreen.storyboard
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#30
File: Projects/DataSource/Sources/NetworkService/Plugin/RefreshTokenPlugin.swift:42-43
Timestamp: 2025-07-30T03:56:18.617Z
Learning: choijungp는 현재 테스트 단계에서 RefreshTokenPlugin의 토큰 갱신 로직 디버깅을 위해 액세스 토큰과 리프레시 토큰의 실제 값을 로그에 기록하는 것을 선호함.
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Common/PresentationDependencyAssembler.swift:0-0
Timestamp: 2025-07-16T10:57:16.559Z
Learning: choijungp는 추후 CustomAlertView를 만들어서 에러 처리를 UI로 해결하도록 수정할 계획을 가지고 있음.
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Domain/Sources/UseCase/Onboarding/OnboardingUseCase.swift:0-0
Timestamp: 2025-07-16T10:58:30.858Z
Learning: choijungp는 OnboardingUseCase의 convertToDictionary 함수에서 에러 처리 개선을 추후 고민하고 반영할 계획을 가지고 있음.
🔇 Additional comments (9)
Tuist/Package.resolved (1)

30-38: Lottie 패키지 해시 고정은 좋으나 Package.swift와 버전 일치 여부 확인 필요

Package.resolved에는 4.5.2 해시가 고정되어 있으나, Package.swift에서는 from: "4.0.0"으로 범위가 넓게 잡혀 있습니다. 추후 tuist fetchswift package update 실행 시 새로운 마이너 버전으로 자동 상승할 수 있으므로 동일한 버전을 고정하거나, 의도적 범위인지 한 번 더 확인 부탁드립니다.

Tuist/Package.swift (1)

9-10: Lottie 의존성 추가 👍

Presentation 모듈에서 사용할 Lottie를 선언해주셔서 정상 빌드가 가능해졌습니다. 별다른 문제 없어 보입니다.

Projects/Presentation/Project.swift (1)

15-18: Presentation 타깃에 Lottie 연결 완료 — 모듈 간 중복 의존성 여부만 확인해주세요

현재 Presentation 모듈만 Lottie를 링크하고 있습니다. 다른 모듈(예: Shared)에서도 Lottie를 직접 참조할 계획이 있다면, 중복 추가로 인한 링커 경고가 발생하지 않도록 dependency 구조를 한 번 더 점검해 주세요.

Projects/Presentation/Sources/Common/DesignSystem/BitnagilGraphic.swift (1)

18-18: 새 로고 리소스는 Optional UIImage이므로 사용 시 강제 언래핑 주의

logoGraphicUIImage? 타입으로 정의되어 있어 뷰에서 강제 언래핑하면 런타임 크래시가 발생할 수 있습니다. guard let 으로 안전하게 처리하거나, 실패 시 placeholder 이미지를 사용하도록 구현 여부를 확인해주세요.

Projects/Presentation/Sources/Common/View/SplashView.swift (5)

8-8: Lottie 의존성 추가 승인

Lottie 애니메이션 기능을 위한 import가 올바르게 추가되었습니다.


14-18: 레이아웃 상수 정의 잘 구현됨

Layout enum을 통해 매직넘버를 중앙화하고 의미있는 이름으로 상수를 정의한 것이 좋습니다.


20-21: 프로퍼티 선언 적절함

프라이빗 접근제어자와 명확한 네이밍으로 프로퍼티가 잘 선언되었습니다.


23-28: 애니메이션 재생 타이밍 고려 필요

현재 구현은 올바르지만, PR 목표에서 언급한 "애니메이션이 한 번 재생된 후 다음 뷰로 전환"하는 로직을 고려해보세요. 현재는 뷰가 로드되자마자 애니메이션이 시작됩니다.


42-57: 레이아웃 구성 잘 구현됨

SnapKit을 사용한 제약조건 설정이 명확하고 올바르게 구현되었습니다. 애니메이션 뷰와 로고 이미지의 배치가 적절합니다.

Comment on lines 30 to 40
private func configureAttribute() {
splashGraphicView.image = BitnagilGraphic.introGraphic
let presentationBundle = Bundle(for: SplashView.self)
guard let filePath = presentationBundle.path(forResource: "splash", ofType: "json")
else { return }
splashAnimationView = LottieAnimationView(filePath: filePath)
splashAnimationView.contentMode = .scaleAspectFit
splashAnimationView.loopMode = .playOnce

logoImage.image = BitnagilGraphic.logoGraphic
logoImage.contentMode = .scaleAspectFit
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

리소스 로딩 에러 처리 개선 필요

현재 구현에서 몇 가지 개선점이 있습니다:

  1. splash.json 파일을 찾지 못할 경우 silent failure가 발생합니다
  2. 에러 상황에 대한 적절한 처리나 로깅이 없습니다

다음과 같이 개선하는 것을 고려해보세요:

private func configureAttribute() {
    let presentationBundle = Bundle(for: SplashView.self)
    guard let filePath = presentationBundle.path(forResource: "splash", ofType: "json")
-   else { return }
+   else { 
+       print("Warning: splash.json file not found in bundle")
+       // fallback 처리 또는 기본 애니메이션 로직 추가
+       return 
+   }
    splashAnimationView = LottieAnimationView(filePath: filePath)
    splashAnimationView.contentMode = .scaleAspectFit
    splashAnimationView.loopMode = .playOnce
    
    logoImage.image = BitnagilGraphic.logoGraphic
    logoImage.contentMode = .scaleAspectFit
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private func configureAttribute() {
splashGraphicView.image = BitnagilGraphic.introGraphic
let presentationBundle = Bundle(for: SplashView.self)
guard let filePath = presentationBundle.path(forResource: "splash", ofType: "json")
else { return }
splashAnimationView = LottieAnimationView(filePath: filePath)
splashAnimationView.contentMode = .scaleAspectFit
splashAnimationView.loopMode = .playOnce
logoImage.image = BitnagilGraphic.logoGraphic
logoImage.contentMode = .scaleAspectFit
}
private func configureAttribute() {
let presentationBundle = Bundle(for: SplashView.self)
guard let filePath = presentationBundle.path(forResource: "splash", ofType: "json")
else {
print("Warning: splash.json file not found in bundle")
// fallback 처리 또는 기본 애니메이션 로직 추가
return
}
splashAnimationView = LottieAnimationView(filePath: filePath)
splashAnimationView.contentMode = .scaleAspectFit
splashAnimationView.loopMode = .playOnce
logoImage.image = BitnagilGraphic.logoGraphic
logoImage.contentMode = .scaleAspectFit
}
🤖 Prompt for AI Agents
In Projects/Presentation/Sources/Common/View/SplashView.swift around lines 30 to
40, the code silently fails if the splash.json resource is not found and lacks
error handling or logging. Modify the guard statement to handle the failure case
explicitly by logging an error message or providing fallback behavior to inform
about the missing resource, ensuring the app does not fail silently.

Copy link
Copy Markdown
Collaborator

@taipaise taipaise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

회의때 말씀해주신 것처럼 조이가 알잘딱하게 해결하실거라 믿어 의심치 않습니다!!!
오늘도 언제나처럼 고생하셨습니다~!!!

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
Projects/Presentation/Sources/Common/View/SplashView.swift (3)

38-48: 리소스 로딩 실패 시 에러 처리 개선 필요

splash.json 파일을 찾지 못할 경우 silent failure가 발생합니다. 디버깅과 사용자 경험을 위해 로깅이나 fallback 처리를 추가하는 것이 좋겠습니다.

다음과 같이 개선해보세요:

guard let filePath = presentationBundle.path(forResource: "splash", ofType: "json")
-else { return }
+else { 
+    print("Warning: splash.json 파일을 찾을 수 없습니다")
+    // fallback 처리 또는 기본 동작 추가
+    return 
+}

39-48: 리소스 로딩 에러 처리 개선 필요

이전 리뷰에서 지적된 splash.json 파일 로딩 실패에 대한 에러 처리가 여전히 부족합니다. Silent failure 대신 적절한 fallback 처리나 로깅이 필요합니다.

다음과 같이 개선하는 것을 고려해보세요:

private func configureAttribute() {
    let presentationBundle = Bundle(for: SplashView.self)
    guard let filePath = presentationBundle.path(forResource: "splash", ofType: "json")
-   else { return }
+   else { 
+       print("Warning: splash.json file not found in bundle")
+       // 기본 애니메이션 없이 로고만 표시하거나 fallback 처리
+       delegate?.splashView(self, isCompletedAnimated: true)
+       return 
+   }
    splashAnimationView = LottieAnimationView(filePath: filePath)
    splashAnimationView.contentMode = .scaleAspectFit
    splashAnimationView.loopMode = .playOnce

    logoImage.image = BitnagilGraphic.logoGraphic
    logoImage.contentMode = .scaleAspectFit
}

38-48: 리소스 로딩 에러 처리 개선 필요

이전 리뷰에서 지적된 것처럼 splash.json 파일을 찾지 못할 경우 silent failure가 발생합니다. 에러 상황에 대한 적절한 처리나 로깅이 없습니다.

다음과 같이 개선하는 것을 고려해보세요:

private func configureAttribute() {
    let presentationBundle = Bundle(for: SplashView.self)
    guard let filePath = presentationBundle.path(forResource: "splash", ofType: "json")
-   else { return }
+   else { 
+       print("Warning: splash.json file not found in bundle")
+       // 애니메이션 파일이 없을 경우 델리게이트에게 즉시 완료 알림
+       DispatchQueue.main.async { [weak self] in
+           guard let self else { return }
+           self.delegate?.splashView(self, isCompletedAnimated: true)
+       }
+       return 
+   }
    splashAnimationView = LottieAnimationView(filePath: filePath)
    splashAnimationView.contentMode = .scaleAspectFit
    splashAnimationView.loopMode = .playOnce
    
    logoImage.image = BitnagilGraphic.logoGraphic
    logoImage.contentMode = .scaleAspectFit
}
🧹 Nitpick comments (1)
Projects/App/Sources/SceneDelegate.swift (1)

50-68: 델리게이트 구현과 비동기 처리 검토

델리게이트 패턴 구현이 적절하며 @mainactor를 사용한 UI 업데이트도 올바릅니다. 다만 몇 가지 개선 사항을 고려해보세요:

  1. 의존성 해결 실패 시 치명적 오류 대신 더 우아한 처리 방법 고려
  2. 토큰 재발급 실패 시에 대한 에러 처리 부재
func splashView(_ sender: Presentation.SplashView, isCompletedAnimated: Bool) {
    guard isCompletedAnimated else { return }

    guard let userDataRepository = DIContainer.shared.resolve(type: UserDataRepositoryProtocol.self)
-   else { fatalError("userDataRepository 의존성이 등록되지 않았습니다.") }
+   else { 
+       print("Error: userDataRepository dependency not registered")
+       // 기본 IntroView로 이동
+       let introView = IntroView()
+       let navigationController = UINavigationController(rootViewController: introView)
+       window?.rootViewController = navigationController
+       return
+   }

    Task { @MainActor in
-       let isLogined = await userDataRepository.reissueToken()
+       do {
+           let isLogined = try await userDataRepository.reissueToken()
            if isLogined {
                window?.rootViewController = TabBarView()
            } else {
                let introView = IntroView()
                let navigationController = UINavigationController(rootViewController: introView)
                window?.rootViewController = navigationController
            }
+       } catch {
+           print("Token reissue failed: \(error)")
+           let introView = IntroView()
+           let navigationController = UINavigationController(rootViewController: introView)
+           window?.rootViewController = navigationController
+       }
    }
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c092eb4 and 87e0f44.

📒 Files selected for processing (2)
  • Projects/App/Sources/SceneDelegate.swift (2 hunks)
  • Projects/Presentation/Sources/Common/View/SplashView.swift (1 hunks)
👮 Files not reviewed due to content moderation or server errors (2)
  • Projects/App/Sources/SceneDelegate.swift
  • Projects/Presentation/Sources/Common/View/SplashView.swift
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: choijungp는 추후 customalertview를 만들어서 에러 처리를 ui로 해결하도록 수정할 계획을 가지고 있음....
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Common/PresentationDependencyAssembler.swift:0-0
Timestamp: 2025-07-16T10:57:16.559Z
Learning: choijungp는 추후 CustomAlertView를 만들어서 에러 처리를 UI로 해결하도록 수정할 계획을 가지고 있음.

Applied to files:

  • Projects/Presentation/Sources/Common/View/SplashView.swift
📚 Learning: choijungp는 onboardingusecase의 converttodictionary 함수에서 에러 처리 개선을 추후 고민하고 반영할 계획을 가지고 있음....
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Domain/Sources/UseCase/Onboarding/OnboardingUseCase.swift:0-0
Timestamp: 2025-07-16T10:58:30.858Z
Learning: choijungp는 OnboardingUseCase의 convertToDictionary 함수에서 에러 처리 개선을 추후 고민하고 반영할 계획을 가지고 있음.

Applied to files:

  • Projects/Presentation/Sources/Common/View/SplashView.swift
📚 Learning: onboardingrecommendedroutineview에서 viewwillappear에 registeronboarding 호출하는 것이 적절한 이유: 사용자가 이전 페이지에서 ...
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Presentation/Sources/Onboarding/View/OnboardingRecommendedRoutineView.swift:57-59
Timestamp: 2025-07-16T09:21:15.038Z
Learning: OnboardingRecommendedRoutineView에서 viewWillAppear에 registerOnboarding 호출하는 것이 적절한 이유: 사용자가 이전 페이지에서 온보딩 선택지를 변경한 후 돌아올 때 새로운 선택지로 다시 등록해야 하기 때문. 홈 뷰에서는 이 뷰로 돌아올 수 없어서 중복 호출 문제가 발생하지 않음.

Applied to files:

  • Projects/App/Sources/SceneDelegate.swift
🔇 Additional comments (20)
Projects/App/Sources/SceneDelegate.swift (7)

23-26: 스플래시 화면 우선 표시로 사용자 경험 개선

애니메이션 완료 후 로그인 상태를 확인하는 방식으로 변경되어 사용자에게 더 나은 시각적 경험을 제공합니다. 로직 분리도 명확해졌습니다.


50-68: 애니메이션 완료 기반 화면 전환 로직 잘 구현됨

SplashViewDelegate를 통해 애니메이션 완료 후 로그인 상태 확인 및 화면 전환을 처리하는 로직이 깔끔하게 구현되었습니다. @mainactor를 사용한 비동기 처리도 적절합니다.


39-47: 코드 포맷팅 개선

빈 씬 라이프사이클 메서드들의 간결한 포맷팅으로 가독성이 향상되었습니다.


23-26: 적절한 초기화 순서와 델리게이트 설정

SplashView를 즉시 루트 뷰 컨트롤러로 설정하고 델리게이트를 적절히 연결한 구현이 좋습니다. 애니메이션 완료 후 로그인 상태 확인으로 이어지는 플로우가 직관적입니다.


39-47: 라이프사이클 메서드 포맷팅 개선

빈 라이프사이클 메서드들을 한 줄로 정리한 것이 코드 가독성을 향상시킵니다.


23-26: 스플래시 뷰 초기화 및 델리게이트 설정이 적절합니다.

SplashView 인스턴스를 생성하고 델리게이트를 설정한 후 즉시 루트 뷰 컨트롤러로 설정하는 구조가 깔끔합니다. 애니메이션 완료 후 화면 전환 로직이 델리게이트 패턴으로 분리되어 관심사의 분리가 잘 이루어졌습니다.


39-48: 생명주기 메서드 정리가 깔끔합니다.

빈 생명주기 메서드들을 한 줄로 정리한 것이 코드 가독성을 높였습니다.

Projects/Presentation/Sources/Common/View/SplashView.swift (13)

8-14: 델리게이트 패턴을 통한 깔끔한 통신 구조

Lottie 라이브러리 도입과 SplashViewDelegate 프로토콜 정의가 적절하게 구현되었습니다. 애니메이션 완료 시점을 외부에 알리는 구조가 명확합니다.


18-26: 체계적인 레이아웃 상수 관리와 적절한 메모리 관리

Layout enum을 통한 상수 관리와 weak delegate 사용으로 코드 구조와 메모리 관리가 잘 구현되었습니다.


32-35: 애니메이션 실행과 콜백 처리 잘 구현됨

viewDidLoad에서 즉시 애니메이션을 재생하고 완료 시 델리게이트에 알리는 로직이 적절합니다. weak self 사용으로 메모리 누수도 방지했습니다.


50-65: 레이아웃 구성이 깔끔하고 직관적

SnapKit을 활용한 Auto Layout 구성이 적절하며, 애니메이션과 로고의 배치가 자연스럽습니다. Layout enum의 상수 활용도 일관성 있게 잘 구현되었습니다.


12-14: 델리게이트 프로토콜 설계 양호

SplashViewDelegate 프로토콜이 간결하고 명확하게 정의되었습니다. 애니메이션 완료 상태를 Boolean으로 전달하는 것이 적절합니다.


18-22: 레이아웃 상수 구조화

Layout enum을 통해 magic number를 제거하고 레이아웃 값들을 체계적으로 관리한 것이 좋습니다.


24-26: 프로퍼티 선언과 델리게이트 설정

Lottie 애니메이션 뷰와 로고 이미지 뷰, 델리게이트 프로퍼티가 적절히 선언되었습니다. weak 참조 사용으로 메모리 누수를 방지한 것도 좋습니다.


32-36: 애니메이션 실행과 완료 처리

애니메이션 실행과 완료 콜백 처리가 적절합니다. weak self 사용으로 순환 참조를 방지한 것도 좋습니다.


51-65: 레이아웃 구성 적절

SnapKit을 사용한 오토레이아웃 설정이 명확하고 적절합니다. 중앙 정렬과 spacing 설정이 잘 되어 있습니다.


12-14: 델리게이트 프로토콜 정의가 적절합니다.

SplashViewDelegate 프로토콜이 명확하게 정의되어 있고, 애니메이션 완료 상태를 전달하는 구조가 좋습니다.


18-22: 레이아웃 상수를 enum으로 관리하는 것이 좋습니다.

레이아웃 관련 상수들을 enum으로 그룹화하여 관리하는 방식이 깔끔하고 유지보수에 유리합니다.


32-36: 애니메이션 재생 및 완료 처리가 적절합니다.

Lottie 애니메이션을 재생하고 완료 시 델리게이트에게 알리는 구조가 잘 구현되어 있습니다. weak self를 사용한 메모리 관리도 적절합니다.


50-66: 레이아웃 구성이 잘 되어 있습니다.

SnapKit을 사용한 제약 조건 설정이 명확하고, 애니메이션 뷰와 로고 이미지의 배치가 적절합니다. 배경색을 흰색으로 설정한 것도 스플래시 화면에 적합합니다.

Comment on lines +50 to 68
extension SceneDelegate: SplashViewDelegate {
func splashView(_ sender: Presentation.SplashView, isCompletedAnimated: Bool) {
guard isCompletedAnimated else { return }

guard let userDataRepository = DIContainer.shared.resolve(type: UserDataRepositoryProtocol.self)
else { fatalError("userDataRepository 의존성이 등록되지 않았습니다.") }

Task { @MainActor in
let isLogined = await userDataRepository.reissueToken()
if isLogined {
window?.rootViewController = TabBarView()
} else {
let introView = IntroView()
let navigationController = UINavigationController(rootViewController: introView)
window?.rootViewController = navigationController
}
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

비동기 작업 처리가 적절하나 에러 핸들링 개선 필요

SplashViewDelegate 구현이 적절하고 @mainactor를 사용한 UI 업데이트도 올바릅니다. 하지만 reissueToken() 작업에서 발생할 수 있는 예외에 대한 처리가 없습니다.

다음과 같이 에러 핸들링을 추가하는 것을 고려해보세요:

Task { @MainActor in
-    let isLogined = await userDataRepository.reissueToken()
-    if isLogined {
-        window?.rootViewController = TabBarView()
-    } else {
-        let introView = IntroView()
-        let navigationController = UINavigationController(rootViewController: introView)
-        window?.rootViewController = navigationController
-    }
+    do {
+        let isLogined = await userDataRepository.reissueToken()
+        if isLogined {
+            window?.rootViewController = TabBarView()
+        } else {
+            let introView = IntroView()
+            let navigationController = UINavigationController(rootViewController: introView)
+            window?.rootViewController = navigationController
+        }
+    } catch {
+        // 토큰 재발급 실패 시 로그인 화면으로 이동
+        let introView = IntroView()
+        let navigationController = UINavigationController(rootViewController: introView)
+        window?.rootViewController = navigationController
+    }
}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In Projects/App/Sources/SceneDelegate.swift between lines 50 and 68, the async
call to userDataRepository.reissueToken() lacks error handling. Wrap the await
call in a do-catch block to catch and handle any thrown errors. In the catch
block, provide appropriate fallback UI logic or error logging to ensure the app
remains stable if reissueToken() fails.

@choijungp choijungp merged commit 7726a5a into develop Aug 5, 2025
2 checks passed
@choijungp choijungp deleted the feat/splash-view branch August 5, 2025 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants