Skip to content

약관동의 화면 구현#92

Merged
moondev03 merged 14 commits intodevelopfrom
feat/#89-약관동의-화면-구현
Apr 3, 2026

Hidden character warning

The head ref may contain hidden characters: "feat/#89-\uc57d\uad00\ub3d9\uc758-\ud654\uba74-\uad6c\ud604"
Merged

약관동의 화면 구현#92
moondev03 merged 14 commits intodevelopfrom
feat/#89-약관동의-화면-구현

Conversation

@moondev03
Copy link
Copy Markdown
Member

@moondev03 moondev03 commented Apr 2, 2026

📌 작업 내용

  • 로그인 플로우 내 약관 동의 화면을 추가하고 Login -> Terms -> Home 흐름으로 연결
  • 로그인/약관 화면 패키지 구조를 landing, terms, navigation 기준으로 재정리
  • 약관 상세 확인을 웹뷰와 약관 URL 연결용 BuildConfig 설정 추가
  • 약관 화면 구현에 필요한 디자인 시스템 컴포넌트(PrezelCheckbox, PrezelAccordion, PrezelTopAppBar)를 보강

🧩 관련 이슈


📸 스크린샷

Screen_recording_20260402_233753.webm

📢 논의하고 싶은 내용

  • 현재는 로그인 성공 후 약관 동의 화면으로 이동하도록 구성했습니다.
  • 약관 동의 이력의 영속 저장 여부와 재진입 시 스킵 정책은 후속 범위로 분리하겠습니다.

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 약관 동의 화면 추가: 약관/개인정보/마케팅 동의 체크, 상세 보기 모달(웹뷰) 및 동의 후 계속하기 제공
  • 개선 사항

    • 체크박스 터치 영역과 상단 앱바 인셋 처리 개선으로 조작성 향상
    • 로그인 흐름 및 네비게이션 정리 — 로그인에서 약관 화면으로 이동 경로 추가
    • 약관/개인정보 링크를 외부 URL로 열람할 수 있도록 구성 가능
  • 기타

    • 다수 UI 문자열 추가 및 버튼 레이블 현지화 반영

@moondev03 moondev03 self-assigned this Apr 2, 2026
@moondev03 moondev03 requested a review from HamBeomJoon as a code owner April 2, 2026 15:08
@moondev03 moondev03 added the ✨ feat 새로운 기능 추가 또는 기존 기능 확장 label Apr 2, 2026
@moondev03 moondev03 linked an issue Apr 2, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

로그인 흐름을 약관(terms) 화면으로 라우팅하도록 네비게이션·뷰모델·계약을 추가·변경했고, 약관 화면(및 상세 모달)과 관련된 UI/상태/이펙트를 새로 도입했습니다. 디자인시스템에서는 PrezelCheckbox 상호작용·세맨틱스 재구성과 PrezelTopAppBar insets 인자 추가 및 프리뷰 업데이트가 포함됩니다.

Changes

Cohort / File(s) Summary
디자인 시스템 컴포넌트
Prezel/core/designsystem/src/main/java/.../PrezelCheckbox.kt, Prezel/core/designsystem/src/main/java/.../TopAppBar.kt, Prezel/core/designsystem/src/main/java/.../PrezelAccordion.kt
PrezelCheckboxPrezelTouchArea로 래핑되어 클릭 처리와 세맨틱스 변경(이제 클릭에서 onCheckedChange 토글 호출), 시그니처에 extraTouchPadding: PaddingValues 추가, 아이콘/크기 추출 유틸화. PrezelTopAppBarwindowInsets: WindowInsets 파라미터 추가. PrezelAccordion 프리뷰에서 extraTouchPadding = PaddingValues() 전달.
로그인 네비게이션 엔트리 및 키
Prezel/feature/login/impl/.../navigation/LoginEntryBuilder.kt, Prezel/feature/login/impl/.../navigation/LoginTermsNavKey.kt
로그인 엔트리에서 navigateToTerms로 라우팅하도록 변경하고 LoginTermsNavKeyentry<LoginTermsNavKey> 추가하여 약관 화면 진입 경로를 등록.
로그인 화면 이동 및 리네이밍
Prezel/feature/login/impl/.../landing/LoginScreen.kt
LoginScreenlanding 패키지로 이동·수정: navigateToHomenavigateToTerms로 변경, animatedVisibilityScope 제거 및 로컬 scope 사용, UI 이펙트 핸들링 재배치.
뷰모델·계약 리팩토링(landing)
Prezel/feature/login/impl/.../landing/LoginViewModel.kt, .../landing/contract/LoginUiEffect.kt, .../landing/contract/LoginUiIntent.kt, .../landing/contract/LoginUiState.kt
뷰모델과 계약을 landing 패키지로 이동하고 가시성을 internal로 조정. 네비게이션 이펙트 이름을 NavigateToTerms로 변경하고 intent/이펙트 흐름 및 디버그 분기 로직 조정. LoginUiState가 landing에 새로 추가됨.
약관 화면(terms) 추가
Prezel/feature/login/impl/.../terms/TermsScreen.kt, .../terms/TermsViewModel.kt, .../terms/component/TermsDetailModal.kt
새로운 TermsScreen 컴포저블, Hilt 기반 TermsViewModel, 웹뷰 기반 TermsDetailModal 추가. 약관 체크박스/아코디언 UI, 상세 보기 모달, Continue 동작과 네비게이션 이펙트 구현 포함.
약관 계약 정의
Prezel/feature/login/impl/.../terms/contract/TermsUiEffect.kt, .../TermsUiIntent.kt, .../TermsUiState.kt
약관 흐름용 내부 sealed 계약 파일 추가(이펙트·인텐트·상태). 상태 모델에 필수·선택 체크 항목과 파생 속성(isRequiredChecked, isAllChecked) 정의.
모델 이동/정리
Prezel/feature/login/impl/src/main/java/.../model/LoginUiMessage.kt, Prezel/feature/login/impl/.../landing/model/LoginUiMessage.kt
기존 LoginUiMessage 제거 및 landing용 패키지에 동일 목적의 내부 enum 재생성(메시지 항목 재배치).
빌드 설정
Prezel/feature/login/impl/build.gradle.kts
모듈에서 buildConfig 생성 활성화 및 PRIVACY_POLICY_URL, TERMS_OF_SERVICE_URL BuildConfig 문자열 필드 추가(로컬 속성에서 로드).
문자열 리소스
Prezel/feature/login/impl/src/main/res/values/strings.xml
로그인/약관 관련 문자열 다수 추가(카카오 버튼 레이블, 약관 제목/레이블/요약/버튼/아이콘 설명 등) 및 기존 스낵바 확인 문자열 삭제.

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목 '약관동의 화면 구현'은 이 변경의 주요 목적을 명확하게 요약하며, 실제 코드 변경(약관 화면 구현, Terms 관련 컴포넌트 추가, 로그인 플로우 연결)과 일치합니다.
Description check ✅ Passed PR 설명이 템플릿의 주요 섹션(작업 내용, 관련 이슈, 스크린샷, 논의사항)을 포함하고 있으며, 변경사항과 향후 계획을 명확히 제시합니다.
Linked Issues check ✅ Passed PR이 이슈 #89의 요구사항(약관 동의 화면 및 모달 구현, 로그인 플로우 통합)을 완전히 충족합니다. TermsScreen, TermsViewModel, 약관 상세 모달 및 Login->Terms->Home 흐름 구현이 모두 포함되어 있습니다.
Out of Scope Changes check ✅ Passed PR의 모든 변경사항이 약관 동의 화면 구현(이슈 #89)과 이를 지원하는 디자인 시스템 개선에 직접 관련되어 있으며, 범위를 벗어난 변경사항은 없습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@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: 9

🧹 Nitpick comments (1)
Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsScreen.kt (1)

89-103: 미사용 변수 및 함수 네이밍 개선

  1. Line 103의 resources 변수가 선언되었지만 사용되지 않습니다. Line 121에서 resources.getString()을 사용하지만, 이는 stringResource()로 대체 가능합니다.

  2. TermsScreenScreen 함수명에 "Screen"이 중복됩니다. TermsScreenContent 또는 TermsContent로 변경하는 것이 좋습니다.

♻️ 리팩토링 제안
 `@OptIn`(ExperimentalMaterial3Api::class)
 `@Composable`
-private fun TermsScreenScreen(
+private fun TermsScreenContent(
     uiState: TermsUiState,
     onBack: () -> Unit,
     ...
     modifier: Modifier = Modifier,
 ) {
-    val resources = LocalResources.current
-
     Column(modifier = modifier.fillMaxSize()) {
         TermsScreenTopAppBar(onBack = onBack)
         ...
         PrezelButtonArea {
             MainButton(
-                label = resources.getString(R.string.feature_login_impl_terms_continue_button_text),
+                label = stringResource(R.string.feature_login_impl_terms_continue_button_text),
                 enabled = uiState.isRequiredChecked,
                 onClick = onContinue,
             )
         }
     }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsScreen.kt`
around lines 89 - 103, The composable TermsScreenScreen has an unused
LocalResources variable (resources) and its name duplicates "Screen"; remove the
unused resources declaration and replace any resources.getString(...) calls with
Compose's stringResource(...) usage, then rename the function TermsScreenScreen
to a clearer name such as TermsScreenContent or TermsContent and update all call
sites to the new name (search for TermsScreenScreen to refactor references).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt`:
- Around line 40-52: The component lost accessibility role semantics when
switching to PrezelTouchArea; ensure the checkbox exposes Role.Checkbox to
screen readers by updating the touch area’s modifier (in PrezelCheckbox / where
PrezelTouchArea is used) to include checkbox semantics—either replace or augment
the modifier with a toggleable(role = Role.Checkbox) or add Modifier.semantics {
role = Role.Checkbox; stateDescription = if (checked) "checked" else "unchecked"
} so TalkBack recognizes the control and its checked state; apply this change on
the PrezelTouchArea invocation that currently wraps the Icon.

In `@Prezel/feature/login/impl/build.gradle.kts`:
- Around line 14-17: The build fails if privacy/terms keys are missing because
buildConfigField currently calls localProperty(...).get() directly; change to
use the Provider.map pattern so missing properties don't throw (e.g. replace
direct .get() with localProperty("privacy.policy.url").map { value ->
"\"${value}\"" }.orElse("\"\"") or provide a safe default), updating the two
buildConfigField calls for PRIVACY_POLICY_URL and TERMS_OF_SERVICE_URL inside
defaultConfig to use the mapped Provider rather than .get(); reference the
buildConfigField and localProperty usages to locate the spots to change.

In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginScreen.kt`:
- Around line 29-31: The import
androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel is deprecated; replace
it with androidx.hilt.navigation.compose.hiltViewModel in the LoginScreen file
so usages of hiltViewModel() (e.g., in composable functions or where ViewModel
is obtained) reference the navigation-compatible provider; update the import
line and verify references to hiltViewModel() still resolve (no other code
changes needed).

In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginViewModel.kt`:
- Around line 51-57: In LoginViewModel, when BuildConfig.DEBUG short-circuits to
LoginUiEffect.NavigateToTerms the isLoading flag remains true because
handleLoginResult isn't invoked; update the DEBUG branch to clear or reset the
loading state (set isLoading = false or call the existing
handleLoginResult/resetLoading method) before sending
LoginUiEffect.NavigateToTerms so the UI button is re-enabled when returning,
ensuring the same state transition used by the LaunchLogin/provider path is
applied.

In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/component/TermsDetailModal.kt`:
- Around line 84-106: The rememberWebView currently creates a WebView but never
cleans it up; wrap the created WebView in a DisposableEffect inside
rememberWebView (add import androidx.compose.runtime.DisposableEffect) and in
onDispose call proper cleanup on the WebView instance (stopLoading(),
removeAllViews(), clearHistory(), and destroy()) so the WebView created in
remember(url) is destroyed when the composable leaves composition; reference the
rememberWebView function and the WebView instance returned (and keep your
existing webViewClient/NOTION_STYLE_PATCH injection intact).
- Around line 62-68: The AndroidView update lambda is forcing a reload every
recomposition via view.url?.let(view::loadUrl), causing unnecessary network
calls and flicker; remove the update parameter entirely (since the WebView is
recreated with remember(url) / rememberWebView and initial loadUrl(url) is
already called) or change the update to only load when the incoming url differs
from view.url (compare the new url param to view.url before calling loadUrl).
Target the AndroidView usage and its update block in TermsDetailModal.kt and
adjust accordingly.
- Around line 41-50: PrezelTopAppBar is being used without passing windowInsets
so it defaults to WindowInsets() and can overlap the status bar in the
full-screen modal; fix by either passing a status-bar-aware insets instance
(e.g., windowInsets = WindowInsets.statusBars()) into PrezelTopAppBar or by
applying status bar padding to the modal content (e.g., add
Modifier.statusBarsPadding() to the container that uses fillMaxSize), ensuring
the app bar (PrezelTopAppBar) no longer overlaps the system status bar.

In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsScreen.kt`:
- Line 29: The file imports the deprecated symbol
androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel; replace that import
with androidx.hilt.navigation.compose.hiltViewModel and keep existing usages of
hiltViewModel in TermsScreen (or any ViewModel retrieval calls) unchanged so
they resolve to the non-deprecated function from the navigation.compose package.
- Around line 82-83: BuildConfig URLs can be null/empty because localProperty()
may return null; update the click handlers and the consumer to validate URLs
before use: when setting activeDetailUrl from BuildConfig.TERMS_OF_SERVICE_URL
or BuildConfig.PRIVACY_POLICY_URL, guard against null/blank and either set
activeDetailUrl to a safe fallback (e.g., empty string / show error state) or
disable opening the TermsDetailModal; also add validation inside
TermsDetailModal/NotionWebView to check the url passed to
NotionWebView.loadUrl(url) and skip loading (and surface a user-friendly error)
if the URL is null/blank. Ensure you reference activeDetailUrl,
BuildConfig.TERMS_OF_SERVICE_URL, BuildConfig.PRIVACY_POLICY_URL,
TermsDetailModal, and NotionWebView.loadUrl when making these changes.

---

Nitpick comments:
In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsScreen.kt`:
- Around line 89-103: The composable TermsScreenScreen has an unused
LocalResources variable (resources) and its name duplicates "Screen"; remove the
unused resources declaration and replace any resources.getString(...) calls with
Compose's stringResource(...) usage, then rename the function TermsScreenScreen
to a clearer name such as TermsScreenContent or TermsContent and update all call
sites to the new name (search for TermsScreenScreen to refactor references).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c2148e13-9bcb-4425-ac51-c2803ba9a483

📥 Commits

Reviewing files that changed from the base of the PR and between 116867d and eb906a2.

📒 Files selected for processing (21)
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt
  • Prezel/feature/login/impl/build.gradle.kts
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginScreen.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginViewModel.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/contract/LoginUiEffect.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/contract/LoginUiIntent.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/contract/LoginUiState.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/model/LoginUiMessage.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/model/LoginUiMessage.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/navigation/LoginEntryBuilder.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/navigation/LoginTermsNavKey.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsScreen.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsViewModel.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/component/TermsDetailModal.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/contract/TermsUiEffect.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/contract/TermsUiIntent.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/contract/TermsUiState.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/viewModel/LoginUiState.kt
  • Prezel/feature/login/impl/src/main/res/values/strings.xml
💤 Files with no reviewable changes (2)
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/model/LoginUiMessage.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/viewModel/LoginUiState.kt

moondev03 added 12 commits April 3, 2026 00:45
`PrezelCheckbox` 컴포넌트에 접근성 지원을 위한 시맨틱 정보를 추가하였습니다.

*   `modifier`에 `Role.Checkbox`를 지정하여 컴포넌트의 역할을 명시했습니다.
*   `ToggleableState`를 통해 현재 체크 상태(`checked`)를 시맨틱 트리에 반영했습니다.
* refactor: 디버그 환경에서 로그인 시 로딩 상태를 해제하도록 수정

MVP 개발용 디버그 로직에서 약관 화면(`NavigateToTerms`)으로 이동하기 전, `isLoading` 상태를 `false`로 업데이트하여 로딩 인디케이터가 남지 않도록 개선했습니다.
@moondev03 moondev03 force-pushed the feat/#89-약관동의-화면-구현 branch from eb906a2 to 52177dd Compare April 2, 2026 15:46
Copy link
Copy Markdown
Contributor

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt (1)

31-43: ⚠️ Potential issue | 🟠 Major

기본값 WindowInsets()는 기존 호출부의 동작을 깨뜨립니다.

Material3 TopAppBar의 기본 windowInsetsTopAppBarDefaults.windowInsets로, 상태바 등 시스템 인셋을 올바르게 처리합니다. 하지만 현재 WindowInsets()는 빈 인셋을 생성하므로, windowInsets 파라미터를 전달하지 않는 기존 호출부들(TermsScreen, TermsDetailModal, PrezelDatePicker)에서 상태바와 TopAppBar 콘텐츠가 겹칠 수 있습니다.

모달 내부에서 인셋을 제거해야 하는 경우에는 해당 호출부에서 명시적으로 WindowInsets()를 전달하는 것이 바람직합니다.

🛠️ 기존 동작을 유지하면서 커스텀 인셋을 허용하는 수정 제안
 `@Composable`
 fun PrezelTopAppBar(
     modifier: Modifier = Modifier,
     title: `@Composable` () -> Unit = {},
     leadingIcon: `@Composable` () -> Unit = {},
     trailingIcons: `@Composable` RowScope.() -> Unit = {},
     scrollBehavior: TopAppBarScrollBehavior? = null,
-    windowInsets: WindowInsets = WindowInsets(),
+    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
 ) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt`
around lines 31 - 43, 기본 파라미터 windowInsets가 WindowInsets()로 설정돼 있어 기존 호출부의 동작을
깨뜨리므로 TopAppBar 컴포저블의 파라미터 기본값을 TopAppBarDefaults.windowInsets로 변경하고, 모달 등에서 인셋을
제거해야 하는 경우에는 해당 호출부(TermsScreen, TermsDetailModal, PrezelDatePicker 등)에 명시적으로
WindowInsets()를 전달하도록 수정하세요; 관련 식별자: TopAppBar (컴포저블), windowInsets 파라미터,
TopAppBarDefaults.windowInsets, 호출부 예시
TermsScreen/TermsDetailModal/PrezelDatePicker.
🧹 Nitpick comments (1)
Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginScreen.kt (1)

90-93: animatedVisibilityScope 계약은 시그니처에 드러내는 편이 안전합니다.

Line 92처럼 내부에서 scope를 조회하도록 바뀌면, 이 화면이 어떤 호스트 전제조건을 필요로 하는지 호출 지점에서 바로 드러나지 않습니다. 이전처럼 파라미터로 유지하면 재사용 지점과 테스트 코드에서 계약이 더 명확해집니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginScreen.kt`
around lines 90 - 93, The LoginScreen composable should explicitly accept
animatedVisibilityScope as a parameter rather than querying
LocalNavAnimatedContentScope.current inside; update the LoginScreen signature to
include an animatedVisibilityScope parameter (e.g., animatedVisibilityScope:
NavAnimatedContentScopeType) and restore the call site to pass
LocalNavAnimatedContentScope.current (as shown in the diff) so the host
requirement is visible to callers; update any other usages and tests of
LoginScreen to provide the scope and remove internal accesses to
LocalNavAnimatedContentScope.current within LoginScreen.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt`:
- Around line 31-43: 기본 파라미터 windowInsets가 WindowInsets()로 설정돼 있어 기존 호출부의 동작을
깨뜨리므로 TopAppBar 컴포저블의 파라미터 기본값을 TopAppBarDefaults.windowInsets로 변경하고, 모달 등에서 인셋을
제거해야 하는 경우에는 해당 호출부(TermsScreen, TermsDetailModal, PrezelDatePicker 등)에 명시적으로
WindowInsets()를 전달하도록 수정하세요; 관련 식별자: TopAppBar (컴포저블), windowInsets 파라미터,
TopAppBarDefaults.windowInsets, 호출부 예시
TermsScreen/TermsDetailModal/PrezelDatePicker.

---

Nitpick comments:
In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginScreen.kt`:
- Around line 90-93: The LoginScreen composable should explicitly accept
animatedVisibilityScope as a parameter rather than querying
LocalNavAnimatedContentScope.current inside; update the LoginScreen signature to
include an animatedVisibilityScope parameter (e.g., animatedVisibilityScope:
NavAnimatedContentScopeType) and restore the call site to pass
LocalNavAnimatedContentScope.current (as shown in the diff) so the host
requirement is visible to callers; update any other usages and tests of
LoginScreen to provide the scope and remove internal accesses to
LocalNavAnimatedContentScope.current within LoginScreen.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2be57404-4728-447c-b9e8-6885e0707cd0

📥 Commits

Reviewing files that changed from the base of the PR and between eb906a2 and 52177dd.

📒 Files selected for processing (21)
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelAccordion.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/TopAppBar.kt
  • Prezel/feature/login/impl/build.gradle.kts
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginScreen.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/LoginViewModel.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/contract/LoginUiEffect.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/contract/LoginUiIntent.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/contract/LoginUiState.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/model/LoginUiMessage.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/model/LoginUiMessage.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/navigation/LoginEntryBuilder.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/navigation/LoginTermsNavKey.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsScreen.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsViewModel.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/component/TermsDetailModal.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/contract/TermsUiEffect.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/contract/TermsUiIntent.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/contract/TermsUiState.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/viewModel/LoginUiState.kt
  • Prezel/feature/login/impl/src/main/res/values/strings.xml
💤 Files with no reviewable changes (2)
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/viewModel/LoginUiState.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/model/LoginUiMessage.kt
✅ Files skipped from review due to trivial changes (7)
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/navigation/LoginTermsNavKey.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/contract/LoginUiState.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/contract/LoginUiIntent.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/model/LoginUiMessage.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/contract/TermsUiEffect.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/contract/TermsUiIntent.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/contract/TermsUiState.kt
🚧 Files skipped from review as they are similar to previous changes (8)
  • Prezel/feature/login/impl/build.gradle.kts
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/landing/contract/LoginUiEffect.kt
  • Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/PrezelCheckbox.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/navigation/LoginEntryBuilder.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsViewModel.kt
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsScreen.kt
  • Prezel/feature/login/impl/src/main/res/values/strings.xml
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/component/TermsDetailModal.kt

@HamBeomJoon HamBeomJoon closed this Apr 3, 2026
@HamBeomJoon HamBeomJoon deleted the feat/#89-약관동의-화면-구현 branch April 3, 2026 04:38
@moondev03 moondev03 restored the feat/#89-약관동의-화면-구현 branch April 3, 2026 04:38
@moondev03 moondev03 reopened this Apr 3, 2026
* refactor: `TermsUiIntent` 네이밍 변경

`TermsUiIntent`의 각 항목에서 불필요한 `On` 접두사를 제거하여 네이밍을 간결하게 수정했습니다.
- `OnToggleAll` -> `ToggleAll`
- `OnToggleTermsOfService` -> `ToggleTermsOfService`
- `OnTogglePrivacyPolicy` -> `TogglePrivacyPolicy`
- `OnToggleMarketingConsent` -> `ToggleMarketingConsent`
- `OnClickContinue` -> `ClickContinue`

* refactor: TermsViewModel 코드 포맷팅 및 구조 정리

- `TermsViewModel` 생성자 및 내부 메서드의 들여쓰기(Indentation)를 수정하여 가독성을 개선했습니다.
- 변경된 `TermsUiIntent` 명칭에 맞춰 `onIntent` 내 `when` 분기 로직을 업데이트했습니다.

* refactor: TermsScreen 내 Intent 호출부 업데이트

- `TermsScreen` 컴포저블에서 `ViewModel`로 Intent를 전달하는 코드를 신규 네이밍 규칙에 맞게 수정했습니다.
* refactor: `TermsUiIntent` 네이밍 변경

`TermsUiIntent`의 각 항목에서 불필요한 `On` 접두사를 제거하여 네이밍을 간결하게 수정했습니다.
- `OnToggleAll` -> `ToggleAll`
- `OnToggleTermsOfService` -> `ToggleTermsOfService`
- `OnTogglePrivacyPolicy` -> `TogglePrivacyPolicy`
- `OnToggleMarketingConsent` -> `ToggleMarketingConsent`
- `OnClickContinue` -> `ClickContinue`

* refactor: TermsViewModel 코드 포맷팅 및 구조 정리

- `TermsViewModel` 생성자 및 내부 메서드의 들여쓰기(Indentation)를 수정하여 가독성을 개선했습니다.
- 변경된 `TermsUiIntent` 명칭에 맞춰 `onIntent` 내 `when` 분기 로직을 업데이트했습니다.

* refactor: TermsScreen 내 Intent 호출부 업데이트

- `TermsScreen` 컴포저블에서 `ViewModel`로 Intent를 전달하는 코드를 신규 네이밍 규칙에 맞게 수정했습니다.
Copy link
Copy Markdown
Contributor

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

🧹 Nitpick comments (2)
Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsViewModel.kt (2)

44-54: 상태 읽기를 update 블록 내부로 이동 고려 (선택사항)

currentState.isAllCheckedupdate 블록 외부에서 읽고 있어, 이론적으로 읽기와 업데이트 사이에 상태가 변경될 수 있습니다. 실제로 UI 이벤트는 순차적으로 처리되어 문제가 될 가능성은 낮지만, 더 안전한 패턴을 원하신다면:

♻️ 더 안전한 패턴 제안
         private fun toggleAll() {
-            val newChecked = !currentState.isAllChecked
-
             update {
+                val newChecked = !isAllChecked
                 copy(
                     isTermsOfServiceChecked = newChecked,
                     isPrivacyPolicyChecked = newChecked,
                     isMarketingConsentChecked = newChecked,
                 )
             }
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsViewModel.kt`
around lines 44 - 54, 현재 toggleAll()에서 currentState.isAllChecked를 update 블록 외부에서
읽고 있어 상태가 중간에 바뀔 가능성이 있으니, 읽기를 update의 인자로 전달된 상태 내부로 이동해 안전하게 처리하세요; 즉
toggleAll()의 update { ... } 호출을 state -> copy(...) 형태로 사용하고, newChecked 값을 외부가
아닌 전달된 state.isAllChecked로 계산하도록 변경해 현재의 currentState, toggleAll, update 식별자를
사용해 수정하세요.

27-28: UI Effect 채널에 버퍼 추가 권장

기본 Channel()은 RENDEZVOUS 용량(0)을 사용하므로, 수신자가 준비되지 않은 상태에서 send()를 호출하면 suspend됩니다. Configuration change 중에 이벤트가 지연되거나 유실될 수 있습니다.

♻️ 버퍼 추가 제안
-        private val _uiEffect = Channel<TermsUiEffect>()
+        private val _uiEffect = Channel<TermsUiEffect>(Channel.BUFFERED)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsViewModel.kt`
around lines 27 - 28, The _uiEffect Channel is created with the default
RENDEZVOUS (0) capacity which can suspend senders and risk lost/delayed events
during configuration changes; change the declaration to create a buffered
channel (e.g., use Channel(Channel.BUFFERED) or Channel(1)) and keep uiEffect as
_uiEffect.receiveAsFlow() so senders can use _uiEffect.trySend(...) or
_uiEffect.send(...) without unexpected suspension; update references to
_uiEffect and uiEffect in TermsViewModel accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsViewModel.kt`:
- Around line 44-54: 현재 toggleAll()에서 currentState.isAllChecked를 update 블록 외부에서
읽고 있어 상태가 중간에 바뀔 가능성이 있으니, 읽기를 update의 인자로 전달된 상태 내부로 이동해 안전하게 처리하세요; 즉
toggleAll()의 update { ... } 호출을 state -> copy(...) 형태로 사용하고, newChecked 값을 외부가
아닌 전달된 state.isAllChecked로 계산하도록 변경해 현재의 currentState, toggleAll, update 식별자를
사용해 수정하세요.
- Around line 27-28: The _uiEffect Channel is created with the default
RENDEZVOUS (0) capacity which can suspend senders and risk lost/delayed events
during configuration changes; change the declaration to create a buffered
channel (e.g., use Channel(Channel.BUFFERED) or Channel(1)) and keep uiEffect as
_uiEffect.receiveAsFlow() so senders can use _uiEffect.trySend(...) or
_uiEffect.send(...) without unexpected suspension; update references to
_uiEffect and uiEffect in TermsViewModel accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c045f2ab-652b-480f-ad90-22cb00ec7c6c

📥 Commits

Reviewing files that changed from the base of the PR and between bc4ccd0 and 9036b98.

📒 Files selected for processing (1)
  • Prezel/feature/login/impl/src/main/java/com/team/prezel/feature/login/impl/terms/TermsViewModel.kt

Copy link
Copy Markdown
Contributor

@HamBeomJoon HamBeomJoon left a comment

Choose a reason for hiding this comment

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

고생하셨습니다

@moondev03 moondev03 merged commit b739342 into develop Apr 3, 2026
2 checks passed
@moondev03 moondev03 deleted the feat/#89-약관동의-화면-구현 branch April 3, 2026 05:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feat 새로운 기능 추가 또는 기존 기능 확장

Projects

None yet

Development

Successfully merging this pull request may close these issues.

약관동의 화면 구현

2 participants