Skip to content

[FIX/#153] 키보드 이슈 해결 #154

Merged
nhyeonii merged 5 commits intodevelopfrom
fix/#153-keyboard-bug
Jan 23, 2026
Merged

[FIX/#153] 키보드 이슈 해결 #154
nhyeonii merged 5 commits intodevelopfrom
fix/#153-keyboard-bug

Conversation

@hyeminililo
Copy link
Contributor

@hyeminililo hyeminililo commented Jan 22, 2026

Related issue 🛠

Work Description ✏️

  • 키보드 올라갔을 때 패딩이 잘 적용되지 않는 부분을 해결했습니다.

Screenshot 📸

Uncompleted Tasks 😅

N/A

To Reviewers 📢

한 번 봐주세요오 ,, 마지막이길

Summary by CodeRabbit

  • 버그 수정

    • 포커스된 입력 필드가 키보드에 가려지지 않고 자동으로 보이도록 개선
    • 스크롤·포커스 동작과 입력 반응성 최적화
  • 새로운 기능

    • 스크롤 가능한 레이아웃과 스티키 헤더로 화면 구조 개선
    • 입력 필드 포커스 이동 및 제스처 처리로 키보드 상호작용 향상
  • 리팩터/동작 변경

    • 시작 화면 흐름 단순화: 자동 홈 이동 경로 제거, 온보딩으로의 전환이 기본 동작으로 변경

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

@hyeminililo hyeminililo requested a review from a team as a code owner January 22, 2026 22:16
@hyeminililo hyeminililo linked an issue Jan 22, 2026 that may be closed by this pull request
@coderabbitai
Copy link

coderabbitai bot commented Jan 22, 2026

Walkthrough

온보딩 정보 화면을 Scaffold에서 LazyColumn 기반으로 재구성하여 IME/포커스/bring-into-view, 포인터/제스처 처리, sticky 헤더 및 액션 버튼 위치를 변경했습니다. 스플래시 관련으로는 TokenManager 및 navigateToHome 경로와 자동 로그인 분기 로직을 제거했습니다.

Changes

Cohort / File(s) 요약
온보딩 정보 화면 리팩토링
app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationScreen.kt
Scaffold 기반 레이아웃에서 LazyColumn으로 전환. BringIntoViewRequester, FocusRequester, 포인터 입력/제스처 처리, IME 인셋 애니메이션(animateDpAsState) 및 bring-into-view 로직 추가. 액션 버튼을 스크롤 외부로 이동. UserInfoTextFieldtextFieldModifier 인자 전달 가능하도록 수정. padding 및 레이아웃 스페이싱 조정.
온보딩 뷰모델 경량화
app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationViewModel.kt
생성자에서 TokenManager 제거 및 관련 saveId 호출 삭제(의존성 축소).
스플래시 네비게이션/뷰모델 단순화
app/src/main/java/com/cherrish/android/presentation/splash/SplashScreen.kt, app/src/main/java/com/cherrish/android/presentation/splash/SplashSideEffect.kt, app/src/main/java/com/cherrish/android/presentation/splash/SplashViewModel.kt, app/src/main/java/com/cherrish/android/presentation/splash/navigation/SplashNavigation.kt, app/src/main/java/com/cherrish/android/presentation/main/MainScreen.kt
navigateToHome 파라미터 및 SplashSideEffect.NavigateToHome 제거. SplashViewModel에서 TokenManager 제거, isAutoLoginCheck()navigateToOnboarding()로 변경하여 항상 온보딩으로 이동하도록 단순화. MainScreen에서 splashNavGraph 호출 시 홈 콜백 제거.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Screen as OnboardingInformationScreen
    participant Field as TextField (Name/Age)
    participant Bring as BringIntoViewRequester
    participant Layout as LazyColumn
    participant IME as IME/Keyboard

    User->>Field: 터치/클릭
    Field->>Screen: pointerInput 이벤트
    Screen->>Screen: FocusRequester.requestFocus()
    Screen->>Bring: bringIntoView()
    Bring->>Layout: 스크롤 요청
    Layout->>Layout: 대상 필드 노출
    Screen->>IME: 키보드 표시 요청
    IME->>Screen: WindowInsets.ime 값 제공
    Screen->>Screen: animateDpAsState로 bottom inset 적용
    Screen->>Layout: 하단 패딩/레이아웃 조정
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • sohee6989
  • usuuhyn
🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
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.
Out of Scope Changes check ❓ Inconclusive 대부분의 변경 사항은 키보드 이슈 해결과 직접 관련되어 있으나, TokenManager 제거는 연관성이 낮을 수 있습니다. TokenManager 제거가 키보드 이슈 해결과 필요한 관련성이 있는지 명확히 설명하면 좋겠습니다.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경 사항인 키보드 이슈 해결과 밀접하게 관련되어 있으며, 코드 변경 사항들이 키보드 인셋 처리, IME 패딩 조정, 레이아웃 개선 등을 포함하고 있습니다.
Description check ✅ Passed PR 설명이 필수 템플릿 섹션들을 포함하고 있으나, 스크린샷이 없고 작업 설명이 간략합니다.
Linked Issues check ✅ Passed 코드 변경 사항들이 키보드 인셋 처리, IME 패딩 동적 조정, 텍스트 필드 포커스 관리 등을 통해 #153의 키보드 패딩 이슈 해결 요구사항을 충족합니다.

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

@hyeminililo hyeminililo self-assigned this Jan 22, 2026
@hyeminililo hyeminililo added FIX🐛 오류 및 버그 수정 혜민🍒 혜민 담당 labels Jan 22, 2026
Copy link

@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/OnboardingInformationScreen.kt`:
- Around line 127-131: The root Column in OnboardingInformationScreen.kt is
missing application of the system padding; apply paddingValues to the Column
modifier first (i.e., include .padding(paddingValues) on the Column's modifier
before .fillMaxSize()/.background()) so window insets (status/nav bars) are
respected rather than only applying bottom inset to the button; update the
Column modifier where Column(...) is declared to use .padding(paddingValues)
then chain the existing .fillMaxSize() and .background().
🧹 Nitpick comments (1)
app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationScreen.kt (1)

122-125: IME 표시 시 버튼이 가려질 가능성 확인 필요
Line 122-125에서 IME가 뜨면 bottomInset을 0.dp로 만들고 있어 edge-to-edge 구성에서는 Line 231-240의 버튼이 키보드에 가려질 수 있습니다. 실제 설정에서 동작 확인 후 필요 시 IME 인셋을 반영하도록 조정해 주세요.

⚙️ 조정 예시
-    val targetBottomInset = if (imeBottomDp > 0.dp) 0.dp else paddingValues.calculateBottomPadding()
+    val targetBottomInset = maxOf(imeBottomDp, paddingValues.calculateBottomPadding())

Also applies to: 231-240

Comment on lines +127 to +131
Column(
modifier = modifier
.fillMaxSize()
.background(color = CherrishTheme.colors.gray0)
) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, locate and read the target file
cat -n app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationScreen.kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 15266


루트 Column에 paddingValues 적용 필수

현재 코드는 루트 Column에 .padding(paddingValues)를 적용하지 않고 있습니다. 대신 paddingValues에서 하단 패딩만 추출하여 버튼에만 적용되고 있어, 상태바와 내비게이션 바의 패딩이 제대로 처리되지 않을 수 있습니다. 루트 Column 수정자에 .padding(paddingValues)를 먼저 적용하세요.

✅ 적용 예시
     Column(
         modifier = modifier
             .fillMaxSize()
             .background(color = CherrishTheme.colors.gray0)
+            .padding(paddingValues)
     ) {
📝 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
Column(
modifier = modifier
.fillMaxSize()
.background(color = CherrishTheme.colors.gray0)
) {
Column(
modifier = modifier
.fillMaxSize()
.background(color = CherrishTheme.colors.gray0)
.padding(paddingValues)
) {
🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationScreen.kt`
around lines 127 - 131, The root Column in OnboardingInformationScreen.kt is
missing application of the system padding; apply paddingValues to the Column
modifier first (i.e., include .padding(paddingValues) on the Column's modifier
before .fillMaxSize()/.background()) so window insets (status/nav bars) are
respected rather than only applying bottom inset to the button; update the
Column modifier where Column(...) is declared to use .padding(paddingValues)
then chain the existing .fillMaxSize() and .background().

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

와웅 확인햇어요 !! 고생해사..ㅜㅜ

Copy link

@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 17-22: The onboarding response contains a user id that must be
persisted to TokenManager but the ViewModel currently never saves it; in
OnboardingInformationViewModel update the success handler inside onNextClicked()
(where onboardingProfileRepository is used) to call
tokenManager.saveId(response.id) after a successful response so AuthInterceptor
can later retrieve the id via tokenManager.getId(); ensure TokenManager is
injected/available in the ViewModel and invoke saveId with the response.id in
the success branch.
🧹 Nitpick comments (1)
app/src/main/java/com/cherrish/android/presentation/splash/SplashScreen.kt (1)

40-47: LaunchedEffect 내부에서 scope.launch 중첩은 불필요합니다.

LaunchedEffect는 이미 코루틴 스코프를 제공하므로 내부에서 delay와 함수 호출을 직접 수행할 수 있습니다. rememberCoroutineScope()는 이 경우 필요하지 않으며 제거 가능합니다.

♻️ 권장 수정안
-    val scope = rememberCoroutineScope()
-
-    LaunchedEffect (Unit) {
-        scope.launch {
-            delay(3000)
-            viewModel.navigateToOnboarding()
-        }
+    LaunchedEffect(Unit) {
+        delay(3000)
+        viewModel.navigateToOnboarding()
     }

Comment on lines 17 to 22
import javax.inject.Inject

@HiltViewModel
class OnboardingInformationViewModel @Inject constructor(
private val onboardingProfileRepository: OnboardingProfileRepository,
private val tokenManager: TokenManager
private val onboardingProfileRepository: OnboardingProfileRepository
) : ViewModel() {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for TokenManager usage and id-related methods
echo "=== TokenManager usage ==="
rg -n --type=kt '\bTokenManager\b' -C 2

echo -e "\n=== getId/saveId/userId patterns ==="
rg -n --type=kt '\bgetId\b|\bsaveId\b|\buserId\b' -C 2

echo -e "\n=== OnboardingInformationViewModel file ==="
cat -n app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationViewModel.kt | head -80

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 2850


🏁 Script executed:

#!/bin/bash
# Broader search for TokenManager
echo "=== TokenManager literal search ==="
rg -n 'TokenManager' -C 2

echo -e "\n=== getId/saveId patterns ==="
rg -n 'getId|saveId' -C 2

echo -e "\n=== usesId or userId patterns ==="
rg -n 'userId|user.*[Ii]d' -C 2 | head -100

echo -e "\n=== Check all kotlin files in onboarding package ==="
find app/src/main/java/com/cherrish/android/presentation/onboarding -name "*.kt" -type f

echo -e "\n=== Check OnboardingProfileRepository for id handling ==="
find app/src/main -name "*OnboardingProfileRepository*" -type f

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 18725


🏁 Script executed:

#!/bin/bash
echo "=== OnboardingProfileRepositoryImpl ==="
cat app/src/main/java/com/cherrish/android/data/repositoryimpl/OnboardingProfileRepositoryImpl.kt

echo -e "\n=== Check response DTO ==="
find app/src/main -name "*OnboardingProfile*ResponseDto*" -o -name "*OnboardingProfile*Response*" | head -20
fd OnboardingProfile app/src/main --type f -name "*.kt" | grep -i response

echo -e "\n=== Look for id in onboarding responses ==="
find app/src/main/java/com/cherrish/android/data/remote/dto -name "*.kt" | xargs grep -l "onboarding\|Onboarding" -i

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 1807


🏁 Script executed:

#!/bin/bash
echo "=== OnboardingProfileResponseDto ==="
cat app/src/main/java/com/cherrish/android/data/remote/dto/response/OnboardingProfileResponseDto.kt

echo -e "\n=== OnboardingProfileResponseModel ==="
cat app/src/main/java/com/cherrish/android/data/model/OnboardingProfileResponseModel.kt

echo -e "\n=== Check previous version in git history ==="
git log --oneline -n 20 -- app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationViewModel.kt

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 927


🏁 Script executed:

#!/bin/bash
echo "=== Check git diff for the onboarding file ==="
git show 5c302cc -- app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationViewModel.kt | head -150

echo -e "\n=== Also check if there are other places where saveId is called ==="
rg 'saveId' -C 3

Repository: TEAM-Cherrish/Cherrish-Android

Length of output: 4342


onboardingProfileRepository 응답에서 받은 사용자 idTokenManager에 저장해야 합니다.

응답 DTO에서 id를 수신하지만, 현재 코드에서는 이를 저장하지 않습니다. AuthInterceptor가 모든 API 요청에서 tokenManager.getId()를 호출하므로, id가 저장되지 않으면 이후 네트워크 요청이 실패하거나 사용자 정보 없이 진행됩니다.

onNextClicked()의 성공 핸들러에서 tokenManager.saveId(response.id)를 호출하세요.

🤖 Prompt for AI Agents
In
`@app/src/main/java/com/cherrish/android/presentation/onboarding/information/OnboardingInformationViewModel.kt`
around lines 17 - 22, The onboarding response contains a user id that must be
persisted to TokenManager but the ViewModel currently never saves it; in
OnboardingInformationViewModel update the success handler inside onNextClicked()
(where onboardingProfileRepository is used) to call
tokenManager.saveId(response.id) after a successful response so AuthInterceptor
can later retrieve the id via tokenManager.getId(); ensure TokenManager is
injected/available in the ViewModel and invoke saveId with the response.id in
the success branch.

Copy link

@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/splash/SplashScreen.kt`:
- Around line 40-47: Remove the unnecessary rememberCoroutineScope() and the
internal scope.launch inside the LaunchedEffect in SplashScreen; LaunchedEffect
already provides a coroutine scope and cancellation, so call delay(3000)
directly inside LaunchedEffect and then invoke viewModel.navigateToOnboarding(),
and delete references to scope and rememberCoroutineScope to ensure proper
cancellation when the composable leaves composition.

Comment on lines 40 to 47
val scope = rememberCoroutineScope()

LifecycleEventEffect(Lifecycle.Event.ON_START) {
LaunchedEffect(Unit) {
scope.launch {
delay(3000)
viewModel.isAutoLoginCheck()
viewModel.navigateToOnboarding()
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

LaunchedEffect 내부의 불필요한 scope.launch 제거 필요

LaunchedEffect는 이미 코루틴 스코프를 제공하므로, 내부에서 rememberCoroutineScope()를 통한 scope.launch는 불필요합니다. 또한 이 패턴은 컴포저블이 컴포지션을 벗어날 때 delay가 제대로 취소되지 않을 수 있습니다.

♻️ 수정 제안
-    val scope = rememberCoroutineScope()
-
-    LaunchedEffect(Unit) {
-        scope.launch {
-            delay(3000)
-            viewModel.navigateToOnboarding()
-        }
-    }
+    LaunchedEffect(Unit) {
+        delay(3000)
+        viewModel.navigateToOnboarding()
+    }
📝 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
val scope = rememberCoroutineScope()
LifecycleEventEffect(Lifecycle.Event.ON_START) {
LaunchedEffect(Unit) {
scope.launch {
delay(3000)
viewModel.isAutoLoginCheck()
viewModel.navigateToOnboarding()
}
}
LaunchedEffect(Unit) {
delay(3000)
viewModel.navigateToOnboarding()
}
🤖 Prompt for AI Agents
In `@app/src/main/java/com/cherrish/android/presentation/splash/SplashScreen.kt`
around lines 40 - 47, Remove the unnecessary rememberCoroutineScope() and the
internal scope.launch inside the LaunchedEffect in SplashScreen; LaunchedEffect
already provides a coroutine scope and cancellation, so call delay(3000)
directly inside LaunchedEffect and then invoke viewModel.navigateToOnboarding(),
and delete references to scope and rememberCoroutineScope to ensure proper
cancellation when the composable leaves composition.

@nhyeonii nhyeonii merged commit c08fd20 into develop Jan 23, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FIX🐛 오류 및 버그 수정 혜민🍒 혜민 담당

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FIX] 키보드 이슈 해결

3 participants