Skip to content
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

[REFACTOR] 데이터 레이어 다른 계층 참조하지 않도록 코드 분리 #340

Merged
merged 18 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
a2d3c2b
[FEAT] #339 Interceptor에서 액세스, 리프레시 토큰 관리 작업 구현
sxunea Mar 14, 2024
b609e6c
[FEAT] #339 액세스 토큰 재발급 성공시, preference에 해당 값 저장
sxunea Mar 14, 2024
8b882b7
[FEAT] #339 리프레시 토큰 또한 만료 / 통신 실패 시 빈 값 preference에 저장
sxunea Mar 14, 2024
123e7e7
[CHORE] #339 주석 추가 및 코드 정리
sxunea Mar 14, 2024
60adff3
[DEL] #339 Authenticator 제거
sxunea Mar 14, 2024
3e8d971
[MOD] #339 레트로핏 모듈에 Interceptor 반영
sxunea Mar 14, 2024
1aebc18
[FEAT] #339 accessToken 빈 문자열이면 토스트메시지와 함께 재로그인 요청
sxunea Mar 14, 2024
2ac7be5
[REFACTOR] #339 non null 단언 연산자 제거
sxunea Mar 14, 2024
0c210d0
[REFACTOR] #339 named argument 적용
sxunea Mar 24, 2024
ead0369
[REFACTOR] #339 interceptor return if로 response처리
sxunea Mar 24, 2024
60bbd81
[REFACTOR] #339 리뷰 간단사항 반영
sxunea Mar 24, 2024
a5eab3d
[ADD] #339 LoginStatus Enum Class 만들어 적용해 토큰 값 따른 로그인 상태 관리
sxunea Mar 24, 2024
b3267c8
[REFACTOR] #339 토큰preferenceManager AuthUtil로 빼서 관리
sxunea Mar 24, 2024
625d913
[MOD] #339 applicationContext 주입
sxunea Mar 24, 2024
e9c245b
[MOD] #339 runBlocking제거
sxunea Mar 27, 2024
0af3516
[REFACTOR] #339 applicationContext -> context로 변경하고, null 안전하게 체크
sxunea Mar 27, 2024
a390166
Merge remote-tracking branch 'origin/develop' into feature/refactor-data
sxunea Apr 24, 2024
7315ecc
[MERGE] #339 충돌 해결
sxunea Apr 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ import com.runnect.runnect.R
import com.runnect.runnect.application.ApiMode
import com.runnect.runnect.application.ApplicationClass
import com.runnect.runnect.application.PreferenceManager
import com.runnect.runnect.presentation.mypage.setting.accountinfo.MySettingAccountInfoFragment
import com.runnect.runnect.util.custom.toast.RunnectToast
import com.runnect.runnect.util.preference.LoginStatus
import com.runnect.runnect.util.preference.AuthUtil.getAccessToken
import com.runnect.runnect.util.preference.AuthUtil.getNewToken
import com.runnect.runnect.util.preference.AuthUtil.saveToken
import com.runnect.runnect.util.preference.StatusType.LoginStatus
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
Expand All @@ -44,8 +46,8 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev

private fun initUserInfo() {
val ctx: Context = context ?: return
val accessToken = PreferenceManager.getString(ctx, TOKEN_KEY_ACCESS) ?: ""
val refreshToken = PreferenceManager.getString(ctx, TOKEN_KEY_REFRESH) ?: ""
val accessToken = ctx.getAccessToken()
val refreshToken = ctx.getNewToken()

setPreferenceSummary("dev_pref_key_access_token", accessToken)
setPreferenceSummary("dev_pref_key_refresh_token", refreshToken)
Expand All @@ -70,18 +72,11 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev

PreferenceManager.apply {
setString(ctx, ApplicationClass.API_MODE, selectItem)
setString(
ctx,
MySettingAccountInfoFragment.TOKEN_KEY_ACCESS,
LoginStatus.NONE.value
)
setString(
ctx,
MySettingAccountInfoFragment.TOKEN_KEY_REFRESH,
LoginStatus.NONE.value
)
}

ctx.saveToken(
accessToken = LoginStatus.NONE.value,
refreshToken = LoginStatus.NONE.value
)
destroyApp(ctx)
true
}
Expand Down Expand Up @@ -184,8 +179,6 @@ class RunnectDeveloperActivity : AppCompatActivity(R.layout.activity_runnect_dev

companion object {
private const val CLIPBOARD_LABEL = "keyword"
const val TOKEN_KEY_ACCESS = "access"
const val TOKEN_KEY_REFRESH = "refresh"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.runnect.runnect.data.service

import android.content.Context
import com.runnect.runnect.application.ApplicationClass
import com.runnect.runnect.application.PreferenceManager
import com.runnect.runnect.data.dto.response.ResponseGetRefreshToken
import com.runnect.runnect.data.dto.response.base.BaseResponse
import com.runnect.runnect.util.preference.LoginStatus
import com.runnect.runnect.util.preference.AuthUtil.getAccessToken
import com.runnect.runnect.util.preference.AuthUtil.getNewToken
import com.runnect.runnect.util.preference.AuthUtil.saveToken
import com.runnect.runnect.util.preference.StatusType.LoginStatus
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.decodeFromString
Expand All @@ -17,6 +20,7 @@ import timber.log.Timber
import javax.inject.Inject

class AuthInterceptor @Inject constructor(
private val context: Context,
private val json: Json
) : Interceptor {
// access Header 에 보내고 이때 401(토큰 만료) 뜨면 액세스 재발급 요청
Expand All @@ -37,7 +41,7 @@ class AuthInterceptor @Inject constructor(
handleTokenExpired(chain, originalRequest, headerRequest)
} catch (t: Throwable) {
Timber.e("Exception: ${t.message}")
saveToken(
context.saveToken(
accessToken = LoginStatus.EXPIRED.value,
refreshToken = LoginStatus.EXPIRED.value
)
Expand All @@ -50,34 +54,15 @@ class AuthInterceptor @Inject constructor(

private fun Request.newAuthTokenBuilder() =
runBlocking(Dispatchers.IO) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분 runBlocking 쓰신 이유가 있나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저 때는 해당 작업이 완료될때까지 스레드를 막으려고 runBlocking을 사용하긴 했습니다 ! 다만 runBlocking이 아예 차단이라는 점에서 스레드를 점유하니까 좋진 않을거라고 작성할때도 생각하긴했습니다 .. .ㅎ ㅎ 처음에는 suspend로 작성했었는데 그러면 newAuthTokenBuilder를 사용하는 okhttp3 intercept까지 suspend func이 되어야 하는데, 이를 지원하지 않더라구요 😭 그래서 차선책으로 사용했습니다!!

지금 생각해보니 저 동작이 꼭 비동기여야할 필요는 없다고 생각이 드는데 어떻게 생각하시나요 ? 아니면 혹시 runBlocking을 쓰지 않고 다르게 처리할 방법이 있는지 궁금합니다

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 runBlocking을 작성하지 않았을 때 제대로 동작하지 않았나요??
interceptor가 비동기적으로 동작하더라도 같은 메소드 내에서는 실행 순서가 보장될테니 별도 처리가 필요 없을 것 같다는 생각이 들었습니다~!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

처음에 구현할땐 저도 필요없다고 생각했어서 작성하지 않았는데 동작이 안됐어서 runBlocking을 사용했는데, 지금 제거하고 보니 또 잘 가져오네요 🥹 다른 부분이 잘못됐었는데 불필요하게 같이 고쳐준 것 같아요 저도 runBlocking이 여전히 불필요하다고 생각합니다 ㅎㅎㅎ 없애서 수정할게요 !

val accessToken = getAccessToken()
val refreshToken = getNewToken()
val accessToken = context.getAccessToken()
val refreshToken = context.getNewToken()
newBuilder().apply {
addHeader(ACCESS_TOKEN, accessToken)
addHeader(REFRESH_TOKEN, refreshToken)
}
}


private fun getAccessToken(): String {
return PreferenceManager.getString(
ApplicationClass.appContext,
TOKEN_KEY_ACCESS
) ?: ""
}

private fun getNewToken(): String {
return PreferenceManager.getString(
ApplicationClass.appContext,
TOKEN_KEY_REFRESH
) ?: ""
}

private fun saveToken(accessToken: String, refreshToken: String) {
PreferenceManager.setString(ApplicationClass.appContext, TOKEN_KEY_ACCESS, accessToken)
PreferenceManager.setString(ApplicationClass.appContext, TOKEN_KEY_REFRESH, refreshToken)
}

private fun handleTokenExpired(
chain: Interceptor.Chain,
originalRequest: Request,
Expand All @@ -87,13 +72,13 @@ class AuthInterceptor @Inject constructor(
return if (refreshTokenResponse.isSuccessful) {
handleGetRefreshTokenSuccess(refreshTokenResponse, originalRequest, chain)
} else {
handleGetRefreshTokenFailure(refreshTokenResponse, headerRequest, chain)
handleGetNewTokenFailure(refreshTokenResponse, headerRequest, chain)
}
}

private fun getNewToken(originalRequest: Request, chain: Interceptor.Chain): Response {
val baseUrl = ApplicationClass.getBaseUrl()
val refreshToken = getNewToken()
val refreshToken = context.getNewToken()
val refreshTokenRequest = originalRequest.newBuilder().post("".toRequestBody())
.url("$baseUrl/api/auth/getNewToken")
.addHeader(REFRESH_TOKEN, refreshToken)
Expand All @@ -113,21 +98,24 @@ class AuthInterceptor @Inject constructor(
)
responseToken.data?.data?.let {
Timber.e("New Refresh Token Success: ${it.refreshToken}")
saveToken(it.accessToken, it.refreshToken)
context.saveToken(it.accessToken, it.refreshToken)
}
}

val newRequest = originalRequest.newAuthTokenBuilder().build()
return chain.proceed(newRequest)
}

private fun handleGetRefreshTokenFailure(
private fun handleGetNewTokenFailure(
refreshTokenResponse: Response,
headerRequest: Request,
chain: Interceptor.Chain
): Response {
Timber.e("New Refresh Token Failure: ${refreshTokenResponse.code}")
saveToken(accessToken = LoginStatus.EXPIRED.value, refreshToken = LoginStatus.EXPIRED.value)
context.saveToken(
accessToken = LoginStatus.EXPIRED.value,
refreshToken = LoginStatus.EXPIRED.value
)
return chain.proceed(headerRequest)
}

Expand All @@ -136,9 +124,6 @@ class AuthInterceptor @Inject constructor(
private const val ACCESS_TOKEN = "accessToken"
private const val CODE_TOKEN_EXPIRED = 401
private const val REFRESH_TOKEN = "refreshToken"

const val TOKEN_KEY_ACCESS = "access"
const val TOKEN_KEY_REFRESH = "refresh"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import com.google.firebase.remoteconfig.ktx.remoteConfig
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
import com.runnect.runnect.BuildConfig.REMOTE_KEY_APP_VERSION
import com.runnect.runnect.R
import com.runnect.runnect.application.ApplicationClass
import com.runnect.runnect.application.PreferenceManager
import com.runnect.runnect.binding.BindingActivity
import com.runnect.runnect.databinding.ActivityMainBinding
import com.runnect.runnect.presentation.coursemain.CourseMainFragment
Expand All @@ -23,7 +21,8 @@ import com.runnect.runnect.presentation.storage.StorageScrapFragment
import com.runnect.runnect.util.analytics.Analytics
import com.runnect.runnect.util.analytics.EventName
import com.runnect.runnect.util.analytics.EventName.EVENT_VIEW_HOME
import com.runnect.runnect.util.preference.LoginStatus
import com.runnect.runnect.util.preference.AuthUtil.getAccessToken
import com.runnect.runnect.util.preference.StatusType.LoginStatus
import dagger.hilt.android.AndroidEntryPoint
import timber.log.Timber

Expand All @@ -45,7 +44,7 @@ class MainActivity : BindingActivity<ActivityMainBinding>(R.layout.activity_main
}

private fun checkVisitorMode() {
val accessToken = PreferenceManager.getString(ApplicationClass.appContext, TOKEN_KEY_ACCESS)
val accessToken = applicationContext.getAccessToken()
dongx0915 marked this conversation as resolved.
Show resolved Hide resolved
val loginStatus = LoginStatus.getLoginStatus(accessToken)
isVisitorMode = loginStatus == LoginStatus.VISITOR
}
Expand Down Expand Up @@ -164,7 +163,6 @@ class MainActivity : BindingActivity<ActivityMainBinding>(R.layout.activity_main
const val DEFAULT_VERSION = "0.0.0"

const val EXTRA_FRAGMENT_REPLACEMENT_DIRECTION = "fragmentReplacementDirection"
const val TOKEN_KEY_ACCESS = "access"

var isVisitorMode = false
var discoverFragment: DiscoverFragment? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import android.view.MotionEvent
import androidx.activity.viewModels
import androidx.core.view.isVisible
import com.runnect.runnect.R
import com.runnect.runnect.application.PreferenceManager
import com.runnect.runnect.binding.BindingActivity
import com.runnect.runnect.databinding.ActivityGiveNicknameBinding
import com.runnect.runnect.presentation.MainActivity
import com.runnect.runnect.presentation.state.UiState
import com.runnect.runnect.util.extension.hideKeyboard
import com.runnect.runnect.util.extension.showToast
import com.runnect.runnect.util.preference.AuthUtil.saveToken
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
Expand All @@ -35,15 +35,9 @@ class GiveNicknameActivity :
}

private fun saveSignTokenInfo() {
PreferenceManager.setString(
applicationContext,
TOKEN_KEY_ACCESS,
intent.getStringExtra("access")
)
PreferenceManager.setString(
applicationContext,
TOKEN_KEY_REFRESH,
intent.getStringExtra("refresh")
applicationContext.saveToken(
accessToken = intent.getStringExtra("access") ?: "",
refreshToken = intent.getStringExtra("refresh") ?: ""
)
}

Expand Down Expand Up @@ -113,9 +107,5 @@ class GiveNicknameActivity :
return super.dispatchTouchEvent(ev)
}

companion object {
const val TOKEN_KEY_ACCESS = "access"
const val TOKEN_KEY_REFRESH = "refresh"
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import android.widget.Toast
import androidx.activity.viewModels
import androidx.core.view.isVisible
import com.runnect.runnect.R
import com.runnect.runnect.application.PreferenceManager
import com.runnect.runnect.binding.BindingActivity
import com.runnect.runnect.databinding.ActivityLoginBinding
import com.runnect.runnect.presentation.MainActivity
Expand All @@ -16,22 +15,24 @@ import com.runnect.runnect.util.analytics.Analytics
import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_VISITOR
import com.runnect.runnect.util.analytics.EventName.EVENT_VIEW_SOCIAL_LOGIN
import com.runnect.runnect.util.extension.showToast
import com.runnect.runnect.util.preference.LoginStatus
import com.runnect.runnect.util.preference.AuthUtil.getAccessToken
import com.runnect.runnect.util.preference.AuthUtil.saveToken
import com.runnect.runnect.util.preference.StatusType.LoginStatus
import dagger.hilt.android.AndroidEntryPoint
import timber.log.Timber

@AndroidEntryPoint
class LoginActivity :
BindingActivity<ActivityLoginBinding>(com.runnect.runnect.R.layout.activity_login) {
lateinit var socialLogin: SocialLogin
lateinit var googleLogin: GoogleLogin
lateinit var kakaoLogin: KakaoLogin
BindingActivity<ActivityLoginBinding>(R.layout.activity_login) {
private lateinit var socialLogin: SocialLogin
private lateinit var googleLogin: GoogleLogin
private lateinit var kakaoLogin: KakaoLogin
private val viewModel: LoginViewModel by viewModels()

//자동 로그인
override fun onStart() {
super.onStart()
val accessToken = PreferenceManager.getString(applicationContext, TOKEN_KEY_ACCESS)
val accessToken = applicationContext.getAccessToken()

when (LoginStatus.getLoginStatus(accessToken)) {
LoginStatus.EXPIRED -> {
Expand Down Expand Up @@ -77,15 +78,9 @@ class LoginActivity :
}
btnVisitorMode.setOnClickListener {
Analytics.logClickedItemEvent(EVENT_CLICK_VISITOR)
PreferenceManager.setString(
context = applicationContext,
key = TOKEN_KEY_ACCESS,
value = LoginStatus.VISITOR.value
)
PreferenceManager.setString(
context = applicationContext,
key = TOKEN_KEY_REFRESH,
value = LoginStatus.VISITOR.value
applicationContext.saveToken(
accessToken = LoginStatus.VISITOR.value,
refreshToken = LoginStatus.VISITOR.value
)
moveToMain()
}
Expand Down Expand Up @@ -134,16 +129,12 @@ class LoginActivity :


private fun saveSignTokenInfo() {
PreferenceManager.setString(
context = applicationContext,
key = TOKEN_KEY_ACCESS,
value = viewModel.loginResult.value?.accessToken
)
PreferenceManager.setString(
context = applicationContext,
key = TOKEN_KEY_REFRESH,
value = viewModel.loginResult.value?.refreshToken
)
viewModel.loginResult.value?.let { loginResult ->
applicationContext.saveToken(
accessToken = loginResult.accessToken,
refreshToken = loginResult.refreshToken
)
}
Timber.d("ACCESS TOKEN: ${viewModel.loginResult.value?.accessToken}")
Timber.d("REFRESH TOKEN: ${viewModel.loginResult.value?.refreshToken}")
}
Expand All @@ -167,9 +158,6 @@ class LoginActivity :
const val GOOGLE_SIGN = "GOOGLE"
const val KAKAO_SIGN = "KAKAO"

const val TOKEN_KEY_ACCESS = "access"
const val TOKEN_KEY_REFRESH = "refresh"

const val EXTRA_ACCESS_TOKEN = "access"
const val EXTRA_REFRESH_TOKEN = "refresh"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import androidx.fragment.app.commit
import androidx.fragment.app.replace
import androidx.fragment.app.viewModels
import com.runnect.runnect.R
import com.runnect.runnect.application.PreferenceManager
import com.runnect.runnect.binding.BindingFragment
import com.runnect.runnect.databinding.FragmentMySettingAccountInfoBinding
import com.runnect.runnect.presentation.login.LoginActivity
Expand All @@ -25,7 +24,8 @@ import com.runnect.runnect.util.analytics.EventName.EVENT_VIEW_SUCCESS_WITHDRAW
import com.runnect.runnect.util.extension.setCustomDialog
import com.runnect.runnect.util.extension.setDialogButtonClickListener
import com.runnect.runnect.util.extension.showToast
import com.runnect.runnect.util.preference.LoginStatus
import com.runnect.runnect.util.preference.AuthUtil.saveToken
import com.runnect.runnect.util.preference.StatusType.LoginStatus
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.android.synthetic.main.custom_dialog_delete.btn_delete_yes
import timber.log.Timber
Expand Down Expand Up @@ -111,8 +111,10 @@ class MySettingAccountInfoFragment :
}

private fun moveToLogin() {
PreferenceManager.setString(requireContext(), TOKEN_KEY_ACCESS, LoginStatus.NONE.value)
PreferenceManager.setString(requireContext(), TOKEN_KEY_REFRESH, LoginStatus.NONE.value)
requireActivity().applicationContext?.saveToken(
dongx0915 marked this conversation as resolved.
Show resolved Hide resolved
accessToken = LoginStatus.NONE.value,
refreshToken = LoginStatus.NONE.value
)
val intent = Intent(requireActivity(), LoginActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
startActivity(intent)
Expand Down Expand Up @@ -168,7 +170,5 @@ class MySettingAccountInfoFragment :
const val DESCRIPTION_WITHDRAWAL = "정말로 탈퇴하시겟어요?"
const val DESCRIPTION_WITHDRAWAL_YES = "네"
const val DESCRIPTION_WITHDRAWAL_NO = "아니오"
const val TOKEN_KEY_ACCESS = "access"
const val TOKEN_KEY_REFRESH = "refresh"
}
}
Loading
Loading