-
Notifications
You must be signed in to change notification settings - Fork 10
9주차 미션 / 안드로이드 1조 정일혁 #30
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
base: develop
Are you sure you want to change the base?
Changes from all commits
a047a58
c62340d
7b4f7b3
4d8a1f5
fb67908
b801059
ba74537
cb50212
179fd7d
aca9015
fd56889
460b888
da6b8bb
04f83ac
4e4cb53
924862d
f817333
25834c3
e64229a
874812c
f2e0e7d
039f752
555e5ed
6a335ab
29306ae
e2cd3ad
2704669
f331764
f68a3cb
dd8492d
99572ac
9064fcb
dc63e43
543fd9b
57b0e7e
7d4df19
1de778d
a5991f4
b94897f
9327b07
9904e2f
d1ef930
ba13d06
c9a755d
fae2449
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| kotlin version: 2.0.21 | ||
| error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output: | ||
| 1. Kotlin compile daemon is ready | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| kotlin version: 2.0.21 | ||
| error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output: | ||
| 1. Kotlin compile daemon is ready | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "java.configuration.updateBuildConfiguration": "automatic" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package com.example.kuit6_android_api | ||
|
|
||
| import android.app.Application | ||
| import androidx.lifecycle.ViewModelProvider.NewInstanceFactory.Companion.instance | ||
| import dagger.hilt.android.HiltAndroidApp | ||
|
|
||
|
|
||
| @HiltAndroidApp | ||
| class App: Application() { | ||
| //Application은 Context의 하위 클래스 | ||
|
|
||
| override fun onCreate(){ | ||
| super.onCreate() | ||
| instance = this | ||
| //Application Context 전달 | ||
| } | ||
|
|
||
| companion object{ | ||
| lateinit var instance: App | ||
| private set | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.example.kuit6_android_api.data.api | ||
|
|
||
| import android.content.Context | ||
| import com.example.kuit6_android_api.data.repository.TokenRepository | ||
| import com.example.kuit6_android_api.data.repository.TokenRepositoryImpl | ||
| import kotlinx.coroutines.runBlocking | ||
| import okhttp3.Interceptor | ||
| import okhttp3.Response | ||
| import javax.inject.Inject | ||
| import javax.inject.Singleton | ||
|
|
||
| @Singleton | ||
| class AuthInterceptor @Inject constructor( | ||
| private val tokenRepository: TokenRepository // Hilt가 TokenRepositoryImpl을 생성해서 주입 | ||
| ) : Interceptor { | ||
| //발생한 요청을 가로채 수정 | ||
|
|
||
| override fun intercept(chain: Interceptor.Chain): Response { | ||
| val token = runBlocking { | ||
| //블록이 완료될 때까지 intercept를 호출한 스레드의 실행 멈춤 | ||
| tokenRepository.getToken() | ||
| } | ||
|
|
||
| val request = chain.request().newBuilder() | ||
| if(!token.isNullOrEmpty()){ | ||
| request.addHeader("Authorization", "Bearer $token") | ||
| } | ||
| return chain.proceed(request.build()) | ||
| } | ||
|
Comment on lines
+18
to
+29
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. Critical: 요청 스레드에서 runBlocking 사용으로 인한 성능 문제 Interceptor의
다음 중 하나의 해결 방법을 고려하세요: 해결 방법 1 (권장): 동기 토큰 캐시 사용 TokenRepository에 메모리 캐싱을 추가하여 동기적으로 토큰을 반환: @Singleton
class AuthInterceptor @Inject constructor(
private val tokenRepository: TokenRepository
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val token = tokenRepository.getTokenSync() // 동기 메서드 추가
val request = chain.request().newBuilder()
if (!token.isNullOrEmpty()) {
request.addHeader("Authorization", "Bearer $token")
}
return chain.proceed(request.build())
}
}해결 방법 2: Authenticator 사용 OkHttp의 Authenticator를 사용하여 401 응답 시에만 토큰 재인증: class TokenAuthenticator @Inject constructor(
private val tokenRepository: TokenRepository
) : Authenticator {
override fun authenticate(route: Route?, response: Response): Request? {
val token = runBlocking { tokenRepository.getToken() }
return response.request.newBuilder()
.header("Authorization", "Bearer $token")
.build()
}
}🤖 Prompt for AI Agents |
||
| } | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| package com.example.kuit6_android_api.data.di | ||
|
|
||
| import com.example.kuit6_android_api.BuildConfig | ||
|
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. BODY 레벨 HttpLoggingInterceptor로 인한 토큰/민감 정보 노출 위험 현재 빌드 타입에 따라 로그 레벨을 분기하는 것을 강하게 추천드립니다. 예: - fun provideLoginInterceptor(): HttpLoggingInterceptor =
- HttpLoggingInterceptor().apply {
- level = HttpLoggingInterceptor.Level.BODY
- }
+ fun provideLoginInterceptor(): HttpLoggingInterceptor =
+ HttpLoggingInterceptor().apply {
+ level = if (BuildConfig.DEBUG) {
+ HttpLoggingInterceptor.Level.BODY
+ } else {
+ HttpLoggingInterceptor.Level.NONE
+ }
+ }이렇게 하면 개발 환경에서는 상세 로그를 유지하면서, 운영 환경에서는 민감 정보가 로그에 남지 않도록 할 수 있습니다. Also applies to: 22-27 🤖 Prompt for AI Agents |
||
| import com.example.kuit6_android_api.data.api.ApiService | ||
| import com.example.kuit6_android_api.data.api.AuthInterceptor | ||
| import dagger.Module | ||
| import dagger.Provides | ||
| import dagger.hilt.InstallIn | ||
| import dagger.hilt.components.SingletonComponent | ||
| import kotlinx.serialization.json.Json | ||
| import okhttp3.MediaType.Companion.toMediaType | ||
| import okhttp3.OkHttpClient | ||
| import okhttp3.logging.HttpLoggingInterceptor | ||
| import retrofit2.Retrofit | ||
| import retrofit2.converter.kotlinx.serialization.asConverterFactory | ||
| import javax.inject.Singleton | ||
|
|
||
|
|
||
| @Module | ||
| @InstallIn(SingletonComponent::class) | ||
| object NetworkModule { | ||
| @Provides | ||
| @Singleton | ||
| fun provideLoginInterceptor(): HttpLoggingInterceptor = | ||
| HttpLoggingInterceptor().apply { | ||
| level = HttpLoggingInterceptor.Level.BODY | ||
| } | ||
|
|
||
| @Provides | ||
| @Singleton | ||
| fun provideOkHttpClient( | ||
| authInterceptor: AuthInterceptor, // Hilt가 인터셉터를 자동으로 주입하므로써 인터셉터를 매번 생성할 필요가 없게 됨 | ||
| loggingInterceptor: HttpLoggingInterceptor | ||
| ): okhttp3.OkHttpClient = | ||
| OkHttpClient.Builder() | ||
| .addInterceptor(authInterceptor) | ||
| .addInterceptor(loggingInterceptor) | ||
| .build() | ||
|
|
||
| @Provides | ||
| @Singleton | ||
| fun provideJson(): Json = Json { | ||
| ignoreUnknownKeys = true | ||
| coerceInputValues = true | ||
| } | ||
|
|
||
| @Provides | ||
| @Singleton | ||
| fun provideRetrofit( | ||
| okHttpClient: OkHttpClient, | ||
| json: Json | ||
| ): Retrofit = | ||
| Retrofit.Builder() | ||
| .baseUrl(BuildConfig.BASE_URL) | ||
| .client(okHttpClient) | ||
| .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) | ||
| .build() | ||
|
|
||
| @Provides | ||
| @Singleton | ||
| fun provideApiService(retrofit: Retrofit) : ApiService = | ||
| retrofit.create(ApiService::class.java) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package com.example.kuit6_android_api.data.di | ||
|
|
||
| import com.example.kuit6_android_api.data.repository.LoginRepository | ||
| import com.example.kuit6_android_api.data.repository.LoginRepositoryImpl | ||
| import com.example.kuit6_android_api.data.repository.PostRepository | ||
| import com.example.kuit6_android_api.data.repository.PostRepositoryImpl | ||
| import com.example.kuit6_android_api.data.repository.TokenApiRepository | ||
| import com.example.kuit6_android_api.data.repository.TokenApiRepositoryImpl | ||
| import com.example.kuit6_android_api.data.repository.TokenRepository | ||
| import com.example.kuit6_android_api.data.repository.TokenRepositoryImpl | ||
| import dagger.Binds | ||
| import dagger.Module | ||
| import dagger.hilt.InstallIn | ||
| import dagger.hilt.components.SingletonComponent | ||
| import javax.inject.Singleton | ||
|
|
||
| @Module | ||
| @InstallIn(SingletonComponent::class) | ||
| abstract class RepositoryModule { | ||
|
|
||
| @Binds | ||
| @Singleton | ||
| abstract fun bindLoginRepository(impl: LoginRepositoryImpl) : LoginRepository | ||
|
|
||
| @Binds | ||
| @Singleton | ||
| abstract fun bindTokenRepository(impl: TokenRepositoryImpl) : TokenRepository | ||
|
|
||
| @Binds | ||
| @Singleton | ||
| abstract fun bindPostRepository(impl: PostRepositoryImpl) : PostRepository | ||
|
|
||
| @Binds | ||
| @Singleton | ||
| abstract fun bindTokenApiRepository(impl: TokenApiRepositoryImpl) : TokenApiRepository | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.example.kuit6_android_api.data.model.request | ||
|
|
||
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| data class LoginRequest( | ||
| val username:String, | ||
| val password:String | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package com.example.kuit6_android_api.data.model.response | ||
|
|
||
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| data class LoginResponse( | ||
| val token:String, | ||
| val userId:Long, | ||
| val username: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.
사용되지 않는 잘못된 import를 제거해주세요.
ViewModelProvider.NewInstanceFactory.Companion.instanceimport는 이 파일에서 사용되지 않으며, 실제로는 companion object의instance프로퍼티를 사용하고 있습니다. 이 import는 혼란을 야기할 수 있으므로 제거해야 합니다.다음과 같이 import를 제거하세요:
package com.example.kuit6_android_api import android.app.Application -import androidx.lifecycle.ViewModelProvider.NewInstanceFactory.Companion.instance import dagger.hilt.android.HiltAndroidApp📝 Committable suggestion
🤖 Prompt for AI Agents