@@ -16,6 +16,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
1616import kotlinx.coroutines.flow.asStateFlow
1717import kotlinx.coroutines.flow.update
1818import kotlinx.coroutines.launch
19+ import kotlinx.coroutines.suspendCancellableCoroutine
20+ import kotlin.coroutines.resume
1921import javax.inject.Inject
2022
2123data class DeleteAccountUiState (
@@ -37,53 +39,75 @@ class DeleteAccountViewModel @Inject constructor(
3739 fun deleteAccount (context : Context ) {
3840 viewModelScope.launch {
3941 _uiState .update { it.copy(isLoading = true , errorMessage = null ) }
40-
41- try {
42+
43+ runCatching {
44+ // 1. FCM 토큰 삭제 (실패해도 계속 진행)
4245 notificationRepository.deleteFcmToken()
4346 .onFailure { exception ->
4447 Log .w(" DeleteAccountViewModel" , " FCM 토큰 삭제 실패 (계속 진행)" , exception)
4548 }
4649
50+ // 2. 회원 탈퇴 요청
4751 userRepository.deleteAccount()
4852 .onSuccess {
53+ // 3. 로컬 데이터 정리 (동기화 보장)
4954 performLocalDataCleanup(context)
5055
5156 _uiState .update { it.copy(isLoading = false , isDeleteCompleted = true ) }
5257 }
5358 .onFailure { exception ->
59+ Log .e(" DeleteAccountViewModel" , " 서버 회원탈퇴 요청 실패" , exception)
5460 throw exception
5561 }
56- } catch ( exception: Exception ) {
62+ }.onFailure { exception ->
5763 Log .e(" DeleteAccountViewModel" , " 회원탈퇴 실패" , exception)
58- _uiState .update {
64+ _uiState .update {
5965 it.copy(
60- isLoading = false ,
66+ isLoading = false ,
6167 errorMessage = exception.message ? : " 회원탈퇴에 실패했습니다."
62- )
68+ )
6369 }
6470 }
6571 }
6672 }
67-
73+
6874 private suspend fun performLocalDataCleanup (context : Context ) {
69- try {
75+ runCatching {
76+ // 1. 토큰과 디바이스 데이터 정리
7077 tokenManager.clearTokens()
7178 context.clearAppScopeDeviceData()
7279
73- UserApiClient .instance.unlink { error ->
74- if (error != null ) {
75- Log .e(" DeleteAccountViewModel" , " 카카오 연결 끊기 실패" , error)
76- } else {
77- Log .d(" DeleteAccountViewModel" , " 카카오 연결 끊기 성공" )
78- }
80+ // 2. 카카오 SDK 연결 끊기 (동기화 보장)
81+ runCatching {
82+ unlinkKakaoAccount()
83+ Log .d(" DeleteAccountViewModel" , " 카카오 연결 끊기 성공" )
84+ }.onFailure { e ->
85+ Log .e(" DeleteAccountViewModel" , " 카카오 연결 끊기 실패" , e)
86+ }
87+
88+ // 3. 구글 SDK 로그아웃
89+ runCatching {
90+ val gso = GoogleSignInOptions .Builder (GoogleSignInOptions .DEFAULT_SIGN_IN ).build()
91+ GoogleSignIn .getClient(context, gso).signOut()
92+ Log .d(" DeleteAccountViewModel" , " 구글 로그아웃 성공" )
93+ }.onFailure { e ->
94+ Log .e(" DeleteAccountViewModel" , " 구글 로그아웃 실패" , e)
7995 }
8096
81- val gso = GoogleSignInOptions .Builder (GoogleSignInOptions .DEFAULT_SIGN_IN ).build()
82- GoogleSignIn .getClient(context, gso).signOut()
83-
8497 Log .i(" DeleteAccountViewModel" , " 로컬 데이터 정리 완료" )
85- } catch (e : Exception ) {
98+ }.onFailure { e ->
8699 Log .e(" DeleteAccountViewModel" , " 로컬 데이터 정리 중 오류" , e)
87100 }
88101 }
102+
103+ private suspend fun unlinkKakaoAccount () = suspendCancellableCoroutine<Unit > { continuation ->
104+ UserApiClient .instance.unlink { error ->
105+ if (error != null ) {
106+ continuation.resume(Unit ) // 실패해도 정상적으로 완료 처리
107+ Log .w(" DeleteAccountViewModel" , " 카카오 연결 해제 실패하지만 계속 진행" , error)
108+ } else {
109+ continuation.resume(Unit )
110+ }
111+ }
112+ }
89113}
0 commit comments