From 6096da840d3026c664a7c9cf173614633baee130 Mon Sep 17 00:00:00 2001 From: Moony-H <53536205+Moony-H@users.noreply.github.com> Date: Sat, 22 Aug 2026 12:25:58 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=EC=98=A8=EB=B3=B4=EB=94=A9=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=ED=99=94=EB=A9=B4=20=EB=A1=9C=EC=A7=81=20=EB=B0=8F?= =?UTF-8?q?=20=EA=B6=8C=ED=95=9C=20=EC=9A=94=EC=B2=AD=20=ED=9D=90=EB=A6=84?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kikidan/onboarding/OnboardingRoute.kt | 25 +++++++------------ .../kikidan/onboarding/OnboardingViewModel.kt | 12 ++++++--- .../onboarding/screen/CompleteScreen.kt | 10 +++++--- .../onboarding/OnboardingViewModelTest.kt | 19 ++++++++++---- 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt b/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt index db38745a..1e7e2977 100644 --- a/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt +++ b/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt @@ -10,7 +10,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -42,15 +41,12 @@ fun OnboardingRoute( viewModel: OnboardingViewModel = hiltViewModel(), ) { val state by viewModel.collectAsState() - var permissionHandled by rememberSaveable { - mutableStateOf(Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) - } val permissionLauncher = rememberLauncherForActivityResult( contract = ActivityResultContracts.RequestPermission(), ) { - // 권한을 허락하지 않더라도 앱 진입 - permissionHandled = true + // 권한을 허락하지 않더라도 회원가입 진행 + viewModel.confirmComplete(onboardingToken) } val signupErrorMessage = stringResource(R.string.onboarding_signup_error) val invalidInputErrorMessage = stringResource(R.string.onboarding_invalid_input_error) @@ -69,7 +65,7 @@ fun OnboardingRoute( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) } else { - onFinish() + viewModel.confirmComplete(onboardingToken) } } @@ -127,21 +123,18 @@ fun OnboardingRoute( canProceed = state.canProceed, onLifeStageSelect = viewModel::selectLifeStage, onRelationshipStatusSelect = viewModel::selectRelationshipStatus, - onNextClick = { - viewModel.confirmComplete(onboardingToken) - }, + onNextClick = viewModel::clickComplete, onBackClick = viewModel::clickBack, modifier = modifier, ) } OnboardingStep.COMPLETE -> { - if (permissionHandled) { - CompleteScreen( - onFinish = onFinish, - modifier = modifier, - ) - } + CompleteScreen( + isLoading = state.isSubmitting, + onFinish = onFinish, + modifier = modifier, + ) } } diff --git a/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingViewModel.kt b/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingViewModel.kt index 2322b041..c181e7c5 100644 --- a/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingViewModel.kt +++ b/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingViewModel.kt @@ -46,6 +46,11 @@ class OnboardingViewModel } } + fun clickComplete() = + intent { + postSideEffect(OnboardingSideEffect.PermissionRequest) + } + fun confirmComplete(onboardingToken: OnboardingToken) = intent { if (state.isSubmitting) return@intent @@ -54,15 +59,14 @@ class OnboardingViewModel postSideEffect(OnboardingSideEffect.InvalidInput) return@intent } - reduce { state.copy(isSubmitting = true) } + reduce { state.copy(isSubmitting = true, step = OnboardingStep.COMPLETE) } signUpUseCase( signupSubmission = signupSubmission, onboardingToken = onboardingToken, ).onSuccess { - reduce { state.copy(isSubmitting = false, step = OnboardingStep.COMPLETE) } - postSideEffect(OnboardingSideEffect.PermissionRequest) - }.onFailure { e -> reduce { state.copy(isSubmitting = false) } + }.onFailure { e -> + reduce { state.copy(isSubmitting = false, step = OnboardingStep.EXTRA_QUESTION) } postSideEffect(OnboardingSideEffect.Failure(e)) } } diff --git a/feature/onboarding/src/main/java/com/kikidan/onboarding/screen/CompleteScreen.kt b/feature/onboarding/src/main/java/com/kikidan/onboarding/screen/CompleteScreen.kt index 6e0d6606..0718e974 100644 --- a/feature/onboarding/src/main/java/com/kikidan/onboarding/screen/CompleteScreen.kt +++ b/feature/onboarding/src/main/java/com/kikidan/onboarding/screen/CompleteScreen.kt @@ -31,13 +31,16 @@ import kotlinx.coroutines.delay @Composable internal fun CompleteScreen( + isLoading: Boolean, onFinish: () -> Unit, modifier: Modifier = Modifier, ) { val currentOnFinish by rememberUpdatedState(onFinish) - LaunchedEffect(Unit) { - delay(3000) - currentOnFinish() + LaunchedEffect(isLoading) { + if (!isLoading) { + delay(3000L) + currentOnFinish() + } } Box( modifier = @@ -83,6 +86,7 @@ internal fun CompleteScreen( private fun CompleteScreenPreview() { TodakunTheme { CompleteScreen( + isLoading = false, onFinish = {}, ) } diff --git a/feature/onboarding/src/test/java/com/kikidan/onboarding/OnboardingViewModelTest.kt b/feature/onboarding/src/test/java/com/kikidan/onboarding/OnboardingViewModelTest.kt index 9afbe18d..cfeb6fa3 100644 --- a/feature/onboarding/src/test/java/com/kikidan/onboarding/OnboardingViewModelTest.kt +++ b/feature/onboarding/src/test/java/com/kikidan/onboarding/OnboardingViewModelTest.kt @@ -134,7 +134,17 @@ class OnboardingViewModelTest { } @Test - fun `마지막 스텝에서 다음을 누르면 완료 화면으로 전환된다`() = + fun `완료 단계에서 다음을 누르면 권한 요청 사이드이펙트가 먼저 전달된다`() = + runTest { + val initial = OnboardingState(step = OnboardingStep.EXTRA_QUESTION) + viewModel().test(this, initialState = initial) { + containerHost.clickComplete() + expectSideEffect(OnboardingSideEffect.PermissionRequest) + } + } + + @Test + fun `가입 요청을 시작하면 응답을 기다리는 동안 완료 화면으로 전환된다`() = runTest { val initial = OnboardingState( @@ -149,9 +159,8 @@ class OnboardingViewModelTest { ) viewModel().test(this, initialState = initial) { containerHost.confirmComplete(onboardingToken) - expectState { copy(isSubmitting = true) } + expectState { copy(isSubmitting = true, step = OnboardingStep.COMPLETE) } expectState { copy(isSubmitting = false, step = OnboardingStep.COMPLETE) } - expectSideEffect(OnboardingSideEffect.PermissionRequest) } } @@ -195,8 +204,8 @@ class OnboardingViewModelTest { ) viewModel().test(this, initialState = initial) { containerHost.confirmComplete(onboardingToken) - expectState { copy(isSubmitting = true) } - expectState { copy(isSubmitting = false) } + expectState { copy(isSubmitting = true, step = OnboardingStep.COMPLETE) } + expectState { copy(isSubmitting = false, step = OnboardingStep.EXTRA_QUESTION) } expectSideEffect(OnboardingSideEffect.Failure(error)) } } From 6313a2b5f943249bc2b0c51063edabe4fd1b2e39 Mon Sep 17 00:00:00 2001 From: oungsi2000 Date: Sat, 22 Aug 2026 12:49:37 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20=EB=84=A4=ED=8A=B8=EC=9B=8C?= =?UTF-8?q?=ED=81=AC=20=ED=83=80=EC=9E=84=EC=95=84=EC=9B=83(HttpTimeout)?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=EC=8B=9C=EA=B0=84=20=EC=83=81=ED=96=A5?= =?UTF-8?q?=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 네트워크 요청의 안정성을 확보하기 위해 `HttpTimeout`의 주요 설정 값을 기존 10~15초에서 100초로 일괄 상향 조정합니다. - `requestTimeoutMillis`: 15,000ms -> 100,000ms - `connectTimeoutMillis`: 10,000ms -> 100,000ms - `socketTimeoutMillis`: 15,000ms -> 100,000ms --- .../java/com/kikidan/data_remote/di/NetworkExtension.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/data-remote/src/main/java/com/kikidan/data_remote/di/NetworkExtension.kt b/core/data-remote/src/main/java/com/kikidan/data_remote/di/NetworkExtension.kt index 73d3773b..98e1951e 100644 --- a/core/data-remote/src/main/java/com/kikidan/data_remote/di/NetworkExtension.kt +++ b/core/data-remote/src/main/java/com/kikidan/data_remote/di/NetworkExtension.kt @@ -23,9 +23,9 @@ internal fun HttpClientConfig<*>.installTodakunDefaults( json(json) } install(HttpTimeout) { - requestTimeoutMillis = 15_000 - connectTimeoutMillis = 10_000 - socketTimeoutMillis = 15_000 + requestTimeoutMillis = 100_000 + connectTimeoutMillis = 100_000 + socketTimeoutMillis = 100_000 } install(DefaultRequest) { url(baseUrl) From 4ff92e47e7066415e3f1e4f254264e679aa204ec Mon Sep 17 00:00:00 2001 From: oungsi2000 Date: Sat, 22 Aug 2026 13:31:18 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=EC=98=A8=EB=B3=B4=EB=94=A9=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=20=ED=99=94=EB=A9=B4=20=EB=A1=9C=EB=94=A9=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EC=B2=98=EB=A6=AC=20=EB=B0=A9=EC=8B=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EC=BD=94=EB=93=9C=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 온보딩 최종 제출 상태를 관리하는 `OnboardingSubmitState`를 UI 레이어에 일관되게 적용하고, 불필요한 코드를 정리합니다. - `OnboardingRoute`: `CompleteScreen`의 `isLoading` 인자를 기존 `state.isSubmitting` 대신 `state.submitState`가 `Loading` 상태인지 확인하는 로직으로 변경 - `OnboardingViewModel`: 중복으로 포함된 `OnboardingSubmitState` 임포트 구문 제거 --- .../src/main/java/com/kikidan/onboarding/OnboardingRoute.kt | 2 +- .../src/main/java/com/kikidan/onboarding/OnboardingViewModel.kt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt b/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt index 5c398ed9..9ca2d50c 100644 --- a/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt +++ b/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingRoute.kt @@ -133,7 +133,7 @@ fun OnboardingRoute( OnboardingStep.COMPLETE -> { CompleteScreen( - isLoading = state.isSubmitting, + isLoading = state.submitState is OnboardingSubmitState.Loading, onFinish = onFinish, modifier = modifier, ) diff --git a/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingViewModel.kt b/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingViewModel.kt index 6cdfb20e..5281937c 100644 --- a/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingViewModel.kt +++ b/feature/onboarding/src/main/java/com/kikidan/onboarding/OnboardingViewModel.kt @@ -14,7 +14,6 @@ import com.kikidan.onboarding.model.OnboardingSideEffect import com.kikidan.onboarding.model.OnboardingState import com.kikidan.onboarding.model.OnboardingStep import com.kikidan.onboarding.model.OnboardingSubmitState -import com.kikidan.onboarding.model.OnboardingSubmitState import com.kikidan.onboarding.model.toDomain import dagger.hilt.android.lifecycle.HiltViewModel import org.orbitmvi.orbit.ContainerHost