Skip to content

[Feature/#3] BaseViewModel 구현#6

Merged
l5x5l merged 4 commits intodevelopfrom
feature/#2-base_view_model
Jun 22, 2025
Merged

[Feature/#3] BaseViewModel 구현#6
l5x5l merged 4 commits intodevelopfrom
feature/#2-base_view_model

Conversation

@l5x5l
Copy link
Copy Markdown
Contributor

@l5x5l l5x5l commented Jun 22, 2025

[ PR Content ]

앱 내 전체적으로 사용될 ViewModel의 기반인 MviViewModel 클래스를 구현합니다

Related issue

Screenshot 📸

  • N/A

Work Description

  • MviViewModel 구현
  • MviViewModel 관련 unitTest 작성

To Reviewers 📢

  • BaseViewModel 네이밍보다는 Mvi에 대한 기반 ViewModel이라는 뜻에서 MviViewModel이라고 명칭했습니다
  • 간단한 사용법은 MviViewModelTest.kt 코드 내 존재하는 SampleMviViewModel을 참고해주시면 될 것 같습니다
  • kotlin-parcelize의 경우, savedStateHandle 사용을 위해 추가했습니다
  • 추가적인 궁금증 혹은 이상한 부분이 있다면 코멘트 부탁드립니다!

Summary by CodeRabbit

  • New Features
    • MVI(Model-View-Intent) 아키텍처 지원을 위한 기본 인터페이스(MviIntent, MviSideEffect, MviState) 및 추상 ViewModel(MviViewModel) 추가
  • Chores
    • Kotlin Parcelize 플러그인 및 관련 테스트 라이브러리(Orbit Test, Kotlin Coroutines Test) 의존성 추가 및 설정
  • Tests
    • MVI ViewModel 동작 검증을 위한 테스트(MviViewModelTest) 추가

@l5x5l l5x5l requested a review from wjdrjs00 June 22, 2025 05:00
@l5x5l l5x5l added the ✨ Feature 새로운 기능 구현 label Jun 22, 2025
@l5x5l l5x5l linked an issue Jun 22, 2025 that may be closed by this pull request
1 task
@l5x5l l5x5l added ⚙ Init 개발 환경 세팅 세환 labels Jun 22, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jun 22, 2025

Walkthrough

MVI 아키텍처를 위한 공통 ViewModel 기반 클래스와 관련 인터페이스(MviState, MviSideEffect, MviIntent)가 도입되었습니다. Kotlin Parcelize 플러그인 및 테스트 관련 라이브러리들이 빌드 설정에 추가되었으며, 새로 도입된 MviViewModel의 동작을 검증하는 테스트 코드가 작성되었습니다.

Changes

파일/경로 그룹 변경 요약
build.gradle.kts, gradle/libs.versions.toml, presentation/build.gradle.kts Kotlin Parcelize 플러그인 및 코루틴/Orbit 테스트 라이브러리 추가
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviIntent.kt MviIntent 마커 인터페이스 추가
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviSideEffect.kt MviSideEffect 마커 인터페이스 추가
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviState.kt Parcelable을 상속하는 MviState 마커 인터페이스 추가
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt 추상 클래스 MviViewModel 추가 (MVI 패턴용 BaseViewModel)
presentation/src/test/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModelTest.kt MviViewModel 동작 검증을 위한 테스트 코드 추가

Sequence Diagram(s)

sequenceDiagram
    participant View as View
    participant VM as MviViewModel
    participant Orbit as Orbit Container

    View->>VM: sendIntent(intent)
    activate VM
    VM->>VM: reduceState(intent, currentState)
    alt 상태 변화 발생 시
        VM->>Orbit: intent { reduce { newState } }
        Orbit-->>VM: stateFlow 업데이트
    end
    deactivate VM
    VM-->>View: stateFlow, sideEffectFlow
Loading

Assessment against linked issues

Objective (이슈 번호) Addressed Explanation
앱 내 기본적으로 사용될 BaseViewModel 추상 클래스 구현 (#3)
ViewModel 보일러플레이트 감소, 일관된 형식 제공, 향후 확장성 고려 (#3)

Assessment against linked issues: Out-of-scope changes

(해당 변경사항에서 범위를 벗어난 기능적 코드 변경은 발견되지 않았습니다.)

Poem

🐰
MVI의 길 위에
토끼가 뛰노네
상태와 의도, 부드럽게 이어
사이드 이펙트도 살짝 더해
테스트까지 빈틈없이
BaseViewModel이
우리 앱을 빛내주네!
🌱✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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.
    • @coderabbitai modularize this function.
  • 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.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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 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 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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.

coderabbitai bot added a commit that referenced this pull request Jun 22, 2025
Docstrings generation was requested by @l5x5l.

* #6 (comment)

The following files were modified:

* `presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt`
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jun 22, 2025

Note

Generated docstrings for this pull request at #7

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: 0

🧹 Nitpick comments (5)
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviState.kt (1)

5-5: ✅ 상태 마커 인터페이스 정의 적절함

MviStateParcelable을 상속해 컴포넌트 간 안전하게 전달 가능한 상태를 보장합니다.
구현체에 @Parcelize 사용을 권장합니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviIntent.kt (1)

3-3: ✅ Intent 마커 인터페이스 정의 적절

MVI 아키텍처에서 Intent 분리를 위한 빈 인터페이스입니다.
공개 API이므로 KDoc 주석 추가를 권장합니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviSideEffect.kt (1)

3-3: ✅ SideEffect 마커 인터페이스 정의 적절

사이드 이펙트 구분을 위해 간결하게 설계되었습니다.
공개 API이므로 KDoc 주석 추가를 권장합니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt (1)

25-28: 추상 메서드 설계가 적절합니다.

reduceState 메서드의 시그니처가 명확하고, nullable 반환 타입으로 상태 변경이 없는 경우를 처리할 수 있어 좋습니다.

메서드에 KDoc 주석을 추가하여 사용법을 명확히 하는 것을 고려해보세요:

+    /**
+     * Intent를 처리하여 새로운 상태를 반환합니다.
+     * @param intent 처리할 인텐트
+     * @param state 현재 상태
+     * @return 새로운 상태 (변경이 없는 경우 null 반환 가능)
+     */
     protected abstract suspend fun SimpleSyntax<STATE, SIDE_EFFECT>.reduceState(
presentation/src/test/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModelTest.kt (1)

12-12: 실험적 API 사용에 대한 고려사항

@ExperimentalCoroutinesApi 사용이 현재는 적절하지만, 향후 안정적인 API로 마이그레이션할 계획을 고려해보세요.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 564017c and d28ae74.

📒 Files selected for processing (8)
  • build.gradle.kts (1 hunks)
  • gradle/libs.versions.toml (3 hunks)
  • presentation/build.gradle.kts (2 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviIntent.kt (1 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviSideEffect.kt (1 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviState.kt (1 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt (1 hunks)
  • presentation/src/test/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModelTest.kt (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (15)
gradle/libs.versions.toml (3)

98-98: ✅ Orbit 테스트 라이브러리 추가 적절

orbit-test 의존성 추가로 ViewModel 유닛테스트 지원이 강화됩니다.


114-114: ✅ 코루틴 테스트 라이브러리 추가 적절

kotlin-coroutines-test를 통해 코루틴 기반 테스트 안정성을 확보합니다.


176-176: ✅ Parcelize 플러그인 카탈로그 등록

버전 카탈로그에 kotlin-parcelize를 추가해 모듈별로 적용이 가능해졌습니다.

build.gradle.kts (1)

9-9: ✅ Parcelize 플러그인 등록 완료

루트 build.gradle.ktskotlin-parcelize 플러그인을 선언했습니다.
presentation 모듈에서 실제로 apply 되었는지 확인해 주세요.

presentation/build.gradle.kts (2)

4-4: Parcelize 플러그인 추가가 적절합니다.

MVI 아키텍처에서 상태 클래스의 Parcelable 지원을 위한 kotlin.parcelize 플러그인 추가가 올바릅니다.


17-19: 테스트 의존성 추가가 적절합니다.

새로운 MviViewModel의 테스트를 위한 JUnit, Kotlin 코루틴 테스트, Orbit 테스트 라이브러리 추가가 올바릅니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt (4)

14-18: MviViewModel 클래스 설계가 훌륭합니다.

제네릭 타입 제약과 Orbit ContainerHost 통합이 올바르게 구현되었습니다. SavedStateHandle을 통한 상태 지속성 지원도 적절합니다.


20-21: 상태 및 사이드 이펙트 플로우 노출이 적절합니다.

StateFlow와 Flow의 읽기 전용 노출이 캡슐화 원칙에 맞게 구현되었습니다.


23-23: 사이드 이펙트 헬퍼 메서드가 유용합니다.

SimpleSyntax 확장 함수로 제공되는 sendSideEffect 메서드가 코드 가독성을 향상시킵니다.


30-37: sendIntent 메서드 구현이 올바릅니다.

Orbit의 intent 구문을 적절히 사용하여 인텐트 처리와 상태 업데이트를 구현했습니다. null 체크를 통한 선택적 상태 업데이트도 효율적입니다.

presentation/src/test/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModelTest.kt (5)

12-19: 테스트 설정이 적절합니다.

@ExperimentalCoroutinesApi 사용과 SampleMviViewModel 초기화가 올바르게 구성되었습니다.


21-34: 상태 순차 업데이트 테스트가 훌륭합니다.

인텐트 처리 순서에 따른 상태 변경을 정확히 검증하는 테스트입니다. Orbit의 test 유틸리티 사용법도 적절합니다.


36-52: 상태와 사이드 이펙트 통합 테스트가 포괄적입니다.

Clear 인텐트에서 사이드 이펙트 발생과 상태 초기화를 함께 테스트하여 MVI 패턴의 완전한 흐름을 검증합니다.


55-74: 샘플 구현이 우수한 참고 자료입니다.

SampleMviViewModel의 reduceState 구현이 다양한 인텐트 타입 처리와 사이드 이펙트 발생을 잘 보여줍니다. 실제 사용법을 이해하는 데 도움이 됩니다.


76-91: 테스트 데이터 클래스들이 적절합니다.

@parcelize 애노테이션을 사용한 SampleState와 sealed class로 구현된 SampleSideEffect, SampleIntent가 MVI 패턴을 올바르게 따릅니다.

Copy link
Copy Markdown
Member

@wjdrjs00 wjdrjs00 left a comment

Choose a reason for hiding this comment

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

확실히 테스트 코드가 있으니 이해하기 편하네요 👍🏻
리뷰는 단순 질문이라 바로 어푸 완료! 고생하셨슴다~!

@l5x5l l5x5l self-assigned this Jun 22, 2025
@l5x5l l5x5l merged commit 08fc652 into develop Jun 22, 2025
2 checks passed
@wjdrjs00 wjdrjs00 deleted the feature/#2-base_view_model branch July 6, 2025 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능 구현 ⚙ Init 개발 환경 세팅 세환

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] BaseViewModel 구현

2 participants