diff --git a/challenge/presentation/src/main/kotlin/com/ruleup/challenge/presentation/detail/viewmodel/ChallengeDetailViewModel.kt b/challenge/presentation/src/main/kotlin/com/ruleup/challenge/presentation/detail/viewmodel/ChallengeDetailViewModel.kt index 4fd52f48..8476f14a 100644 --- a/challenge/presentation/src/main/kotlin/com/ruleup/challenge/presentation/detail/viewmodel/ChallengeDetailViewModel.kt +++ b/challenge/presentation/src/main/kotlin/com/ruleup/challenge/presentation/detail/viewmodel/ChallengeDetailViewModel.kt @@ -49,6 +49,8 @@ import com.ruleup.verification.domain.repository.VerificationRepository import com.ruleup.verification.domain.usecase.AgreeVerificationConsentUseCase import com.ruleup.verification.domain.usecase.CheckVerificationAccessUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import java.io.IOException import java.time.YearMonth @@ -484,14 +486,20 @@ class ChallengeDetailViewModel dispatch(ChallengeDetailReducerEvent.Loading(challengeId)) runCatching { challengeRepository.getChallenge(challengeId) } .onSuccess { detail -> - // 셋업 요구사항은 실패해도(미구현/멤버 아님 등) 상세 렌더를 막지 않도록 흡수한다. - val setup = runCatching { challengeRepository.getSetupInfo(challengeId) }.getOrNull() - // 그룹 멤버는 방을 먼저 받아 둔다 — 상세만 먼저 그리면 참여 전 화면이 잠깐 떴다가 방 화면으로 바뀐다. - val prefetchedRoom = - if (detail.mode.isGroup && detail.myRole.isMember) { - runCatching { roomRepository.getRoom(challengeId) }.getOrNull() - } else { - null + val (setup, prefetchedRoom) = + coroutineScope { + // 셋업 요구사항은 실패해도(미구현/멤버 아님 등) 상세 렌더를 막지 않도록 흡수한다. + val setup = async { runCatching { challengeRepository.getSetupInfo(challengeId) }.getOrNull() } + // 그룹 멤버는 방을 먼저 받아 둔다 — 상세만 먼저 그리면 참여 전 화면이 잠깐 떴다가 방 화면으로 바뀐다. + val room = + async { + if (detail.mode.isGroup && detail.myRole.isMember) { + runCatching { roomRepository.getRoom(challengeId) }.getOrNull() + } else { + null + } + } + setup.await() to room.await() } dispatch( ChallengeDetailReducerEvent.Loaded( diff --git a/challenge/presentation/src/main/kotlin/com/ruleup/challenge/presentation/settings/viewmodel/ChallengeSettingsViewModel.kt b/challenge/presentation/src/main/kotlin/com/ruleup/challenge/presentation/settings/viewmodel/ChallengeSettingsViewModel.kt index 3a7f5ee4..045a92e6 100644 --- a/challenge/presentation/src/main/kotlin/com/ruleup/challenge/presentation/settings/viewmodel/ChallengeSettingsViewModel.kt +++ b/challenge/presentation/src/main/kotlin/com/ruleup/challenge/presentation/settings/viewmodel/ChallengeSettingsViewModel.kt @@ -14,6 +14,8 @@ import com.ruleup.domain.helper.NavigationHelper import com.ruleup.ui.error.userFacingMessage import com.ruleup.ui.mvi.MviViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import javax.inject.Inject @@ -239,15 +241,18 @@ class ChallengeSettingsViewModel ) { viewModelScope.launch { dispatch(ChallengeSettingsReducerEvent.Loading(challengeId)) - runCatching { challengeRepository.getSettings(challengeId) } - .onSuccess { settings -> - // 정원 하한 계산에 현재 인원이 필요한데 settings 응답에 없다. + runCatching { + coroutineScope { + // 정원 하한 계산에 현재 인원이 필요한데 settings 응답에 없다. 인원 조회 실패는 흡수한다. val participants = - runCatching { challengeRepository.getChallenge(challengeId).participantCount }.getOrNull() - dispatch(ChallengeSettingsReducerEvent.Loaded(settings, participants, preserveEdits)) - }.onFailure { - dispatch(ChallengeSettingsReducerEvent.Failed(it.userFacingMessage("설정을 불러오지 못했어요"))) + async { runCatching { challengeRepository.getChallenge(challengeId).participantCount }.getOrNull() } + challengeRepository.getSettings(challengeId) to participants.await() } + }.onSuccess { (settings, participants) -> + dispatch(ChallengeSettingsReducerEvent.Loaded(settings, participants, preserveEdits)) + }.onFailure { + dispatch(ChallengeSettingsReducerEvent.Failed(it.userFacingMessage("설정을 불러오지 못했어요"))) + } } }