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] Week6 과제 #11

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
Open
11 changes: 11 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ plugins {
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.hilt.android)
id("kotlin-kapt")
}

val properties = Properties().apply {
Expand Down Expand Up @@ -46,9 +48,18 @@ android {
compose = true
buildConfig = true
}

hilt {
enableAggregatingTask = false
}
Comment on lines +52 to +54

Choose a reason for hiding this comment

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

이거 관련해서 합세 리뷰에 적어두었으니 확인해주시면 좋을 것 같네요 ~

}

dependencies {
// Hilt
implementation(libs.hilt.android)
implementation(libs.hilt.navigation.compose)
implementation(libs.androidx.appcompat)
kapt(libs.hilt.compiler)
// Network
implementation(platform(libs.okhttp.bom))
implementation(libs.okhttp)
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET" />

<application
android:name=".WavveApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand All @@ -16,7 +17,7 @@
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".feature.main.MainActivity"
android:name=".presentation.main.MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.ANDANDROID">
Expand Down
17 changes: 17 additions & 0 deletions app/src/main/java/org/sopt/and/WavveApp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.sopt.and

import android.app.Application
import androidx.appcompat.app.AppCompatDelegate
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class WavveApp: Application() {
override fun onCreate() {
super.onCreate()
setDarkMode()
}

private fun setDarkMode() {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
}
36 changes: 0 additions & 36 deletions app/src/main/java/org/sopt/and/data/ApiFactory.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sopt.and.data.remote.model
package org.sopt.and.data.local

data class TodayTopData(
val painterId: Int,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.and.data.mapper.todata

import org.sopt.and.data.remote.model.request.UserLoginRequestDto
import org.sopt.and.domain.model.request.UserLoginModel

fun UserLoginModel.toData() : UserLoginRequestDto = UserLoginRequestDto(
username = this.username,
password = this.password
)
Comment on lines +6 to +9

Choose a reason for hiding this comment

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

mapper 함수 네이밍이 조금 더 자세하면 좋을 것 같아요 ~ 저는 주로 toRequestLoginDto 같은 형태를 사용한답니다
그치만 정답은 없어요 !

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.and.data.mapper.todata

import org.sopt.and.data.remote.model.request.UserSignUpRequestDto
import org.sopt.and.domain.model.request.UserSignUpModel

fun UserSignUpModel.toData() : UserSignUpRequestDto = UserSignUpRequestDto(
username = this.username,
password = this.password,
hobby = this.hobby
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.sopt.and.data.mapper.todomain

import org.sopt.and.data.remote.model.response.UserHobbyResponseDto
import org.sopt.and.domain.model.response.Hobby

fun UserHobbyResponseDto.toDomain(): Hobby = Hobby(
hobby = this.hobby
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.sopt.and.data.mapper.todomain

import org.sopt.and.data.remote.model.response.UserSignUpResponseDto
import org.sopt.and.domain.model.response.UserNumber

fun UserSignUpResponseDto.toDomain(): UserNumber = UserNumber(
no = this.no
gitsuhyun marked this conversation as resolved.
Show resolved Hide resolved
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.sopt.and.data.mapper.todomain

import org.sopt.and.data.remote.model.response.UserTokenResponseDto
import org.sopt.and.domain.model.response.Token

fun UserTokenResponseDto.toDomain(): Token = Token(
token = this.token
)

Choose a reason for hiding this comment

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

제가 Mapper를 사용하지 않아서 데이터 변환에 많은 고생을 했는데 Mapper를 꼭 써야겠다는 생각이 드네요

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.sopt.and.data.remote.datasource

import org.sopt.and.data.remote.model.base.ApiResponse
import org.sopt.and.data.remote.model.request.UserLoginRequestDto
import org.sopt.and.data.remote.model.request.UserSignUpRequestDto
import org.sopt.and.data.remote.model.response.UserHobbyResponseDto
import org.sopt.and.data.remote.model.response.UserSignUpResponseDto
import org.sopt.and.data.remote.model.response.UserTokenResponseDto

interface UserDataRemoteSource {
suspend fun postUserSignUp(userSignUpRequestDto: UserSignUpRequestDto): ApiResponse<UserSignUpResponseDto>
suspend fun postUserLogin(userLoginRequestDto: UserLoginRequestDto): ApiResponse<UserTokenResponseDto>
suspend fun getUserHobby(token: String): ApiResponse<UserHobbyResponseDto>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.sopt.and.data.remote.datasourceimpl

import org.sopt.and.data.remote.datasource.UserDataRemoteSource
import org.sopt.and.data.remote.model.base.ApiResponse
import org.sopt.and.data.remote.model.request.UserLoginRequestDto
import org.sopt.and.data.remote.model.request.UserSignUpRequestDto
import org.sopt.and.data.remote.model.response.UserHobbyResponseDto
import org.sopt.and.data.remote.model.response.UserSignUpResponseDto
import org.sopt.and.data.remote.model.response.UserTokenResponseDto
import org.sopt.and.data.remote.service.UserService
import javax.inject.Inject

class UserDataRemoteSourceImpl @Inject constructor(
private val userService: UserService
) : UserDataRemoteSource {

override suspend fun postUserSignUp(userSignUpRequestDto: UserSignUpRequestDto): ApiResponse<UserSignUpResponseDto> =
userService.postUserSignUp(body = userSignUpRequestDto)

override suspend fun postUserLogin(userLoginRequestDto: UserLoginRequestDto): ApiResponse<UserTokenResponseDto> =
userService.postUserLogin(body = userLoginRequestDto)


override suspend fun getUserHobby(token: String): ApiResponse<UserHobbyResponseDto> =
userService.getUserHobby(token = token)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sopt.and.data.network.service
package org.sopt.and.data.remote.service

import org.sopt.and.data.remote.model.base.ApiResponse
import org.sopt.and.data.remote.model.request.UserLoginRequestDto
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.sopt.and.data.remote.utils

import org.sopt.and.data.remote.model.base.ApiResponse

fun <T> ApiResponse<T>.handleApiResponse(): Result<T> {
return try {
Result.success(this.result)
} catch (e: Exception) {
Result.failure(e)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.sopt.and.data.repositoryimpl

import org.sopt.and.data.mapper.todata.toData
import org.sopt.and.data.mapper.todomain.toDomain
import org.sopt.and.data.remote.datasource.UserDataRemoteSource
import org.sopt.and.data.remote.utils.handleApiResponse
import org.sopt.and.domain.model.request.UserLoginModel
import org.sopt.and.domain.model.request.UserSignUpModel
import org.sopt.and.domain.model.response.Hobby
import org.sopt.and.domain.model.response.Token
import org.sopt.and.domain.model.response.UserNumber
import org.sopt.and.domain.repository.UserRepository
import javax.inject.Inject

class UserRepositoryImpl @Inject constructor(
private val userDataRemoteSource: UserDataRemoteSource
) : UserRepository {

override suspend fun postUserSignUp(userSignUpModel: UserSignUpModel): Result<UserNumber> {
return runCatching {
userDataRemoteSource.postUserSignUp(userSignUpModel.toData()).handleApiResponse().getOrThrow().toDomain()
}
}

override suspend fun postUserLogin(userLoginModel: UserLoginModel): Result<Token> {
return runCatching {
userDataRemoteSource.postUserLogin(userLoginModel.toData()).handleApiResponse().getOrThrow().toDomain()
}
}

override suspend fun getUserHobby(token: String): Result<Hobby> {
return runCatching {
userDataRemoteSource.getUserHobby(token = token).handleApiResponse().getOrThrow().toDomain()
}
}
}
19 changes: 19 additions & 0 deletions app/src/main/java/org/sopt/and/di/DataSourceModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.sopt.and.di

import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.sopt.and.data.remote.datasource.UserDataRemoteSource
import org.sopt.and.data.remote.datasourceimpl.UserDataRemoteSourceImpl
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class DataSourceModule {
@Binds
@Singleton
abstract fun bindUserDataRemoteSource(
userDataRemoteSourceImpl: UserDataRemoteSourceImpl
): UserDataRemoteSource
}
Comment on lines +11 to +19

Choose a reason for hiding this comment

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

저와는 다르게 data 폴더와 di 폴더를 아예 구분하셨군요 ! 굿굿 좋아요 ~

90 changes: 90 additions & 0 deletions app/src/main/java/org/sopt/and/di/NetworkModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package org.sopt.and.di

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.Interceptor
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.sopt.and.BuildConfig
import retrofit2.Retrofit
import java.util.concurrent.TimeUnit
import javax.inject.Qualifier
import javax.inject.Singleton

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class Wavve

Choose a reason for hiding this comment

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

이 부분은 혹시 어디서 쓰일까요 ?!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

동일한 타입의 retrofit 객체가 여러개여서 이를 구분하려는 용도로 사용했어요! 그런데 지금 생각해보니 과제에서는 불필요한 것 같네용


@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun providesOkHttpClient(
loggingInterceptor: HttpLoggingInterceptor,
authInterceptor: Interceptor
): OkHttpClient =
OkHttpClient.Builder().apply {
connectTimeout(10, TimeUnit.SECONDS)
writeTimeout(10, TimeUnit.SECONDS)
readTimeout(10, TimeUnit.SECONDS)
addInterceptor(authInterceptor)
}.build()

@Provides
@Singleton
fun providesJson(): Json =
Json {
isLenient = true
prettyPrint = true
explicitNulls = false
ignoreUnknownKeys = true
}

@Provides
@Singleton
fun provideLoggingInterceptor(): HttpLoggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}

@Provides
@Singleton
fun provideAuthInterceptor(): Interceptor = Interceptor { chain ->
val request = chain.request().newBuilder()
.addHeader("Authorization", "Bearer <Your_Token_Here>")
.build()
chain.proceed(request)
}

@Provides
@Singleton
fun provideRetrofit(
okHttpClient: OkHttpClient,
json: Json
): Retrofit {
return Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.client(okHttpClient)
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
.build()
}

@Provides
@Singleton
@Wavve
fun provideWavveRetrofit(
okHttpClient: OkHttpClient,
json: Json
): Retrofit {
return Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.client(okHttpClient)
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
.build()
}
}
20 changes: 20 additions & 0 deletions app/src/main/java/org/sopt/and/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.sopt.and.di

import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.sopt.and.data.repositoryimpl.UserRepositoryImpl
import org.sopt.and.domain.repository.UserRepository
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindUserRepository(
userRepositoryImpl: UserRepositoryImpl
): UserRepository

}
Loading