Skip to content

Commit

Permalink
[BASE] #22 Hilt 모듈 구현 (#24)
Browse files Browse the repository at this point in the history
* [chore] hilt 의존성 추가

* [feature] PokitApplication 구현 및 등록

* [feature] NetworkModule 모듈 구현

* [chore] 타임아웃 설정

* [chore] auth request, response 데이터 추가

* [chore] auth api 추가

* [chore] auth api 수정

* [chore] 버전 카탈로그 라이브러리 추가

- domain 모듈 inject
- logging-interceptor

* [feature] hilt + 네트워크 모듈 구현

* [chore] @androidentrypoint 애노테이션 추가

* [chore] kotest 의존성 추가

* [feature] sns로그인 api연동

* [feature] 테스트 토큰 인터셉터 구현

* [feature] 닉네임 입력 화면 설계

* [chore] 뷰모델 주입

* [chore] 미사용 리소스 제거

* [chore] 코딩 컨벤션 적용

* [chore] 코딩 컨벤션 적용

* [chore] orbit 제거

* [chore] LoginScreen 로직 수정

* [feature] 애플 로그인 구현

* [feature] 네트워크 통신 모듈 구현

* [chore] 클래스명 수정

* [chore] 주석 제거

* [feature] parseErrorResult 함수 구현

* [chore] 닉네임 중복 처리 api 세팅

* [chore] parseErrorResult 분리 및 적용

* [chore] 중복 닉네임 api 세팅

* [chore] 코딩 컨벤션 반영

* [chore] ktlint rule 추가

* [chore] ktlint_standard_function-name 제거

* [chore] 파일 이름 수정
  • Loading branch information
jiwon2724 authored Jul 30, 2024
1 parent a68735a commit 5458359
Show file tree
Hide file tree
Showing 44 changed files with 716 additions and 64 deletions.
3 changes: 1 addition & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ indent_style = space
trim_trailing_whitespace = true
insert_final_newline = true
tab_width = 4
ij_kotlin_allow_trailing_comma = true
ktlint_standard_function-name = false
ij_kotlin_allow_trailing_comma = true
13 changes: 13 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
plugins {
alias(libs.plugins.com.android.application)
alias(libs.plugins.org.jetbrains.kotlin.android)
alias(libs.plugins.hilt)
alias(libs.plugins.googleServices)
id("kotlin-kapt")
}

android {
Expand Down Expand Up @@ -67,5 +70,15 @@ dependencies {
debugImplementation(libs.androidx.ui.test.manifest)

implementation(project(":core:ui"))
implementation(project(":data"))
implementation(project(":domain"))
implementation(project(":feature:login"))

// hilt
implementation(libs.hilt)
kapt(libs.hilt.compiler)

// firebase
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.auth.ktx)
}
62 changes: 62 additions & 0 deletions app/google-services.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"project_info": {
"project_number": "217769178527",
"project_id": "pokit-f5c83",
"storage_bucket": "pokit-f5c83.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:217769178527:android:5d7efa4ceafe61c37af9aa",
"android_client_info": {
"package_name": "pokitmons.pokit"
}
},
"oauth_client": [
{
"client_id": "217769178527-jaa8p8nfmic1j1065qs5a7vfqt18qec0.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "pokitmons.pokit",
"certificate_hash": "9ded6dcd446add68f506001f3c1b457cc1c3be9e"
}
},
{
"client_id": "217769178527-mmbheg9v5npdhdrbfq78slpsk8lt2nga.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "pokitmons.pokit",
"certificate_hash": "b2f3e34f8e02d15beb0d10d3d48a05148e943642"
}
},
{
"client_id": "217769178527-tslgsrrr1o8bli4hr4qnas2u9kg80a9h.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyDMh93QvJGUUX8-E-wyJoSS3cFrwfw8Q3w"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "217769178527-l4prj2q9qsuvkodc2cpi84psvul5rth2.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "217769178527-021j3dpbues9rhbkp6cffnn19mdajorq.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.pokitmons.pokit.App"
}
}
]
}
}
}
],
"configuration_version": "1"
}
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:name=".PokitApplication"
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/pokitmons/pokit/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package pokitmons.pokit
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import dagger.hilt.android.AndroidEntryPoint
import pokitmons.pokit.core.ui.theme.PokitTheme
import pokitmons.pokit.navigation.LoginNavHost

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/pokitmons/pokit/PokitApplication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package pokitmons.pokit

import android.app.Application
import com.google.firebase.FirebaseApp
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class PokitApplication : Application() {
override fun onCreate() {
super.onCreate()
FirebaseApp.initializeApp(this)
}
}
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ plugins {
alias(libs.plugins.org.jetbrains.kotlin.android) apply false
alias(libs.plugins.ktlint.gradle) apply false
alias(libs.plugins.org.jetbrains.kotlin.jvm) apply false
alias(libs.plugins.hilt) apply false
alias(libs.plugins.com.android.library) apply false
alias(libs.plugins.googleServices) apply false
}

subprojects {
Expand Down
27 changes: 27 additions & 0 deletions data/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
plugins {
alias(libs.plugins.com.android.library)
alias(libs.plugins.org.jetbrains.kotlin.android)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.hilt)
id("kotlin-kapt")
}

android {
tasks.withType<Test>().configureEach {
useJUnitPlatform()
}

namespace = "pokitmons.pokit.data"
compileSdk = 34

Expand Down Expand Up @@ -38,6 +45,26 @@ dependencies {
implementation(libs.appcompat)
implementation(libs.material)
testImplementation(libs.junit)
testImplementation(project(":feature:login"))
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)

// kotest
testImplementation(libs.kotest.runner.junit5)
testImplementation(libs.kotlin.reflect)

// hilt
implementation(libs.hilt)
kapt(libs.hilt.compiler)

// serialization
implementation(libs.kotlinx.serialization.json)

// retrofit
implementation(libs.retrofit)
implementation(libs.retrofit.converter.serialization)
implementation(libs.okhttp)
implementation(libs.logging.interceptor)

implementation(project(":domain"))
}
21 changes: 21 additions & 0 deletions data/src/main/java/pokitmons/pokit/data/api/AuthApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package pokitmons.pokit.data.api

import pokitmons.pokit.data.model.auth.request.SNSLoginRequest
import pokitmons.pokit.data.model.auth.response.DuplicateNicknameResponse
import pokitmons.pokit.data.model.auth.response.SNSLoginResponse
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path

interface AuthApi {
@POST("auth/signin")
suspend fun snsLogin(
@Body snsLoginRequest: SNSLoginRequest,
): SNSLoginResponse

@GET("user/duplicate/{nickname}")
suspend fun checkDuplicateNickname(
@Path(value = "nickname") nickname: String,
): DuplicateNicknameResponse
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package pokitmons.pokit.data.datasource.remote.auth

import pokitmons.pokit.data.model.auth.request.SNSLoginRequest
import pokitmons.pokit.data.model.auth.response.DuplicateNicknameResponse
import pokitmons.pokit.data.model.auth.response.SNSLoginResponse

interface AuthDataSource {
// suspend fun signUp(signUpRequest: SignUpRequest): PokitResponse<SignUpResponse>
suspend fun snsLogin(snsLoginRequest: SNSLoginRequest): SNSLoginResponse
suspend fun checkDuplicateNickname(nickname: String): DuplicateNicknameResponse
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package pokitmons.pokit.data.datasource.remote.auth

import pokitmons.pokit.data.api.AuthApi
import pokitmons.pokit.data.model.auth.request.SNSLoginRequest
import pokitmons.pokit.data.model.auth.response.DuplicateNicknameResponse
import pokitmons.pokit.data.model.auth.response.SNSLoginResponse
import javax.inject.Inject

class RemoteAuthDataSourceImpl @Inject constructor(private val authApi: AuthApi) : AuthDataSource {
override suspend fun snsLogin(snsLoginRequest: SNSLoginRequest): SNSLoginResponse {
return authApi.snsLogin(snsLoginRequest)
}

override suspend fun checkDuplicateNickname(nickname: String): DuplicateNicknameResponse {
return authApi.checkDuplicateNickname(nickname)
}
}
23 changes: 23 additions & 0 deletions data/src/main/java/pokitmons/pokit/data/di/auth/AuthModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package pokitmons.pokit.data.di.auth

import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import pokitmons.pokit.data.datasource.remote.auth.AuthDataSource
import pokitmons.pokit.data.datasource.remote.auth.RemoteAuthDataSourceImpl
import pokitmons.pokit.data.repository.auth.AuthRepositoryImpl
import pokitmons.pokit.domain.repository.auth.AuthRepository
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class AuthModule {
@Binds
@Singleton
abstract fun bindAuthRepository(authRepositoryImpl: AuthRepositoryImpl): AuthRepository

@Binds
@Singleton
abstract fun bindAuthDataSource(authDataSourceImpl: RemoteAuthDataSourceImpl): AuthDataSource
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package pokitmons.pokit.data.di.network

import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
import java.io.IOException

// 토큰 api 수정될 때 까지 사용
class BearerTokenInterceptor : Interceptor {
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest: Request = chain.request()
val requestWithToken: Request = originalRequest.newBuilder()
.header(
"Authorization",
"Bearer eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiIxIiwiaWF0IjoxNzIxNjU4MjUxLCJleHAiOj" +
"MwMDE3MjE2NTgyNTF9.gw6LZimKLuZJ2y0UV5cgvk3F7o92pkRIDgx-qlD_S7qEI01QAFt9dZDyHADabftI"
)
.build()

return chain.proceed(requestWithToken)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package pokitmons.pokit.data.di.network

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
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 pokitmons.pokit.data.api.AuthApi
import retrofit2.Retrofit
import java.util.concurrent.TimeUnit
import javax.inject.Singleton

private const val BASE_URL = "https://pokit.site"
private const val API = "api"
private const val VERSION = "v1"

private const val READ_TIME_OUT = 20000L
private const val WRITE_TIME_OUT = 20000L

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Singleton
@Provides
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(BearerTokenInterceptor())
.addInterceptor(
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
)
.readTimeout(READ_TIME_OUT, TimeUnit.SECONDS)
.writeTimeout(WRITE_TIME_OUT, TimeUnit.SECONDS)
.build()
}

@Singleton
@Provides
fun provideJson(): Json {
return Json {
ignoreUnknownKeys = true
coerceInputValues = true
prettyPrint = true
}
}

@Singleton
@Provides
fun provideRetrofit(
okHttpClient: OkHttpClient,
json: Json,
): Retrofit {
val converterFactory = json.asConverterFactory("application/json; charset=UTF8".toMediaType())
return Retrofit.Builder()
.baseUrl("$BASE_URL/$API/$VERSION/")
.addConverterFactory(converterFactory)
.client(okHttpClient)
.build()
}

@Provides
fun provideAuthService(retrofit: Retrofit): AuthApi {
return retrofit.create(AuthApi::class.java)
}
}
21 changes: 21 additions & 0 deletions data/src/main/java/pokitmons/pokit/data/mapper/auth/AuthMapper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package pokitmons.pokit.data.mapper.auth

import pokitmons.pokit.data.model.auth.response.DuplicateNicknameResponse
import pokitmons.pokit.data.model.auth.response.SNSLoginResponse
import pokitmons.pokit.domain.model.auth.DuplicateNicknameResult
import pokitmons.pokit.domain.model.auth.SNSLoginResult

object AuthMapper {
fun mapperToSNSLogin(snsLoginResponse: SNSLoginResponse): SNSLoginResult {
return SNSLoginResult(
accessToken = snsLoginResponse.accessToken,
refreshToken = snsLoginResponse.refreshToken
)
}

fun mapperToDuplicateNickname(checkDuplicateNicknameResponse: DuplicateNicknameResponse): DuplicateNicknameResult {
return DuplicateNicknameResult(
isDuplicate = checkDuplicateNicknameResponse.isDuplicate
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package pokitmons.pokit.data.model.auth.request

import kotlinx.serialization.Serializable

@Serializable
data class SNSLoginRequest(
val authPlatform: String,
val idToken: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package pokitmons.pokit.data.model.auth.request

data class SignUpRequest(
val nickname: String,
val interests: List<String>,
)
Loading

0 comments on commit 5458359

Please sign in to comment.