도리안의 2025년 개발기 #106 - Room 데이터 업데이트 직후 UI 작동 오류 (팝업 A, B가 연달아 뜸)
Room 데이터 업데이트 직후 UI 작동 오류 (팝업 A, B가 연달아 뜸)
No. 106
2025. 06. 11 (수) | Written by @dorian-dev
개발 환경
- OS: Android
- 사용 기술: Jetpack Compose, ViewModel, Room
오늘의 개발기
아래와 같이 객관식 퀴즈에 대답하는 answer 함수 그리고 특정일의 문제를 모두 맞췄는지를 뜻하는 플래그를 저장하는 setDayCompleted 함수를 정의했다고 가정한다. 함수 내부에서는 데이터를 저장하거나 읽기 위해 Room 데이터베이스가 사용된다.
val currentDay = 1
fun answer(day: Int, quizNo: Int, choiceNo: Int) = viewModelScope.launch(Dispatchers.IO) {
// 사용자 응답 저장
}
fun setDayCompleted(day: Int, isCompleted: Boolean) = viewModelScope.launch(Dispatchers.IO) {
// 특정 날짜의 퀴즈 완료 여부 저장
}
fun getDayCompleted(day: Int): Flow<Boolean> {
// 특정 날짜의 완료 여부 구독
}
val isCurrentDayCompleted: Flow<Boolean> = getDayCompleted(currentDay).stateIn(
scope = viewModelScope,
initialValue = false,
started = SharingStarted.WhileSubscribed(5000)
)
문제 상황
(1) 사용자가 퀴즈에 대답할 때 answer 함수가 호출됨
(2) 마지막 퀴즈 대답 후, setDayCompleted(day, true) 함수가 호출되어 완료 상태 저장
(3) 이후 isCurrentDayCompleted 값을 기준으로 팝업을 띄움
(4) 문제: OpenPopUp 컴포저블 함수를 호출하면, 팝업 A와 B가 연달아 보임
@Composable
fun OpenPopUp(day: Int, viewModel: MyViewModel) {
val isDayCompleted by viewModel.getDayCompleted(day).collectAsState()
if (isDayCompleted) {
// 팝업 A 열기
} else {
// 팝업 B 열기
}
}
원인 분석
- answer, setDayCompleted 함수들은 별도의 viewModelScope.launch()로 실행되기 때문에 비동기로 작동
- UI가 getDayCompleted()를 구독할 때, 아직 완료 여부가 저장되지 않았을 수도 있음
- 이로 인해 isDayCompleted 값이 false로 잠시 보인 후 true로 갱신되며, 두 팝업이 연속 표시되는 문제가 발생한 것이다.
해결
- 비동기로 실행되는 함수들이라도 동일 코루틴 스코프 안에서는 실행 순서가 보장됨
- viewModelScope.launch 함수의 코드 블록 안에서도 그러함
- setDayCompleted 함수를 answer 함수 안에 호출하는 것으로 해결
fun answer(day: Int, quizNo: Int, choiceNo: Int) = viewModelScope.launch(Dispatchers.IO) {
// ...
if (allUserAnswerOfDayAreCorrect) {
setDayCompleted(day, true)
}
}
정리
- Room 데이터베이스를 사용하는 함수는 비동기적으로 동작하므로, 순서를 보장하지 않음
- 비동기 실행 함수의 순서 보장: 동일한 Coroutine 블록 내에서 순차적으로 호출
- 상태를 UI에서 안전하게 반영하려면 Flow로 구독하고, 데이터 업데이트는 단일 코루틴 스코프에서 처리하는 것이 좋다.
지난 2025년 개발기
- #105 - 미래에 대한 기대와 걱정
- #104 - Room으로 데이터 읽기는 즉시 반환 함수보다 Flow 권장
- #103 - 매주 금요일 저녁에는 '한주 동안 내가 한 일'을 기록하며 회고
- #102 - Jetpack Compose로 클릭 처리시, 팝업이 잠시 보이고 다시 사라지는 문제
- #101 - 홈 화면에서 진도율이 0%만 뜨는 버그를 수정하며 배운 점
- #1 ~ #100
Layout provided by Steemit Enhancer hommage by ayogom
Posted through the ECblog app (https://blog.etain.club)
안녕하세요.
SteemitKorea팀에서 제공하는 'steemit-enhancer'를 사용해 주셔서 감사합니다. 개선 사항이 있으면 언제나 저에게 연락을 주시면 되고, 관심이 있으신 분들은 https://cafe.naver.com/steemitkorea/425 에서 받아보실 수 있습니다. 사용시 @응원해 가 포함이 되며, 악용시에는 모든 서비스에서 제외될 수 있음을 알려드립니다.
안녕하세요.
이 글은 SteemitKorea팀(@ayogom)님께서 저자이신 @dorian-dev님을 응원하는 글입니다.
소정의 보팅을 해드렸습니다 ^^ 항상 좋은글 부탁드립니다
SteemitKorea팀에서는 보다 즐거운 steemit 생활을 위해 노력하고 있습니다.
이 글은 다음날 다시 한번 포스팅을 통해 소개 될 예정입니다. 감사합니다!