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

[Week4] 4주차 필수 과제 #12

Open
wants to merge 21 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 17 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import java.util.Properties

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
Expand All @@ -7,6 +9,10 @@ plugins {
alias(libs.plugins.kotlin.serialization)
}

val properties = Properties().apply {
load(project.rootProject.file("local.properties").inputStream())
}

android {
namespace = "org.sopt.and"
compileSdk = 34
Expand All @@ -19,6 +25,8 @@ android {
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

buildConfigField("String", "BASE_URL", properties["base.url"].toString())
}

buildTypes {
Expand All @@ -39,6 +47,7 @@ android {
}
buildFeatures {
compose = true
buildConfig = true
}
}

Expand Down Expand Up @@ -72,4 +81,12 @@ dependencies {
//navigation
implementation(libs.androidx.compose.navigation)
implementation(libs.kotlinx.serialization.json)

// Network
implementation(platform(libs.okhttp.bom))
implementation(libs.okhttp)

Choose a reason for hiding this comment

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

okhttp랑 retrofit처럼 같은 카테고리인 친구들은 각각 libs.versions.toml 내부에서 bundles로 묶어서 한번에 디펜던시 추가해줄 수 있서요! 그러면 더 보기 깔끔할 듯합니당

implementation(libs.okhttp.logging.interceptor)
implementation(libs.retrofit)
implementation(libs.retrofit.kotlin.serialization.converter)
implementation(libs.kotlinx.serialization.json)
}
7 changes: 5 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:name=".App"
android:name=".WavveApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand All @@ -12,9 +14,10 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ANDANDROID"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".main.MainActivity"
android:name=".feature.main.MainActivity"

Choose a reason for hiding this comment

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

오호 ui가 아니라 feature로 패키지를 구성하셨군요
새로운 네이밍 좋네요

android:exported="true"
android:theme="@style/Theme.ANDANDROID"
android:windowSoftInputMode="adjustResize">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class App : Application()
class WavveApplication : Application()
2 changes: 1 addition & 1 deletion app/src/main/java/org/sopt/and/component/HomeContent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import androidx.compose.ui.unit.sp
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import org.sopt.and.R
import org.sopt.and.home.model.ContentModel
import org.sopt.and.feature.home.model.ContentModel
import org.sopt.and.ui.theme.ANDANDROIDTheme
import org.sopt.and.ui.theme.White

Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/org/sopt/and/data/datasource/WavveDataSource.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.sopt.and.data.datasource

import org.sopt.and.data.dto.request.RequestSignInDto
import org.sopt.and.data.dto.request.RequestSignUpDto
import org.sopt.and.data.dto.response.BaseResponse
import org.sopt.and.data.dto.response.ResponseUserHobbyDto
import org.sopt.and.data.dto.response.ResponseSignInDto
import org.sopt.and.data.dto.response.ResponseSignUpDto

interface WavveDataSource {
suspend fun postSignUp(requestSignUpDto: RequestSignUpDto): BaseResponse<ResponseSignUpDto>
suspend fun postSignIn(requestSignInDto: RequestSignInDto): BaseResponse<ResponseSignInDto>
suspend fun getUserHobby(): BaseResponse<ResponseUserHobbyDto>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.sopt.and.data.datasourceimpl

import org.sopt.and.data.datasource.WavveDataSource
import org.sopt.and.data.dto.request.RequestSignInDto
import org.sopt.and.data.dto.request.RequestSignUpDto
import org.sopt.and.data.dto.response.BaseResponse
import org.sopt.and.data.dto.response.ResponseUserHobbyDto
import org.sopt.and.data.dto.response.ResponseSignInDto
import org.sopt.and.data.dto.response.ResponseSignUpDto
import org.sopt.and.data.service.WavveService
import javax.inject.Inject

class WavveDataSourceImpl @Inject constructor(
val wavveService: WavveService
) : WavveDataSource {
override suspend fun postSignUp(requestSignUpDto: RequestSignUpDto): BaseResponse<ResponseSignUpDto> =
wavveService.postSignUp(requestSignUpDto)

override suspend fun postSignIn(requestSignInDto: RequestSignInDto): BaseResponse<ResponseSignInDto> =
wavveService.postSignIn(requestSignInDto)

override suspend fun getUserHobby(): BaseResponse<ResponseUserHobbyDto> =
wavveService.getUserHobby()

}
Copy link
Contributor

Choose a reason for hiding this comment

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

깔끔 그 자체에요. 코드 너무 좋아요

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

import okhttp3.Interceptor
import okhttp3.Response
import org.sopt.and.sharedpreference.User
import javax.inject.Inject

class AuthInterceptor @Inject constructor(private val user: User) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {

val token = user.getUserToken()

val request = chain.request().newBuilder()
.apply {
token?.let {
addHeader(TOKEN, token)
}
}
.build()

return chain.proceed(request)
}

companion object {
const val TOKEN: String = "token"
}
}
18 changes: 18 additions & 0 deletions app/src/main/java/org/sopt/and/data/di/DataSourceModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.sopt.and.data.di

import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.sopt.and.data.datasource.WavveDataSource
import org.sopt.and.data.datasourceimpl.WavveDataSourceImpl
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
internal abstract class DataSourceModule {
@Binds
@Singleton
abstract fun bindsDataSource(myDataSourceImpl: WavveDataSourceImpl): WavveDataSource
}
Copy link
Contributor

Choose a reason for hiding this comment

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

데이터스토어 모듈을 따로 만드셨네요. 저도 분리해야겠어요.


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

import android.util.Log
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 org.sopt.and.BuildConfig
import org.sopt.and.sharedpreference.User
import retrofit2.Retrofit
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

private const val CONTENT_TYPE = "application/json"
private const val BASE_URL = BuildConfig.BASE_URL

@Singleton
@Provides
fun provideJson(): Json {
return Json {
ignoreUnknownKeys = true
isLenient = true
encodeDefaults = true
}
}

@Singleton
@Provides
fun provideLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor { message ->
Log.d("Retrofit2", "CONNECTION INFO -> $message")

Choose a reason for hiding this comment

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

세미나에서 배운것은 이 중괄호 블럭이 없는데 이 블럭이 추가되면서 어떤 추가적인 정보를 볼 수 있나요?

Choose a reason for hiding this comment

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

로그는 PR 올릴 때 삭제해주시거나 Timber로 바꿔주시면 좋을 것 같아요!!

}.apply {
level = HttpLoggingInterceptor.Level.BODY
}
}


@Singleton
@Provides
fun provideAuthInterceptor(user: User): AuthInterceptor {
return AuthInterceptor(user)
}

@Singleton
@Provides
fun provideOkHttpClient(
loggingInterceptor: HttpLoggingInterceptor,
authInterceptor: AuthInterceptor
): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.addInterceptor(authInterceptor)
.build()
Comment on lines +58 to +61

Choose a reason for hiding this comment

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

릴리즈에는 필요없는 interceptor이므로 디버그 앱에만 추가해주심이 어떨까요

Suggested change
return OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.addInterceptor(authInterceptor)
.build()
val builder = OkHttpClient.Builder()
if (BuildConfig.DEBUG) builder.addInterceptor(loggingInterceptor)
builder.addInterceptor(authInterceptor)
return builder.build()

}

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

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

@Module
@InstallIn(SingletonComponent::class)
internal abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindsRepository(
myRepositoryImpl: WavveRepositoryImpl
): WavveRepository
}
18 changes: 18 additions & 0 deletions app/src/main/java/org/sopt/and/data/di/ServiceModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.sopt.and.data.di

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.sopt.and.data.service.WavveService
import retrofit2.Retrofit
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object ServiceModule {
@Provides
@Singleton
fun providerService(retrofit: Retrofit): WavveService =
retrofit.create(WavveService::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.sopt.and.data.dto.request

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.sopt.and.domain.entity.request.RequestSignInEntity

@Serializable
data class RequestSignInDto(
@SerialName("username")
val username: String,
@SerialName("password")
val password: String,
)

fun RequestSignInEntity.toDto() = RequestSignInDto(

Choose a reason for hiding this comment

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

요거는 엔티티를 디티오로 바꾸는 거니까 엔티티가 주체잖아요!! 그래서 저라면 엔티티에 해당함수를 구현할 것 같아요

username = username,
password = password
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.sopt.and.data.dto.request

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.sopt.and.domain.entity.request.RequestSignUpEntity

@Serializable
data class RequestSignUpDto(
@SerialName("username")

Choose a reason for hiding this comment

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

변수명과 json key명이 같은데도 SerialName 어노테이션을 굳이 써야하나요?

val username: String,
@SerialName("password")
val password: String,
@SerialName("hobby")
val hobby: String,
)

fun RequestSignUpEntity.toDto() = RequestSignUpDto(
username = username,
password = password,
hobby = hobby
)

11 changes: 11 additions & 0 deletions app/src/main/java/org/sopt/and/data/dto/response/BaseResponse.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.sopt.and.data.dto.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable


@Serializable
data class BaseResponse<T>(
@SerialName("result")
val result: T
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.sopt.and.data.dto.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.sopt.and.domain.entity.response.ResponseSignInEntity

@Serializable
data class ResponseSignInDto(
@SerialName("token")
val token: String
){
fun toEntity() = ResponseSignInEntity(
Copy link
Contributor

Choose a reason for hiding this comment

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

objcect에 Mapper를 모아두는 방식을 안쓰고 데이터 클래스에 바로 정의하신 이유 알려주실 수 있나요??

token = token
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.sopt.and.data.dto.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.sopt.and.domain.entity.response.ResponseSignUpEntity

@Serializable
data class ResponseSignUpDto(
@SerialName("no")
val no: Int
) {
fun toEntity() = ResponseSignUpEntity(
id = no
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.sopt.and.data.dto.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.sopt.and.domain.entity.response.ResponseHobbyEntity

@Serializable
data class ResponseUserHobbyDto(
@SerialName("hobby")
val hobby: String
){
fun toEntity() = ResponseHobbyEntity(

Choose a reason for hiding this comment

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

신기한 문법들

hobby = hobby
)
}
Loading