-
Notifications
You must be signed in to change notification settings - Fork 3
[Feat] users 남은 api 연동 #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9be6818
3de2c8a
74c2074
fda6aa1
4098c6d
5bb468d
65d5f72
c797935
d116345
767ea08
1f1e2c1
33cde28
2f548b1
ad4bafc
ce0d299
46a8b35
a8efc5b
e318580
208818c
f961f96
7a4d646
a2884ff
0e74ef5
8592b8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| package com.texthip.thip.data.manager | ||
|
|
||
| import android.content.Context | ||
| import androidx.datastore.core.DataStore | ||
| import androidx.datastore.preferences.core.Preferences | ||
| import androidx.datastore.preferences.core.edit | ||
| import androidx.datastore.preferences.core.stringPreferencesKey | ||
| import androidx.datastore.preferences.preferencesDataStore | ||
| import dagger.hilt.android.qualifiers.ApplicationContext | ||
| import kotlinx.coroutines.flow.first | ||
| import kotlinx.coroutines.flow.map | ||
| import javax.inject.Inject | ||
| import javax.inject.Singleton | ||
|
|
||
|
|
||
| private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "thip_tokens") | ||
|
|
||
| @Singleton | ||
| class TokenManager @Inject constructor( | ||
| @ApplicationContext private val context: Context | ||
| ) { | ||
| // 저장할 데이터의 Key 정의 | ||
| companion object { | ||
| private val TEMP_TOKEN_KEY = stringPreferencesKey("temp_token") | ||
| private val ACCESS_TOKEN_KEY = stringPreferencesKey("access_token") | ||
| private val REFRESH_TOKEN_KEY = stringPreferencesKey("refresh_token") | ||
| } | ||
|
|
||
| // 임시 토큰 저장 | ||
| suspend fun saveTempToken(token: String) { | ||
| context.dataStore.edit { prefs -> | ||
| prefs[TEMP_TOKEN_KEY] = token | ||
| } | ||
| } | ||
|
|
||
| // 임시 토큰 읽기 | ||
| suspend fun getTempToken(): String? { | ||
| return context.dataStore.data.map { prefs -> | ||
| prefs[TEMP_TOKEN_KEY] | ||
| }.first() // Flow에서 첫 번째 값을 한번만 읽어옴 | ||
| } | ||
|
|
||
| // 정식 토큰들(Access, Refresh) 저장 | ||
| suspend fun saveAccessTokens(accessToken: String, refreshToken: String) { | ||
| context.dataStore.edit { prefs -> | ||
| prefs[ACCESS_TOKEN_KEY] = accessToken | ||
| prefs[REFRESH_TOKEN_KEY] = refreshToken | ||
| } | ||
| } | ||
|
|
||
| // Access Token 읽기 (Flow로 제공하여 토큰 변화를 감지할 수 있게 함) | ||
| fun getAccessToken(): kotlinx.coroutines.flow.Flow<String?> { | ||
| return context.dataStore.data.map { prefs -> | ||
| prefs[ACCESS_TOKEN_KEY] | ||
| } | ||
| } | ||
|
|
||
| // 모든 토큰 삭제 (로그아웃 시) | ||
| suspend fun clearTokens() { | ||
| context.dataStore.edit { prefs -> | ||
| prefs.clear() | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.texthip.thip.data.model.users.request | ||
|
|
||
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| data class ProfileUpdateRequest( | ||
| val nickname: String?, | ||
| val aliasName: String | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.texthip.thip.data.model.users.request | ||
|
|
||
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| data class SignupRequest( | ||
| val nickname: String, | ||
| val aliasName: String | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,22 @@ | ||
| package com.texthip.thip.data.model.users.response | ||
|
|
||
| import com.google.gson.annotations.SerializedName | ||
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| data class OthersFollowersResponse( | ||
| val followers: List<FollowerList>, | ||
| val totalFollowerCount: Int, | ||
| val nextCursor: String?, | ||
| val isLast: Boolean | ||
| @SerializedName("followers") val followers: List<FollowerList>, | ||
| @SerializedName("totalFollowerCount") val totalFollowerCount: Int, | ||
| @SerializedName("nextCursor") val nextCursor: String?, | ||
| @SerializedName("isLast") val isLast: Boolean | ||
| ) | ||
|
|
||
| @Serializable | ||
| data class FollowerList( | ||
| val userId: Long, | ||
| val nickname: String, | ||
| val profileImageUrl: String?, | ||
| val aliasName: String, | ||
| val aliasColor: String, | ||
| val followerCount: Int, | ||
| ) | ||
|
|
||
| @SerializedName("userId") val userId: Long, | ||
| @SerializedName("nickname") val nickname: String, | ||
| @SerializedName("profileImageUrl") val profileImageUrl: String?, | ||
| @SerializedName("aliasName") val aliasName: String, | ||
| @SerializedName("aliasColor") val aliasColor: String, | ||
| @SerializedName("followerCount") val followerCount: Int | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package com.texthip.thip.data.model.users.response | ||
|
|
||
| import com.google.gson.annotations.SerializedName | ||
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| data class SignupResponse( | ||
| @SerializedName("accessToken") val accessToken: String, | ||
| @SerializedName("userId") val userId: Long | ||
| ) | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,18 @@ | ||||||||||||||||||||||||||||||||||
| package com.texthip.thip.data.model.users.response | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| import com.google.gson.annotations.SerializedName | ||||||||||||||||||||||||||||||||||
| import kotlinx.serialization.Serializable | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+4
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Gson 주석과 kotlinx.serialization 혼용 — 한 가지 직렬화 전략으로 통일 권장. 현재 @serializable(kotlinx)와 @SerializedName(Gson)을 혼용 중입니다. Retrofit에서 GsonConverterFactory와 KotlinxSerializationConverterFactory를 함께 쓰면, 등록 순서에 따라 서로 다른 파서가 선택되어 예기치 않은 동작/버그가 발생할 수 있습니다. 해당 응답 모델을 Kotlinx로 사용할 계획이라면 @SerialName으로 통일하고 Gson 주석과 import를 제거해주세요. 반대로 Gson을 쓸 계획이면 @serializable를 제거하세요. 권장 변경(Kotlinx로 통일 시): -import com.google.gson.annotations.SerializedName
+import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable @Serializable
data class UserItem(
- @SerializedName("userId") val userId: Int,
- @SerializedName("nickname") val nickname: String,
- @SerializedName("profileImageUrl") val profileImageUrl: String?,
- @SerializedName("aliasName") val aliasName: String,
- @SerializedName("aliasColor") val aliasColor: String,
- @SerializedName("followerCount") val followerCount: Int
+ @SerialName("userId") val userId: Long,
+ @SerialName("nickname") val nickname: String,
+ @SerialName("profileImageUrl") val profileImageUrl: String?,
+ @SerialName("aliasName") val aliasName: String,
+ @SerialName("aliasColor") val aliasColor: String,
+ @SerialName("followerCount") val followerCount: Int
)Retrofit 구성 시 ConverterFactory 순서도 확인이 필요합니다(Gson 제거 또는 Kotlinx 우선 등록). 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Serializable | ||||||||||||||||||||||||||||||||||
| data class UserSearchResponse( | ||||||||||||||||||||||||||||||||||
| val userList: List<UserItem> | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| @Serializable | ||||||||||||||||||||||||||||||||||
| data class UserItem( | ||||||||||||||||||||||||||||||||||
| @SerializedName("userId") val userId: Int, | ||||||||||||||||||||||||||||||||||
| @SerializedName("nickname") val nickname: String, | ||||||||||||||||||||||||||||||||||
| @SerializedName("profileImageUrl") val profileImageUrl: String?, | ||||||||||||||||||||||||||||||||||
| @SerializedName("aliasName") val aliasName: String, | ||||||||||||||||||||||||||||||||||
| @SerializedName("aliasColor") val aliasColor: String, | ||||||||||||||||||||||||||||||||||
| @SerializedName("followerCount") val followerCount: Int | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+12
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🛠️ Refactor suggestion 🧩 Analysis chainuserId 타입 불일치(Int vs Long) — 도메인 전반 Long으로 일원화 권장. SignupResponse에서 userId: Long으로 정의된 반면, 여기서는 Int입니다. 사용자 식별자는 장기적으로 Int 범위를 초과할 가능성이 있고, 타입 혼재는 변환/비교 시 미묘한 버그를 유발합니다. 전역적으로 Long으로 통일하는 것을 권장합니다. 다음 스크립트로 userId 타입 불일치 지점을 점검할 수 있습니다: 🏁 Script executed: #!/bin/bash
# userId 타입 선언 위치와 사용처 탐색
rg -n -C2 -P 'data\s+class\s+\w+\s*\(.*\buserId:\s*(Int|Long)' app | sed 's/^/DECL: /'
rg -n -C2 -P '\buserId\s*:\s*(Int|Long)\b' app | sed 's/^/TYPE: /'
rg -n -C2 -P '\buserId\b' app/src/main/java | sed 's/^/USE: /'Length of output: 44260 userId 타입 불일치(Int vs Long) — 도메인 전반 Long으로 통일 필요 현재 아래 모델 및 DTO에서 수정이 필요한 주요 파일:
(필요 시 테스트·모킹용 클래스에서도 예시: data class UserItem(
- @SerializedName("userId") val userId: Int,
+ @SerializedName("userId") val userId: Long,
@SerializedName("nickname") val nickname: String,
...
)— 변경 후 앱 전반의 사용자 식별자 타입이 일관된지, 호출부·뷰모델에서
|
||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
직렬화 어노테이션 혼용 — 한 가지로 통일 권장
@Serializable(kotlinx)와@SerializedName(Gson)을 동시에 사용하는 것은 혼동을 야기합니다. 현재 Retrofit 컨버터 구성이 어떤지에 따라 아래 둘 중 하나로 통일하세요.@Serializable제거, Gson만 유지@SerialName으로 전환, Gson 제거Retrofit 컨버터 구성 실사용 여부를 아래 스크립트로 확인해 주세요. 결과에 따라 A/B 중 하나를 적용하면 좋습니다.
🏁 Script executed:
Length of output: 943
Kotlinx Serialization 컨버터 사용 중 — @SerialName으로 통일 필요
네트워크 모듈에서
json.asConverterFactory(…)를 통해 GsonConverterFactory 없이 KotlinxSerializationConverter만 설정되어 있으므로, 해당 모델에서 Gson 어노테이션(@SerializedName)을 제거하고 Kotlinx 어노테이션(@SerialName)으로 전환하세요.적용 위치:
📝 Committable suggestion
🤖 Prompt for AI Agents