Skip to content

Commit 1dcbf42

Browse files
committed
[feat]: 회원 탈퇴시 FCM 토큰 삭제 및 디바이스 정보를 삭제하도록 수정 (#135)
1 parent f578aef commit 1dcbf42

File tree

1 file changed

+42
-18
lines changed

1 file changed

+42
-18
lines changed

app/src/main/java/com/texthip/thip/ui/mypage/viewmodel/DeleteAccountViewModel.kt

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
1616
import kotlinx.coroutines.flow.asStateFlow
1717
import kotlinx.coroutines.flow.update
1818
import kotlinx.coroutines.launch
19+
import kotlinx.coroutines.suspendCancellableCoroutine
20+
import kotlin.coroutines.resume
1921
import javax.inject.Inject
2022

2123
data 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

Comments
 (0)