-
Notifications
You must be signed in to change notification settings - Fork 0
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
base: develop
Are you sure you want to change the base?
Changes from all commits
148c3d2
eca37a7
75519a4
13cbd4f
265203e
84616e6
b5b6e0f
084407f
41840c9
6c47389
37d3db6
6db3300
a3176cf
450ed5e
4538e9b
db02568
f68a47e
9712368
52c7573
5748826
765cb5f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
@@ -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" | ||
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. 오호 ui가 아니라 feature로 패키지를 구성하셨군요 |
||
android:exported="true" | ||
android:theme="@style/Theme.ANDANDROID" | ||
android:windowSoftInputMode="adjustResize"> | ||
|
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() | ||
|
||
} | ||
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. 깔끔 그 자체에요. 코드 너무 좋아요 |
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" | ||
} | ||
} |
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 | ||
} | ||
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. 데이터스토어 모듈을 따로 만드셨네요. 저도 분리해야겠어요. |
||
|
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") | ||||||||||||||||||
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. 세미나에서 배운것은 이 중괄호 블럭이 없는데 이 블럭이 추가되면서 어떤 추가적인 정보를 볼 수 있나요? 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. 로그는 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
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. 릴리즈에는 필요없는 interceptor이므로 디버그 앱에만 추가해주심이 어떨까요
Suggested change
|
||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
@Singleton | ||||||||||||||||||
@Provides | ||||||||||||||||||
fun provideRetrofit(okHttpClient: OkHttpClient, json: Json): Retrofit { | ||||||||||||||||||
return Retrofit.Builder() | ||||||||||||||||||
.baseUrl(BASE_URL) | ||||||||||||||||||
.client(okHttpClient) | ||||||||||||||||||
.addConverterFactory(json.asConverterFactory(CONTENT_TYPE.toMediaType())) | ||||||||||||||||||
.build() | ||||||||||||||||||
} | ||||||||||||||||||
} |
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 | ||
} |
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( | ||
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. 요거는 엔티티를 디티오로 바꾸는 거니까 엔티티가 주체잖아요!! 그래서 저라면 엔티티에 해당함수를 구현할 것 같아요 |
||
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") | ||
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. 변수명과 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 | ||
) | ||
|
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( | ||
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. 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( | ||
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. 신기한 문법들 |
||
hobby = hobby | ||
) | ||
} |
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.
okhttp랑 retrofit처럼 같은 카테고리인 친구들은 각각 libs.versions.toml 내부에서 bundles로 묶어서 한번에 디펜던시 추가해줄 수 있서요! 그러면 더 보기 깔끔할 듯합니당