Skip to content

[FEAT/#76] 정보입력뷰 api 연결#85

Merged
sohee6989 merged 26 commits intodevelopfrom
feat/#76-information-api
Jan 19, 2026
Merged

[FEAT/#76] 정보입력뷰 api 연결#85
sohee6989 merged 26 commits intodevelopfrom
feat/#76-information-api

Conversation

@sohee6989
Copy link
Copy Markdown
Contributor

@sohee6989 sohee6989 commented Jan 18, 2026

Related issue 🛠

Work Description ✏️

  • 정보입력뷰 api 연결
  • 입력뷰 에러 메세지

Screenshot 📸

스크린샷 2026-01-19 오전 12 03 13
Screen_recording_20260118_235944.mp4

Uncompleted Tasks 😅

  • N/A

To Reviewers 📢

다들 화이팅팅팅
스플래서, 온보딩 머지 기다려닸가 그 부분 네비 연결까지 이 브랜치에서 해놓겠습니다~!!
(분리를 원하시면 코멘트 남겨주세요오~!!)

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 온보딩 화면 및 프로필 정보 입력/제출 기능 추가 (이름·나이)
    • 온보딩 단계별 네비게이션 그래프와 사이드이펙트 기반 이동 흐름 추가
    • 서버 전송 후 응답 처리 및 식별자 저장 자동 처리
  • 개선

    • 소프트 키보드에 따른 고급 패딩 처리로 입력 필드 가시성 향상
    • 입력 유효성 검사 강화 및 필드별 오류 표시(이름 길이, 나이 범위)
    • 화면 회전/오리엔테이션 관련 동작 조정
  • 문서/기타

    • Android 매니페스트 포맷 정리 및 키보드 동작 설정 추가

✏️ Tip: You can customize this high-level summary in your review settings.

@sohee6989 sohee6989 requested a review from a team as a code owner January 18, 2026 14:28
@sohee6989 sohee6989 linked an issue Jan 18, 2026 that may be closed by this pull request
@sohee6989 sohee6989 self-assigned this Jan 18, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 18, 2026

Walkthrough

온보딩 프로필 제출 기능과 관련된 데이터 계층(서비스/데이터소스/리포지토리/DTO/모델), DI 바인딩, 프레젠테이션 계층(온보딩 UI, 입력 검증, 사이드이펙트, 네비게이션), IME 패딩 확장, 및 액티비티 설정이 추가되었습니다.

Changes

Cohort / File(s) 요약
AndroidManifest / Activity
app/src/main/AndroidManifest.xml, app/src/main/java/com/cherrish/android/presentation/main/MainActivity.kt
MainActivityandroid:windowSoftInputMode="adjustResize" 추가 및 onCreate에서 화면 방향을 SCREEN_ORIENTATION_UNSPECIFIED로 설정.
IME padding 확장
app/src/main/java/com/cherrish/android/core/common/extension/ModifierExt.kt
Compose용 새 확장 Modifier.advancedImePadding() 추가(뷰 위치 기반 소비 inset 계산 후 imePadding 적용). 주의: 레이아웃 측정과 상태 관리 포함.
원격 DTOs
app/src/main/java/com/cherrish/android/data/remote/dto/request/OnboardingProfileRequestDto.kt,
app/src/main/java/com/cherrish/android/data/remote/dto/response/OnboardingProfileResponseDto.kt
요청/응답 직렬화 DTO 추가(name, age, id, date).
데이터/도메인 모델 및 매퍼
app/src/main/java/com/cherrish/android/data/model/OnboardingProfileRequestModel.kt,
app/src/main/java/com/cherrish/android/data/model/OnboardingProfileResponseModel.kt
도메인 모델과 DTO 변환 매퍼(toDto(), toModel()) 추가.
원격 데이터 레이어 구현
app/src/main/java/com/cherrish/android/data/remote/service/OnboardingProfileService.kt,
app/src/main/java/com/cherrish/android/data/remote/datasource/OnboardingProfileDataSource.kt,
app/src/main/java/com/cherrish/android/data/remote/datasourceimpl/OnboardingProfileDataSourceImpl.kt
Retrofit 서비스와 데이터소스 인터페이스/구현 추가 (POST /api/onboarding/profiles).
DI 모듈 바인딩
app/src/main/java/com/cherrish/android/data/di/ServiceModule.kt,
app/src/main/java/com/cherrish/android/data/di/DataSourceModule.kt,
app/src/main/java/com/cherrish/android/data/di/RepositoryModule.kt
OnboardingProfile 관련 Service/DataSource/Repository 제공자 및 @Binds 추가(@Singleton). DI 연결 확인 필요.
저장소 구현
app/src/main/java/com/cherrish/android/data/repository/OnboardingProfileRepository.kt,
app/src/main/java/com/cherrish/android/data/repositoryimpl/OnboardingProfileRepositoryImpl.kt
저장소 인터페이스 및 구현 추가(요청 변환, suspendRunCatching 래핑, 응답 매핑). 예외/널 처리 흐름 검토 권장.
온보딩 네비게이션 및 그래프
app/src/main/java/com/cherrish/android/presentation/onboarding/navigation/OnboardingNavigator.kt,
app/src/main/java/com/cherrish/android/presentation/onboarding/navigation/OnboardingInformationNavigator.kt
Onboarding 및 OnboardingInformation 라우트/네비게이션 확장, NavController 확장 함수 및 NavGraphBuilder 헬퍼 추가.
온보딩 화면 및 사이드이펙트
app/src/main/java/com/cherrish/android/presentation/onboarding/OnboardingViewModel.kt,
app/src/main/java/com/cherrish/android/presentation/onboarding/OnboardingScreen.kt,
app/src/main/java/com/cherrish/android/presentation/onboarding/OnboardingSideEffect.kt
SharedFlow 기반 사이드 이펙트 추가(NavigateToOnboardingInformation), 라우트/스크린 서명에 패딩 전달 추가 및 onClick → 사이드이펙트 발행 로직 변경.
온보딩 정보 입력 화면
app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationViewModel.kt,
app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationScreen.kt,
app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationUiState.kt,
app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationNavigator.kt
입력 검증(이름 ≤7자, 나이 1–100), UI 에러 플래그, API 호출(onNext → repository), TokenManager에 id 저장, 성공 시 NavigateToHome 사이드이펙트 방출 및 네비게이션 연결. UI와 VM 간 에러/사이드이펙트 흐름 확인 필요.
메인 화면 네비게이션 통합
app/src/main/java/com/cherrish/android/presentation/main/MainScreen.kt,
app/src/main/java/com/cherrish/android/presentation/main/MainAppState.kt
온보딩 관련 NavGraphs 통합 및 clearStackNavOptions/헬퍼 메서드 추가로 네비게이션 흐름 연결.

Sequence Diagram(s)

sequenceDiagram
    participant User as 사용자
    participant UI as OnboardingInformation<br/>Screen
    participant VM as OnboardingInformation<br/>ViewModel
    participant Repo as OnboardingProfile<br/>Repository
    participant DS as OnboardingProfile<br/>DataSource
    participant Service as OnboardingProfile<br/>Service
    participant API as API Server
    participant TM as TokenManager

    User->>UI: 이름/나이 입력
    UI->>VM: onNameChanged/onAgeChanged
    VM->>VM: uiState 업데이트/검증

    User->>UI: Next 클릭
    UI->>VM: onNextClicked()
    VM->>Repo: postOnboardingProfile(requestModel)
    Repo->>DS: postOnboardingProfile(requestDto)
    DS->>Service: postOnboardingProfile(requestDto)
    Service->>API: POST /api/onboarding/profiles
    API-->>Service: BaseResponse<ResponseDto>
    Service-->>DS: 응답 반환
    DS-->>Repo: 응답 반환
    Repo->>Repo: 응답 toModel()
    Repo-->>VM: Result<ResponseModel>
    VM->>TM: saveId(id)
    TM-->>VM: 완료
    VM->>VM: _sideEffect.emit(NavigateToHome)
    VM-->>UI: sideEffect 수집
    UI->>UI: navigateToHome()
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • nhyeonii
  • usuuhyn
🚥 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의 주요 변경 사항(정보입력뷰의 API 연결)을 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명이 템플릿의 주요 섹션(Related issue, Work Description, Screenshot, Uncompleted Tasks, To Reviewers)을 포함하고 있습니다.
Linked Issues check ✅ Passed 변경 사항들이 #76 이슈의 목표인 정보입력뷰 API 연결을 충족합니다. 데이터 레이어 구현(DTO, Service, DataSource, Repository), ViewModel 및 UI 계층 통합이 완벽하게 이루어졌습니다.
Out of Scope Changes check ✅ Passed 일부 추가 변경사항(IME 패딩, 화면 방향 설정, 네비게이션 연결)이 있지만 모두 정보입력 뷰 개선과 관련된 기능들입니다.

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

✨ 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

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

@sohee6989 sohee6989 added FEAT✨ 새로운 기능 구현 소희🍒 소희 담당 labels Jan 18, 2026
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: 5

🤖 Fix all issues with AI agents
In `@app/src/main/java/com/cherrish/android/core/common/extension/ModifierExt.kt`:
- Around line 101-106: 현재 onGloballyPositioned 블록에서 consumePadding이 루트 높이에서
(positionInWindow().y + size.height)를 뺀 값으로 계산되는데, coerceAtLeast(0)가 뺄셈 전 항목에만
적용되어 최종 결과가 음수가 될 수 있습니다; 수정 방법은 onGloballyPositioned 내부의 계산 전체에 대해 최종값을 0 이상으로
클램프하도록 변경하는 것으로, 예컨대 computeValue = findRootCoordinates().size.height -
(coordinates.positionInWindow().y + coordinates.size.height).toInt();
consumePadding = computeValue.coerceAtLeast(0); 이렇게 onGloballyPositioned,
consumePadding, coordinates.findRootCoordinates(),
coordinates.positionInWindow(), coordinates.size.height식을 참조해 최종 값을
.coerceAtLeast(0)로 감싸 주세요.

In `@app/src/main/java/com/cherrish/android/data/di/ServiceModule.kt`:
- Around line 22-26: provideOnboardingProfileService is annotated with
javax.annotation.Signed which is not a Dagger Qualifier and will not
differentiate bindings, causing injection failures at
OnboardingProfileDataSourceImpl; either replace `@Signed` with `@Singleton` to match
CalendarService's scope, or define a custom Dagger `@Qualifier` (apply it to both
the provider provideOnboardingProfileService and the injection site in
OnboardingProfileDataSourceImpl) so the signed Retrofit binding is uniquely
identified and resolves correctly.

In
`@app/src/main/java/com/cherrish/android/data/repositoryimpl/OnboardingProfileRepositoryImpl.kt`:
- Around line 18-22: Replace the forced unwrap of response.data in the
suspendRunCatching block: call
onboardingProfileDataSource.postOnboardingProfile(request = request.toDto()),
capture the response, and explicitly handle a null data (response.data) before
calling toModel(); e.g., if data is null return/emit a Result.failure or throw a
clear exception with context rather than using !!, or alternatively make the
DTO's data field non-nullable if it is guaranteed by the API; reference
onboardingProfileDataSource.postOnboardingProfile, suspendRunCatching,
response.data, toModel() and toDto() when applying the change.

In `@app/src/main/java/com/cherrish/android/presentation/main/MainScreen.kt`:
- Around line 26-35: The navOptions in clearStackNavOptions use popUpTo(0),
which references a non-existent numeric ID for typed (`@Serializable`) routes;
replace that with a valid target such as the navigation graph start destination
or a route string. Update clearStackNavOptions to call
popUpTo(navController.graph.startDestinationId) (or popUpTo("YourStartRoute")
when using route strings) so popUpTo targets an actual destination; keep
launchSingleTop and restoreState as-is. Ensure the change is made where
clearStackNavOptions (and any other popUpTo usages) is defined so the typed
navigation IDs are valid.

In
`@app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationViewModel.kt`:
- Around line 44-54: The onNextClicked() flow in InformationViewModel should
defensively handle empty or non-numeric ages to avoid NumberFormatException:
instead of calling uiState.value.age.toInt() unguarded, parse with
uiState.value.age.toIntOrNull() (or validate that uiState.value.age.isNotBlank()
&& matches(\\d+)) and if null/invalid emit an appropriate side effect/error or
return early; then continue to call
onboardingProfileRepository.postOnboardingProfile(...) with
OnboardingProfileRequestModel(name = uiState.value.username, age = safeInt) and
preserve the existing success path that calls tokenManager.saveId(response.id)
and _sideEffect.emit(InformationSideEffect.NavigateToHome).

Comment thread app/src/main/java/com/cherrish/android/data/di/ServiceModule.kt
Comment on lines +18 to +22
suspendRunCatching {
onboardingProfileDataSource.postOnboardingProfile(
request = request.toDto()
).data!!.toModel()
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

data!! 강제 언래핑은 NPE 위험이 있습니다.

API 응답이 성공적으로 반환되더라도 datanull인 경우 NullPointerException이 발생합니다. suspendRunCatching이 예외를 Result.failure로 변환하긴 하지만, 명시적인 null 처리가 더 안전합니다.

🛠️ 제안하는 수정 방안
     override suspend fun postOnboardingProfile(
         request: OnboardingProfileRequestModel
     ): Result<OnboardingProfileResponseModel> =
         suspendRunCatching {
             onboardingProfileDataSource.postOnboardingProfile(
                 request = request.toDto()
-            ).data!!.toModel()
+            ).data?.toModel()
+                ?: throw IllegalStateException("Onboarding profile response data is null")
         }

또는 API 응답 구조에서 data가 항상 non-null임이 보장된다면, DTO의 data 필드를 non-nullable로 변경하는 것이 더 근본적인 해결책입니다.

📝 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
suspendRunCatching {
onboardingProfileDataSource.postOnboardingProfile(
request = request.toDto()
).data!!.toModel()
}
suspendRunCatching {
onboardingProfileDataSource.postOnboardingProfile(
request = request.toDto()
).data?.toModel()
?: throw IllegalStateException("Onboarding profile response data is null")
}
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/data/repositoryimpl/OnboardingProfileRepositoryImpl.kt`
around lines 18 - 22, Replace the forced unwrap of response.data in the
suspendRunCatching block: call
onboardingProfileDataSource.postOnboardingProfile(request = request.toDto()),
capture the response, and explicitly handle a null data (response.data) before
calling toModel(); e.g., if data is null return/emit a Result.failure or throw a
clear exception with context rather than using !!, or alternatively make the
DTO's data field non-nullable if it is guaranteed by the API; reference
onboardingProfileDataSource.postOnboardingProfile, suspendRunCatching,
response.data, toModel() and toDto() when applying the change.

Comment thread app/src/main/java/com/cherrish/android/presentation/main/MainScreen.kt Outdated
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

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt`:
- Around line 229-233: The Text composable rendering errorText (in
InformationScreen's error block) uses Color.Transparent when errorCase is false
which hides visually but remains in accessibility tree; update the Text to
conditionally add semantics { invisibleToUser() } (using modifier.semantics)
when errorCase is false so TalkBack won't read it, and add the suggested imports
(androidx.compose.ui.semantics.invisibleToUser and
androidx.compose.ui.semantics.semantics); locate the Text that references
errorText and errorCase and apply the conditional modifier there.

Comment on lines +229 to +233
Text(
text = errorText,
style = CherrishTheme.typography.body1R14,
color = if (errorCase) CherrishTheme.colors.red700 else Color.Transparent
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt | sed -n '220,240p'

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 800


🏁 Script executed:

# Also check imports at the beginning of the file
head -50 app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 2424


🏁 Script executed:

# Check if semantics imports exist anywhere
rg "import.*semantics" app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 56


🏁 Script executed:

# Search for similar conditional visibility patterns with semantics
rg "invisibleToUser|semantics.*invisibleToUser" --type kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 100


🏁 Script executed:

# Check for other error text handling patterns
rg "Color\.Transparent" --type kt -B 2 -A 2 | head -40

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 100


🏁 Script executed:

# Search for similar conditional visibility patterns with semantics (corrected)
rg "invisibleToUser|semantics" --type kotlin | head -20

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 56


🏁 Script executed:

# Check for other Color.Transparent usage
rg "Color\.Transparent" --type kotlin -B 2 -A 2

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 6059


🏁 Script executed:

# Check how errorText is defined and set
rg "errorText" app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt -B 3 -A 1

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 727


🏁 Script executed:

# Check the full composable function signature to understand the context
sed -n '180,235p' app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 1877


🏁 Script executed:

# Check build.gradle for Compose version
find . -name "build.gradle*" -type f | xargs grep -l "compose" | head -3

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 115


🏁 Script executed:

# Check if there's gradle or version information
cat build.gradle 2>/dev/null || cat build.gradle.kts 2>/dev/null | head -50

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 424


🏁 Script executed:

# Check app's build.gradle.kts for Compose dependencies
cat app/build.gradle.kts | grep -A 30 "dependencies"

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 1045


🏁 Script executed:

# Check gradle/libs.versions.toml for version definitions
cat gradle/libs.versions.toml | head -80

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 3033


🏁 Script executed:

# Check if semantics is used elsewhere in the codebase
rg "semantics\s*\{" --type kotlin | head -10

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 56


🏁 Script executed:

# Check Compose Material3 and Compose UI documentation for invisibleToUser
# Let's also verify the exact import path
rg "androidx.compose.ui.semantics" app/ --type kotlin

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 56


🏁 Script executed:

# Check for other error message patterns in the codebase
rg "errorCase|error.*Text" app/src/main/java/com/cherrish/android/presentation --type kotlin -A 2 | head -30

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 2509


🏁 Script executed:

# Check the specific composable context more thoroughly
sed -n '175,245p' app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 2284


에러 상태가 아닐 때 보이지 않는 에러 텍스트가 접근성 트리에 남아 TalkBack에서 읽힙니다.
Color.Transparent는 시각적으로만 숨기므로, 에러가 없을 때는 invisibleToUser()로 접근성에서도 제외해야 합니다.

🔧 제안 수정
         Text(
             text = errorText,
             style = CherrishTheme.typography.body1R14,
-            color = if (errorCase) CherrishTheme.colors.red700 else Color.Transparent
+            color = if (errorCase) CherrishTheme.colors.red700 else Color.Transparent,
+            modifier = if (errorCase) Modifier else Modifier.semantics { invisibleToUser() }
         )

필요한 import:

import androidx.compose.ui.semantics.invisibleToUser
import androidx.compose.ui.semantics.semantics
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/presentation/onboarding/information/InformationScreen.kt`
around lines 229 - 233, The Text composable rendering errorText (in
InformationScreen's error block) uses Color.Transparent when errorCase is false
which hides visually but remains in accessibility tree; update the Text to
conditionally add semantics { invisibleToUser() } (using modifier.semantics)
when errorCase is false so TalkBack won't read it, and add the suggested imports
(androidx.compose.ui.semantics.invisibleToUser and
androidx.compose.ui.semantics.semantics); locate the Text that references
errorText and errorCase and apply the conditional modifier there.

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

🤖 Fix all issues with AI agents
In
`@app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationViewModel.kt`:
- Around line 57-60: The empty onLogFailure block in
OnboardingInformationViewModel leaves API failures unhandled; update the
onLogFailure handler to emit a user-facing error side effect (use
_sideEffect.emit) with the failure message or a localized string and provide a
retry option (e.g., emit InformationSideEffect.ShowError or a new
ShowErrorWithRetry side effect), so failures after the tokenManager.saveId /
InformationSideEffect.NavigateToHome flow surface to the UI and allow retry.
♻️ Duplicate comments (2)
app/src/main/java/com/cherrish/android/presentation/main/MainScreen.kt (1)

28-31: popUpTo(0) 대상이 유효한지 확인 필요
타입드 라우팅을 쓰는 경우 0은 유효한 목적지 ID가 아닐 수 있습니다. 그래프의 실제 ID(예: appState.navController.graph.id)나 시작 목적지를 사용해주세요.

🛠️ 수정 제안
 val clearStackNavOptions = navOptions {
-    popUpTo(0) { inclusive = true }
+    popUpTo(appState.navController.graph.id) { inclusive = true }
     launchSingleTop = true
     restoreState = false
 }
app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationScreen.kt (1)

229-233: 에러 텍스트 접근성 문제

Color.Transparent는 시각적으로만 텍스트를 숨기며, TalkBack 등 스크린 리더에서는 여전히 읽힙니다. 에러 상태가 아닐 때는 semantics { invisibleToUser() }를 적용하여 접근성 트리에서도 제외해야 합니다.

🔧 수정 제안
+import androidx.compose.ui.semantics.invisibleToUser
+import androidx.compose.ui.semantics.semantics
         Text(
             text = errorText,
             style = CherrishTheme.typography.body1R14,
-            color = if (errorCase) CherrishTheme.colors.red700 else Color.Transparent
+            color = if (errorCase) CherrishTheme.colors.red700 else Color.Transparent,
+            modifier = if (errorCase) Modifier else Modifier.semantics { invisibleToUser() }
         )
🧹 Nitpick comments (5)
app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationUiState.kt (1)

10-15: age 파싱 중복 제거로 조건식 단순화
age.toIntOrNull()가 두 번 호출되어 중복 파싱이 발생합니다. ageInt를 재사용해 조건을 단순화해주세요.

♻️ 수정 제안
 val buttonEnabled: Boolean
     get() {
-        val ageInt = age.toIntOrNull() ?: return false
-        return username.isNotBlank() && age.toIntOrNull()?.let { it > 0 } == true &&
-            ageInt in 1..100 && username.length <= 7
+        val ageInt = age.toIntOrNull() ?: return false
+        return username.isNotBlank() &&
+            username.length <= 7 &&
+            ageInt in 1..100
     }
app/src/main/java/com/cherrish/android/presentation/onboarding/OnboardingScreen.kt (1)

99-114: paddingValues를 루트 컨테이너에 먼저 적용하세요
현재 Column에만 paddingValues가 적용돼 하단 오버레이 영역은 스캐폴드 인셋을 공유하지 않습니다. Box 루트에 paddingValues를 적용하면 인셋 처리가 일관됩니다. Based on learnings, 루트에 먼저 paddingValues를 적용하는 패턴을 유지해주세요.

♻️ 수정 제안
 Box(
     modifier = modifier
         .fillMaxSize()
         .background(
             brush = Brush.verticalGradient(
                 colors = persistentListOf(colors.graStart, colors.graEnd),
                 startY = 0f,
                 endY = gradientEndY
             )
-        )
+        )
+        .padding(paddingValues)
 ) {
     Column(
         modifier = Modifier
-            .fillMaxSize()
-            .padding(paddingValues)
+            .fillMaxSize()
     ) {

Also applies to: 154-162

app/src/main/java/com/cherrish/android/presentation/main/MainAppState.kt (1)

84-94: NavOptions 매개변수의 일관성 검토 필요

새로 추가된 navigation helper 메서드들은 NavOptions를 필수 매개변수로 받고 있지만, OnboardingInformationNavigator.kt의 extension 함수(navigateToOnboardingInformation)는 NavOptions? = null로 nullable 기본값을 사용합니다. 일관성을 위해 nullable로 변경하거나, 호출부에서 항상 navOptions를 제공해야 하는 이유를 명확히 하는 것이 좋습니다.

♻️ 일관성을 위한 수정 제안
-    fun navigateToOnboarding(navOptions: NavOptions) {
+    fun navigateToOnboarding(navOptions: NavOptions? = null) {
         navController.navigateToOnboarding(navOptions)
     }

-    fun navigateToOnboardingInformation(navOptions: NavOptions) {
+    fun navigateToOnboardingInformation(navOptions: NavOptions? = null) {
         navController.navigateToOnboardingInformation(navOptions)
     }

-    fun navigateToHome(navOptions: NavOptions) {
+    fun navigateToHome(navOptions: NavOptions? = null) {
         navController.navigateToHome(navOptions)
     }
app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationScreen.kt (1)

66-67: 에러 상태 계산의 불필요한 recomposition 비용

viewModel.onNameErrorCase(uiState.username)viewModel.onAgeErrorCase(uiState.age)가 매 recomposition마다 호출됩니다. 이 로직은 ViewModel의 InformationUiStatenameErrorCaseageErrorCase 필드를 추가하여 상태 변경 시에만 계산되도록 최적화할 수 있습니다.

♻️ ViewModel에서 파생 상태로 관리하는 방안

InformationUiState에 에러 상태를 포함시키고, onNameChanged/onAgeChanged에서 함께 업데이트:

// InformationUiState.kt
data class InformationUiState(
    val username: String = "",
    val age: String = "",
    val nameErrorCase: Boolean = false,
    val ageErrorCase: Boolean = false
) {
    val buttonEnabled: Boolean
        get() = username.isNotBlank() && age.isNotBlank() && !nameErrorCase && !ageErrorCase
}
// OnboardingInformationViewModel.kt
fun onNameChanged(name: String) {
    _uiState.update {
        it.copy(
            username = name,
            nameErrorCase = name.length > 7
        )
    }
}
app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationViewModel.kt (1)

46-46: 사소한 스타일 개선

?.let 앞의 불필요한 공백을 제거하면 더 깔끔합니다.

-    fun onAgeErrorCase(age: String): Boolean = age.toIntOrNull() ?.let { it > 100 } ?: false
+    fun onAgeErrorCase(age: String): Boolean = age.toIntOrNull()?.let { it > 100 } ?: false

Comment on lines +57 to +60
).onSuccess { response ->
tokenManager.saveId(response.id)
_sideEffect.emit(InformationSideEffect.NavigateToHome)
}.onLogFailure {}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

API 실패 시 사용자 피드백 부재

onLogFailure {}가 빈 블록으로 되어 있어 API 호출 실패 시 사용자에게 아무런 피드백이 제공되지 않습니다. 오류 메시지를 표시하거나 재시도 옵션을 제공하는 것이 좋습니다.

🔧 에러 처리 개선 제안
// InformationSideEffect에 추가
sealed interface InformationSideEffect {
    data object NavigateToHome : InformationSideEffect
+   data class ShowError(val message: String) : InformationSideEffect
}
            ).onSuccess { response ->
                tokenManager.saveId(response.id)
                _sideEffect.emit(InformationSideEffect.NavigateToHome)
-           }.onLogFailure {}
+           }.onLogFailure { 
+               _sideEffect.emit(InformationSideEffect.ShowError("프로필 저장에 실패했습니다. 다시 시도해주세요."))
+           }
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationViewModel.kt`
around lines 57 - 60, The empty onLogFailure block in
OnboardingInformationViewModel leaves API failures unhandled; update the
onLogFailure handler to emit a user-facing error side effect (use
_sideEffect.emit) with the failure message or a localized string and provide a
retry option (e.g., emit InformationSideEffect.ShowError or a new
ShowErrorWithRetry side effect), so failures after the tokenManager.saveId /
InformationSideEffect.NavigateToHome flow surface to the UI and allow retry.

Copy link
Copy Markdown
Contributor

@usuuhyn usuuhyn left a comment

Choose a reason for hiding this comment

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

수고하셧슴둥
3676ea1e25859cfd1cf10051bfbfced4

navigationBarStyle = SystemBarStyle.dark(Color.TRANSPARENT)
)

requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P999: 이게 아까 그 화면 방향 이슈 해결하려고 쓴 코드인 것? 이거 쓰면 화면이 안돌아가나용?
image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

넵넵!!

Copy link
Copy Markdown
Contributor

@nhyeonii nhyeonii left a comment

Choose a reason for hiding this comment

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

고생햇슈 !! 리뷰 확인 부탁드림니다잉 🫰🫰🫰🫰🫰🫰🫰🫰
image

Comment thread app/src/main/java/com/cherrish/android/presentation/main/MainScreen.kt Outdated
Copy link
Copy Markdown
Contributor

@nhyeonii nhyeonii left a comment

Choose a reason for hiding this comment

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

LGTM ~~
image

@sohee6989 sohee6989 merged commit dc7e9f7 into develop Jan 19, 2026
3 checks passed
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.

[FEAT] 정보입력 뷰 api 연결

3 participants