강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

김성일님의 프로필 이미지
김성일

작성한 질문수

[LV3] Jetpack Compose - 그럴 듯한 다이어트 앱 만들기

Firebase Error message Flow 관련

작성

·

83

0

안녕하세요, 강의 잘 듣고 있습니다.

Jetpack Compose View 강의를 수강하면서 궁금한 점이 생겨 질문드립니다.

강사님께서는 Error Message를 Flow로 collect하여 View에 전달하는 방식을 사용하셨는데,
아래와 같은 상황에서는 에러 메시지가 출력되지 않는 문제가 발생합니다.

  • 사용자가 이메일 혹은 비밀번호 검증에 실패합니다.

  • Firebase에서 "비밀번호 혹은 아이디가 틀렸습니다"라는 에러 메시지를 반환하고, Flow가 이를 collect하여 화면에 출력합니다.

  • 사용자가 이메일 또는 비밀번호를 수정한 후 다시 로그인 요청을 보냅니다.

  • 검증이 다시 실패하여 Firebase에서 동일한 에러 메시지를 반환합니다.

  • 하지만 Flow는 같은 값을 연속으로 emit하지 않기 때문에 View에서는 변경을 감지하지 못하고 에러 메시지가 출력되지 않습니다.

  • 사용자는 아무런 메세지가 없어 무슨 상황인지 모른다

이걸 해결하기 위해 errorMessage의 Flow의 값을 null 처리 해도 똑같습니다.

해당 문제를 해결할수 있는 방법이 있을까요?

전 비록 Text을 쓰지 않고 SnackBar을 썼지만 저의 코드를 봐주시면 감사하겠습니다.

viewModel : https://github.com/sonny8569/DietJetpackCompose/blob/main/app/src/main/java/com/sungil/jetpackcomposediet/ui/intro/IntroViewModel.kt

 

Activity:

https://github.com/sonny8569/DietJetpackCompose/blob/main/app/src/main/java/com/sungil/jetpackcomposediet/ui/intro/IntroActivity.kt

 

view :

https://github.com/sonny8569/DietJetpackCompose/blob/main/app/src/main/java/com/sungil/jetpackcomposediet/ui/intro/screen/LoginScreen.kt

답변 2

0

개복치개발자님의 프로필 이미지
개복치개발자
지식공유자

안녕하세요

굉장히 좋은 질문입니다.

 

사실 이런 로그인 상황에서는 무한정 로그인을 시도할 수 없게

서버단에서 메세지를 받아서 처리해줄 때가 있습니다.

 

result message에 "로그인 1회 (5회 틀리면 계정 정지)"

 

이런식입니다

 

서버단에서 저런 메세지를 조작하지 않는 클라이언트에서는 아래와 같이 viewModel에서 n회 카운트를 추가해주면

 

errorState가 변경되는 것을 보실 수 있습니다.

 

아래와 같이 코드를 변경하는 것이 더 바람직해 보이네요

좋은 질문 감사합니다!

 

class IntroViewModel : ViewModel() {
    private val auth: FirebaseAuth = FirebaseAuth.getInstance()

    private val _authState = MutableStateFlow<FirebaseUser?>(auth.currentUser)
    val authState: StateFlow<FirebaseUser?> = _authState

    private val _errorState = MutableStateFlow<String?>(null)
    val errorState: StateFlow<String?> = _errorState

    private var signUpFailCount = 0
    private var loginFailCount = 0

    //회원가입
    fun singUp(email: String, password: String) {
        viewModelScope.launch(Dispatchers.IO) {
            auth.createUserWithEmailAndPassword(email, password).addOnCompleteListener { task ->


                if (task.isSuccessful) {
                    _authState.value = auth.currentUser
                    return@addOnCompleteListener
                }
                signUpFailCount += 1
                _errorState.value = "실패 ${signUpFailCount}회 ${task.exception?.message}"

            }
        }
    }


    //로그인
    fun login(email: String, password: String) {
        viewModelScope.launch(Dispatchers.IO) {
            auth.signInWithEmailAndPassword(email, password).addOnCompleteListener { task ->


                if (task.isSuccessful) {
                    _authState.value = auth.currentUser
                    return@addOnCompleteListener
                }
                loginFailCount += 1
                _errorState.value = "실패 ${loginFailCount}회 ${task.exception?.message}"
            }
        }
    }
}

0

안녕하세요, 인프런 AI 인턴입니다.

김성일 님의 문제는 Flow를 사용하면서 동일한 에러 메시지를 연속적으로 전송하지 않기 때문에 발생한 것으로 보입니다. Flow는 기본적으로 같은 값을 연속해서 emit하지 않기 때문에, 같은 메세지가 다시 emit될 때 변화로 인식하지 않아 UI 변경이 반영되지 않습니다.

이 문제를 해결하기 위해서는 몇 가지 접근법을 고려해볼 수 있습니다:

  1. StateFlow 사용하기: StateFlow는 상태를 저장하고, UI에서 지속적으로 상태를 관찰할 수 있도록 해줍니다. StateFlow를 사용해 error state를 관리하면, 상태 변화에 따라 UI가 정확하게 업데이트 될 수 있습니다. errorMessage를 null로 설정해서 상태를 초기화 해주는 방식을 사용할 수도 있습니다.

  2. Error Message를 새로운 객체로 래핑하기: 같은 문자열이라도 다른 객체로 인식되도록 래핑할 수 있습니다. 매번 새로운 객체로 에러 메시지를 emit하면, Flow는 이를 변화를 감지하여 UI에 반영할 수 있습니다.

  3. Snackbar의 key 속성 사용하기: 만약 UI에서 Snackbar를 사용 중이라면, key 속성을 활용하여 매번 다른 snackbar를 표시하도록 제어할 수 있습니다.

유사한 문제를 겪으신 많은 분들이 이러한 접근으로 해결하신 것으로 알고 있습니다. 아래 링크들을 추가적으로 참고하시면 도움이 될 것입니다:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

김성일님의 프로필 이미지
김성일

작성한 질문수

질문하기