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

[Feat/#8] 4주차 필수 과제 #9

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open

[Feat/#8] 4주차 필수 과제 #9

wants to merge 6 commits into from

Conversation

hwidung
Copy link
Contributor

@hwidung hwidung commented Nov 15, 2024

Related issue 🛠

Work Description ✏️

  • 필수 과제의 유저 등록, 로그인, 내 취미 조회 api 연동을 완료했습니다.
  • coroutine을 사용하여 구현해 보았습니다..!

Screenshot 📸

2024-11-15.1.36.09.mov

2024-11-15.1.37.34.mov

그런데 제가 지금 에뮬을 바꾸고 초기화 해봐도 같은 현상이 발생하는데요 ....
로그인 버튼 누르고 홈화면 넘어갈 때 한 30초 동안 번쩍 번쩍 대는데용 ... 번쩍 대는 거 끝나면 다 제 기능을 잘 잘동 하지만 !!! 이게 뭔가 싶습니다 !!

2024-11-15.1.36.30.mov

아래는 이러한 로그가 마구마구 찍히고 있는데 혹시 같은 문제를 경험하신 분이나 해결책을 아시는 분 있으면 도와주십사 .. 하고 영상 남깁니다!! ..

스크린샷 2024-11-15 오후 1 38 03

Uncompleted Tasks 😅

  • [ ]

To Reviewers 📢

감사합니답

@hwidung hwidung requested review from SYAAINN, a team, cacaocoffee, Marchbreeze and jihyunniiii and removed request for a team November 15, 2024 05:26
Copy link

@jangsjw jangsjw left a comment

Choose a reason for hiding this comment

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

이번 주차에는 리뷰해야 할 부분이 제 눈에는 많이 보이지 않습니다..ㅠ 이번 주차도 고생하셨습니다!!!

Comment on lines +8 to +9
interface HobbyService {
@GET("/user/my-hobby")
Copy link

Choose a reason for hiding this comment

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

"/user/my-hobby"는 하드코딩되어 있는데, 변경 시 유지보수성이 떨어질 수 있다고 합니다! 이를 상수화하면 관리가 더 편리할 수 있습니다!

Copy link

@cacaocoffee cacaocoffee left a comment

Choose a reason for hiding this comment

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

로그랑 영상보니까 객체가 너무 빨리 생성되어서 main 스레드에 부하가 크게 걸려 GC의 호출이 자주 되는 거 같아요

객체 생성을 줄이거나 천천히 할 수 있게 해야할 거 같네요.

코루틴 사용시 다음과 같이 사용하면 스레드의 부담을 줄일 수 도 있답니다.

withContext(Dispatchers.IO) {
   //실행 
}

도 넣어볼 수 있을 거 같네요

저부분은 저도 한번 찾아보고 다시 올게요! 이번주 과제도 수고하셨습니다.!

Comment on lines +12 to +24
interface UserRegistrationService {
@POST("/user")
suspend fun postUserRegistration(
@Body userRequest: RequestUserRegistrationData
): Response<ResponseUserRegistration>
}

interface LoginService {
@POST("/login")
suspend fun postLogin(
@Body loginRequeset: RequestLoginData
): Response<ResponseLogin>
}

Choose a reason for hiding this comment

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

AuthService 라는 이름에 맞춰서 다음처럼 하나의 인터페이스로 구현하는 건 어떤가요?

Suggested change
interface UserRegistrationService {
@POST("/user")
suspend fun postUserRegistration(
@Body userRequest: RequestUserRegistrationData
): Response<ResponseUserRegistration>
}
interface LoginService {
@POST("/login")
suspend fun postLogin(
@Body loginRequeset: RequestLoginData
): Response<ResponseLogin>
}
interface AuthService{
@POST("/user")
suspend fun postUserRegistration(
@Body userRequest: RequestUserRegistrationData
): Response<ResponseUserRegistration>
@POST("/login")
suspend fun postLogin(
@Body loginRequeset: RequestLoginData
): Response<ResponseLogin>
}

class UserRegistrationRepository @Inject constructor(
private val apiService: UserRegistrationService
) {
suspend fun postUserRegistration(requestData: RequestUserRegistrationData): Result<ResponseUserRegistration> {

Choose a reason for hiding this comment

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

저는 서버 통신하는 부분은 return 문이 없는게 보기 좋더라구요
이런식으로도 사용가능합니다.

suspend fun postUserRegistration(
    requestData: RequestUserRegistrationData
): Result<ResponseUserRegistration> = try { 
    val response = apiService.postUserRegistration(requestData)
    if (response.isSuccessful) {
        Result.success(response.body()!!)
    } else {
        val errorCode = response.errorBody()?.string() ?: "알수없슴"
        Result.failure(Exception("Error code : ${response.code()}, 에러 코드 : $errorCode"))
    }
} catch (e: Exception) {
    Result.failure(e)
}

Comment on lines +25 to +26
val result = myviewRepository.getHobby(token)
_hobbyResult.postValue(result)
Copy link

@cacaocoffee cacaocoffee Nov 17, 2024

Choose a reason for hiding this comment

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

의심되는 부분은 여기인데 아래처럼 바꿔도 안되면 ui 쪽에 문제인거 같네요

Suggested change
val result = myviewRepository.getHobby(token)
_hobbyResult.postValue(result)
val result = withContext(Dispatchers.IO) { myviewRepository.getHobby(token) }
_hobbyResult.postValue(result)

Choose a reason for hiding this comment

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

라이브 데이터에 관한 문제로 생길 수 도 있다고 하니 아래 한번 참고해보셔도 좋을거같아요

https://jminie.tistory.com/188#3.2.%20%EB%B9%84%EB%8F%99%EA%B8%B0%20%EC%9E%91%EC%97%85%20%EC%B8%A1%EB%A9%B4%EC%97%90%EC%84%9C%20LiveData%EC%9D%98%20%EB%8B%A8%EC%A0%90

Copy link

Choose a reason for hiding this comment

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

[3]
LiveData 대신 StateFlow를 사용하는 방법도 있을 것 같습니다 ㅎㅎ 두 개는 어떤 차이가 있을까요?

Copy link

@SYAAINN SYAAINN left a comment

Choose a reason for hiding this comment

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

예상치 못한 힐트의 등장 ㄷㄷ.. 휘둥 그녀는 도대체 조용히 어디까지 성장하는가

Copy link

Choose a reason for hiding this comment

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

[2]
Hilt 도입 ㄷㄷ.. 대단하네요
현재 파일에 Activity, Application, Composable 여러가지가 모두 들어가 있다보니 파일을 분리해준다면 조금 더 가독성이 좋아질 것 같아요!

Comment on lines +42 to +52
@Provides
@Singleton
fun provideUserRegistrationService(retrofit: Retrofit): UserRegistrationService {
return retrofit.create(UserRegistrationService::class.java)
}

@Provides
@Singleton
fun provideLoginService(retrofit: Retrofit): LoginService {
return retrofit.create(LoginService::class.java)
}
Copy link

Choose a reason for hiding this comment

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

[2]
하나의 interface에 여러가지 api가 들어가도 무관합니다!
따라서 api의 특성에 따라 service interface를 어떻게 분리할 지 생각해보는 것도 좋을거 같아요.
그런데 이미 파일명을 AuthService라고 잘 해놓으셨네요! 하나로 통합시킨 후 의존성 주입 부분도 AuthService 하나로 통일하면 더 좋을 것 같습니다!

Copy link

Choose a reason for hiding this comment

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

[3]
service interface를 구현할때 callback을 사용할 때와 달리 suspend fun 을 사용해야만 했던 이유는 무엇일까요? 학습해보면 좋을 것 같습니다!

Copy link

Choose a reason for hiding this comment

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

[2]
AuthService에서 사용한다는 공통점으로 묶은 부분은 좋았지만 추후 프로젝트 규모가 조금이라도 커졌을 때를 대비해 Dto 파일을 분리하는 연습을 해보면 좋을 것 같습니다! 일반적으로는 크게 request와 response에 따라 구분합니다!

Copy link

Choose a reason for hiding this comment

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

[3]
callBack이 아닌 try-catch를 사용하신 이유가 있을까요? 어떤 이점이 있을거라 생각하셨나요?

Copy link

Choose a reason for hiding this comment

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

[3]
runCatching이라는 방법을 사용할 수도 있는데 차이점을 알아보는 것도 좋을 것 같습니다!

Comment on lines +25 to +26
val result = myviewRepository.getHobby(token)
_hobbyResult.postValue(result)
Copy link

Choose a reason for hiding this comment

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

[3]
LiveData 대신 StateFlow를 사용하는 방법도 있을 것 같습니다 ㅎㅎ 두 개는 어떤 차이가 있을까요?

Copy link

@jihyunniiii jihyunniiii left a comment

Choose a reason for hiding this comment

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

수고하셨습니다 ~ 합세 파이띵

Comment on lines +8 to +9
id("kotlin-kapt")
id("com.google.dagger.hilt.android")

Choose a reason for hiding this comment

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

버전 카탈로그를 이용해주셔도 좋을 것 같네요 ~ 그리고 id와 alias의 차이는 뭘까요?

Comment on lines +38 to +42
@Serializable
data class ResponseLogin(
@SerialName("result")
val result: ResultToken
)

Choose a reason for hiding this comment

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

공통되는 부분에 대해 BaseResponse를 만든 후 사용하시면 가독성이 더 좋아질 것 같아요!

return try {
val response = apiService.postLogin(requestData)
if (response.isSuccessful) {
Result.success(response.body()!!)

Choose a reason for hiding this comment

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

!! 사용은 지양합시다. NPE가 발생할 수 있어요.


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

Choose a reason for hiding this comment

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

AppModule이라고 네이밍 하신 이유가 있나요?

}
} else {
val errorMessage = result.exceptionOrNull()?.message ?: "회원가입 실패"
Log.e("signupscreen", errorMessage)

Choose a reason for hiding this comment

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

불필요한 로그는 지워줍시다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[feat] 4주차 과제
5 participants