-
Notifications
You must be signed in to change notification settings - Fork 0
[Feature/#18] 로그인 api 연동 #21
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
Conversation
- 레이어 모듈간 의존성 추가 data -> domain <- presentation - 불필요한 .gitkeep 파일 제거
- AuthTokenSerializerImpl 의존성 주입 추가 - datastore 모듈 datastore-preferences 의존성 api로 변경
- AuthSession 모델 클래스 추가 - AuthRepository 인터페이스 추가 - LoginUseCase 클래스 구현
- AuthService, AuthRemoteDataSource, AuthRepository 구현 - 로그인 API 연동 및 관련 DTO, Mapper, SafeApiCall 구현 - Hilt를 사용하여 의존성 주입 설정 (DataSourceModule, RepositoryModule, ServiceModule)
- AuthLocalDataSource 및 구현체 AuthLocalDataSourceImpl 추가 - LoginUseCase에서 로그인 성공 시 토큰 저장 로직 추가
- UserRole enum class를 정의하여 사용자 역할 관리
- 로그인 결과에 따라 Home 또는 약관 동의 화면으로 이동하도록 SideEffect 추가
## Walkthrough
로그인 API 연동을 위해 도메인, 데이터, 프레젠테이션, 네트워크, 데이터스토어 계층 전반에 걸쳐 인증 관련 모델, 데이터소스, 레포지토리, 유즈케이스, DI 모듈, 서비스, 에러 처리, 토큰 저장 및 인터셉터 로직이 추가 및 리팩토링되었습니다. 전반적으로 로그인 플로우와 토큰 관리의 전체 구조가 구현되었습니다.
## Changes
| 파일/그룹 | 변경 요약 |
|---|---|
| **도메인 계층**<br>domain/src/main/java/com/threegap/bitnagil/domain/auth/model/AuthSession.kt<br>domain/src/main/java/com/threegap/bitnagil/domain/auth/model/UserRole.kt<br>domain/src/main/java/com/threegap/bitnagil/domain/auth/repository/AuthRepository.kt<br>domain/src/main/java/com/threegap/bitnagil/domain/auth/usecase/LoginUseCase.kt<br>domain/src/main/java/com/threegap/bitnagil/domain/error/model/BitnagilError.kt | 인증 세션, 역할, 레포지토리, 유즈케이스, 에러 모델 등 로그인 도메인 모델 및 인터페이스/클래스 추가 |
| **데이터 계층**<br>data/src/main/java/com/threegap/bitnagil/data/auth/datasource/AuthLocalDataSource.kt<br>data/src/main/java/com/threegap/bitnagil/data/auth/datasource/AuthRemoteDataSource.kt<br>data/src/main/java/com/threegap/bitnagil/data/auth/datasourceimpl/AuthLocalDataSourceImpl.kt<br>data/src/main/java/com/threegap/bitnagil/data/auth/datasourceimpl/AuthRemoteDataSourceImpl.kt<br>data/src/main/java/com/threegap/bitnagil/data/auth/mapper/AuthMapper.kt<br>data/src/main/java/com/threegap/bitnagil/data/auth/model/request/LoginRequestDto.kt<br>data/src/main/java/com/threegap/bitnagil/data/auth/model/response/LoginResponseDto.kt<br>data/src/main/java/com/threegap/bitnagil/data/auth/repositoryimpl/AuthRepositoryImpl.kt<br>data/src/main/java/com/threegap/bitnagil/data/auth/service/AuthService.kt<br>data/src/main/java/com/threegap/bitnagil/data/common/SafeApiCall.kt | 인증 관련 데이터소스, DTO, 매퍼, 레포지토리 구현 및 네트워크 응답/에러 처리 유틸 추가 |
| **DI 모듈**<br>app/src/main/java/com/threegap/bitnagil/di/core/DataStoreModule.kt<br>app/src/main/java/com/threegap/bitnagil/di/core/NetworkModule.kt<br>app/src/main/java/com/threegap/bitnagil/di/data/DataSourceModule.kt<br>app/src/main/java/com/threegap/bitnagil/di/data/RepositoryModule.kt<br>app/src/main/java/com/threegap/bitnagil/di/data/ServiceModule.kt | 데이터소스, 레포지토리, 서비스, 토큰 직렬화기, 토큰 프로바이더 등 DI 바인딩 및 프로바이더 추가/수정 |
| **데이터스토어/토큰**<br>core/datastore/src/main/java/com/threegap/bitnagil/datastore/auth/serializer/AuthTokenSerializerImpl.kt<br>core/datastore/src/main/java/com/threegap/bitnagil/datastore/auth/storage/AuthTokenDataStore.kt<br>core/datastore/src/main/java/com/threegap/bitnagil/datastore/auth/storage/AuthTokenDataStoreImpl.kt | 토큰 직렬화기 인터페이스 변경, 데이터스토어 인터페이스 및 구현의 시그니처 및 예외 처리 방식 변경 |
| **네트워크**<br>core/network/src/main/java/com/threegap/bitnagil/network/auth/AuthInterceptor.kt<br>core/network/src/main/java/com/threegap/bitnagil/network/model/ErrorResponse.kt<br>core/network/src/main/java/com/threegap/bitnagil/network/token/TokenProvider.kt | 인증 인터셉터 토큰 주입 로직 개선, 에러 응답 모델 추가, TokenProvider 시그니처 변경 |
| **프레젠테이션**<br>presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginScreen.kt<br>presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginViewModel.kt<br>presentation/src/main/java/com/threegap/bitnagil/presentation/login/model/LoginSideEffect.kt<br>presentation/src/main/java/com/threegap/bitnagil/presentation/login/model/LoginState.kt<br>presentation/src/main/java/com/threegap/bitnagil/presentation/login/model/LoginIntent.kt<br>presentation/src/main/java/com/threegap/bitnagil/presentation/login/kakao/KakaoLoginHandler.kt<br>presentation/src/main/java/com/threegap/bitnagil/presentation/login/kakao/KakaoLoginHandlerImpl.kt | 로그인 화면, 뷰모델, 상태, 사이드이펙트, 인텐트, 카카오 로그인 핸들러 인터페이스 및 구현 추가/리팩토링 |
| **빌드 설정**<br>data/build.gradle.kts<br>domain/build.gradle.kts<br>core/datastore/build.gradle.kts<br>presentation/build.gradle.kts | 각 모듈별 의존성 추가 및 플러그인 설정 변경 |
## Sequence Diagram(s)
```mermaid
sequenceDiagram
participant User
participant LoginScreen
participant LoginViewModel
participant LoginUseCase
participant AuthRepository
participant AuthRemoteDataSource
participant AuthLocalDataSource
participant AuthService
participant AuthTokenDataStore
User->>LoginScreen: 로그인 시도
LoginScreen->>LoginViewModel: OnKakaoLoginResult(intent)
LoginViewModel->>LoginUseCase: invoke(socialAccessToken, socialType)
LoginUseCase->>AuthRepository: login(socialAccessToken, socialType)
AuthRepository->>AuthRemoteDataSource: login(token, dto)
AuthRemoteDataSource->>AuthService: postLogin(token, dto)
AuthService-->>AuthRemoteDataSource: BaseResponse<LoginResponseDto>
AuthRemoteDataSource-->>AuthRepository: Result<LoginResponseDto>
AuthRepository-->>LoginUseCase: Result<AuthSession>
LoginUseCase->>AuthRepository: updateAuthToken(accessToken, refreshToken)
AuthRepository->>AuthLocalDataSource: updateAuthToken(accessToken, refreshToken)
AuthLocalDataSource->>AuthTokenDataStore: updateAuthToken(accessToken, refreshToken)
AuthTokenDataStore-->>AuthLocalDataSource: Unit
AuthLocalDataSource-->>AuthRepository: Result<Unit>
LoginUseCase-->>LoginViewModel: Result<AuthSession>
LoginViewModel->>LoginScreen: 상태/사이드이펙트 업데이트Assessment against linked issues
Possibly related PRs
Suggested reviewers
Poem
|
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.
Actionable comments posted: 3
🧹 Nitpick comments (9)
core/network/src/main/java/com/threegap/bitnagil/network/model/ErrorResponse.kt (1)
6-12:@SerialName제거 검토프로퍼티 이름과 JSON 필드가 동일하므로
@SerialName애너테이션이 사실상 불필요합니다. 유지 보수성을 위해 불필요한 메타데이터를 줄이는 편이 가독성에 도움이 됩니다.- @SerialName("code") - val code: String, - @SerialName("message") - val message: String, + val code: String, + val message: String,domain/build.gradle.kts (1)
5-8:javax.inject의존성 범위 재검토
domain모듈은 프레임워크 독립성을 유지하는 것이 일반적인데,javax.inject는 러untime에도 포함됩니다.
필요한 것이 어노테이션만이라면 다음과 같이compileOnly로 변경해 바이너리 크기를 줄일 수 있습니다.- implementation(libs.javax.inject) + compileOnly(libs.javax.inject)core/datastore/build.gradle.kts (1)
10-13:api노출이 과도할 수 있음
androidx.datastore.preferences를api로 공개하면 상위 모듈이 Datastore 구현 세부사항에 직접 접근할 수 있습니다.
의도적으로 노출하는 것이 아니라면 기존implementation을 유지하는 편이 캡슐레이션에 유리합니다.presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginScreen.kt (1)
44-50: TODO 주석 완료 추적 필요새로운 네비게이션 side effect들이 추가되었지만 TODO 주석으로 남아있습니다. 이슈 트래킹을 통해 완료 일정을 관리해주세요.
네비게이션 로직 구현을 위한 새로운 이슈를 생성하시겠습니까?
domain/src/main/java/com/threegap/bitnagil/domain/error/model/BitnagilError.kt (1)
3-6: 도메인 에러 모델 구현 양호커스텀 예외 클래스가 적절히 구현되었습니다. Exception을 상속하고 code와 message를 포함하는 구조가 좋습니다.
더 나은 타입 안전성을 위해 code 필드를 enum으로 변경하는 것을 고려해보세요:
+enum class ErrorCode { + NETWORK_ERROR, + AUTHENTICATION_ERROR, + VALIDATION_ERROR, + UNKNOWN_ERROR +} + data class BitnagilError( - val code: String, + val code: ErrorCode, override val message: String, ) : Exception()data/src/main/java/com/threegap/bitnagil/data/auth/model/response/LoginResponseDto.kt (1)
6-14: 응답 DTO 구현 양호, 보안 고려사항 검토 필요직렬화 어노테이션이 적절히 적용된 깔끔한 DTO 구현입니다.
보안 및 타입 안전성 개선을 위한 제안사항:
- role 필드를 enum으로 변경:
+enum class UserRole { + GUEST, MEMBER, ADMIN +} + @Serializable data class LoginResponseDto( @SerialName("accessToken") val accessToken: String, @SerialName("refreshToken") val refreshToken: String, @SerialName("role") - val role: String, + val role: UserRole, )
- 토큰 필드에 대한 추가 검증 로직 고려
data/src/main/java/com/threegap/bitnagil/data/auth/model/request/LoginRequestDto.kt (1)
6-10: 요청 DTO 구현 양호, 타입 안전성 개선 제안직렬화가 적절히 구현된 간단한 요청 DTO입니다.
타입 안전성 향상을 위해 socialType을 enum으로 변경하는 것을 고려해보세요:
+enum class SocialType { + @SerialName("kakao") + KAKAO, + @SerialName("naver") + NAVER, + @SerialName("google") + GOOGLE +} + @Serializable data class LoginRequestDto( @SerialName("socialType") - val socialType: String, + val socialType: SocialType, )이렇게 하면 컴파일 타임에 유효하지 않은 소셜 타입 값을 방지할 수 있습니다.
data/src/main/java/com/threegap/bitnagil/data/common/SafeApiCall.kt (2)
34-38: 예외 처리 타입 일관성을 개선해주세요.현재
HttpException은BitnagilError로 반환하지만IOException과 일반Exception은Exception으로 반환하여 일관성이 부족합니다. 모든 예외를BitnagilError로 통일하는 것을 고려해보세요.} catch (e: IOException) { - Result.failure(Exception(e.message ?: "Network error")) + Result.failure( + BitnagilError( + code = "NETWORK_ERROR", + message = e.message ?: "Network error", + ) + ) } catch (e: Exception) { - Result.failure(Exception(e.message ?: "Unknown error")) + Result.failure( + BitnagilError( + code = "UNKNOWN_ERROR", + message = e.message ?: "Unknown error", + ) + ) }
24-27: JSON 파싱 실패 시 예외 처리를 추가해주세요.
Json.decodeFromString호출 시 파싱 실패 예외가 발생할 수 있습니다. 예외 처리를 추가하여 안정성을 높이는 것을 고려해보세요.val errorResponse = errorBody?.let { - Json.decodeFromString<ErrorResponse>(it) + try { + Json.decodeFromString<ErrorResponse>(it) + } catch (e: Exception) { + null + } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (34)
app/src/main/java/com/threegap/bitnagil/di/core/DataStoreModule.kt(2 hunks)app/src/main/java/com/threegap/bitnagil/di/core/NetworkModule.kt(1 hunks)app/src/main/java/com/threegap/bitnagil/di/data/DataSourceModule.kt(1 hunks)app/src/main/java/com/threegap/bitnagil/di/data/RepositoryModule.kt(1 hunks)app/src/main/java/com/threegap/bitnagil/di/data/ServiceModule.kt(1 hunks)core/datastore/build.gradle.kts(1 hunks)core/datastore/src/main/java/com/threegap/bitnagil/datastore/auth/serializer/AuthTokenSerializerImpl.kt(1 hunks)core/datastore/src/main/java/com/threegap/bitnagil/datastore/auth/storage/AuthTokenDataStore.kt(1 hunks)core/datastore/src/main/java/com/threegap/bitnagil/datastore/auth/storage/AuthTokenDataStoreImpl.kt(1 hunks)core/network/src/main/java/com/threegap/bitnagil/network/auth/AuthInterceptor.kt(2 hunks)core/network/src/main/java/com/threegap/bitnagil/network/model/ErrorResponse.kt(1 hunks)core/network/src/main/java/com/threegap/bitnagil/network/token/TokenProvider.kt(1 hunks)data/build.gradle.kts(1 hunks)data/src/main/java/com/threegap/bitnagil/data/auth/datasource/AuthLocalDataSource.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/auth/datasource/AuthRemoteDataSource.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/auth/datasourceimpl/AuthLocalDataSourceImpl.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/auth/datasourceimpl/AuthRemoteDataSourceImpl.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/auth/mapper/AuthMapper.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/auth/model/request/LoginRequestDto.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/auth/model/response/LoginResponseDto.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/auth/repositoryimpl/AuthRepositoryImpl.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/auth/service/AuthService.kt(1 hunks)data/src/main/java/com/threegap/bitnagil/data/common/SafeApiCall.kt(1 hunks)domain/build.gradle.kts(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/auth/model/AuthSession.kt(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/auth/model/UserRole.kt(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/auth/repository/AuthRepository.kt(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/auth/usecase/LoginUseCase.kt(1 hunks)domain/src/main/java/com/threegap/bitnagil/domain/error/model/BitnagilError.kt(1 hunks)presentation/build.gradle.kts(2 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginScreen.kt(2 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginViewModel.kt(2 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/login/model/LoginSideEffect.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/login/model/LoginState.kt(1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: wjdrjs00
PR: YAPP-Github/Bitnagil-Android#16
File: core/network/src/main/java/com/threegap/bitnagil/network/auth/TokenAuthenticator.kt:12-46
Timestamp: 2025-07-03T09:05:30.067Z
Learning: 이 프로젝트에서는 네트워크 모듈을 점진적으로 개발하고 있으며, TokenAuthenticator 같은 인증 관련 기능은 실제 API 연동 작업 시점에 NetworkModule에 연결할 예정입니다.
app/src/main/java/com/threegap/bitnagil/di/core/NetworkModule.kt (1)
Learnt from: wjdrjs00
PR: YAPP-Github/Bitnagil-Android#16
File: core/network/src/main/java/com/threegap/bitnagil/network/auth/TokenAuthenticator.kt:12-46
Timestamp: 2025-07-03T09:05:30.067Z
Learning: 이 프로젝트에서는 네트워크 모듈을 점진적으로 개발하고 있으며, TokenAuthenticator 같은 인증 관련 기능은 실제 API 연동 작업 시점에 NetworkModule에 연결할 예정입니다.
core/datastore/src/main/java/com/threegap/bitnagil/datastore/auth/storage/AuthTokenDataStore.kt (1)
Learnt from: wjdrjs00
PR: YAPP-Github/Bitnagil-Android#19
File: core/network/src/main/java/com/threegap/bitnagil/network/auth/TokenAuthenticator.kt:16-20
Timestamp: 2025-07-06T04:26:03.870Z
Learning: TokenAuthenticator 클래스는 현재 임시 코드로 구현되어 있으며, 실제 토큰 재발급 API 연동 시점에 올바른 구현으로 수정될 예정입니다.
🧬 Code Graph Analysis (2)
data/src/main/java/com/threegap/bitnagil/data/auth/datasourceimpl/AuthRemoteDataSourceImpl.kt (1)
data/src/main/java/com/threegap/bitnagil/data/common/SafeApiCall.kt (1)
safeApiCall(10-39)
presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginViewModel.kt (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt (1)
sendSideEffect(23-23)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (30)
core/network/src/main/java/com/threegap/bitnagil/network/model/ErrorResponse.kt (1)
8-10:code타입 확인API 스펙상
code가 숫자라면Int타입으로 선언하는 편이 직관적이며, 문자열로 받아 숫자로 변환하는 비용을 줄일 수 있습니다. 스펙을 한 번 더 확인해 주세요.presentation/build.gradle.kts (2)
4-5: Hilt 플러그인 추가 후 kapt 세팅 확인 필요
bitnagil.android.hilt플러그인이kotlin-kapt와dagger-hilt-compiler의존성을 자동으로 추가하지 않는 경우 컴파일 오류가 발생합니다.
필요 시 다음을 추가해 주세요.plugins { kotlin("kapt") } dependencies { kapt(libs.hilt.compiler) }
12-15: 의존성 순환 여부 확인
presentation→domain참조가 추가되었는데, 다른 모듈에서 이미presentation을 의존하고 있지 않은지 확인해 순환 참조를 방지하세요.data/build.gradle.kts (2)
13-17: 직렬화 라이브러리 중복 여부 확인
kotlinx.serialization.json을 추가하셨는데, 상위 모듈(예:core/network)에서 이미 동일 라이브러리를api로 노출하고 있다면 중복 의존성이 생길 수 있습니다. 버전 충돌 가능성을 점검해 주세요.
13-17: LGTM!도메인·데이터스토어 의존성 추가가 로그인 플로우 구현과 잘 맞아떨어집니다.
core/datastore/src/main/java/com/threegap/bitnagil/datastore/auth/serializer/AuthTokenSerializerImpl.kt (1)
14-14: 인터페이스 추상화 개선이 잘 되었습니다.
Serializer<AuthToken>에서AuthTokenSerializer로 변경하여 더 나은 추상화와 의존성 주입을 가능하게 했습니다. 이는 테스트 가능성과 모듈 간 결합도를 낮추는 좋은 리팩토링입니다.core/network/src/main/java/com/threegap/bitnagil/network/token/TokenProvider.kt (1)
4-4: 메서드 이름 개선이 적절합니다.
getToken()에서getAccessToken()으로 변경하여 메서드의 역할을 더 명확하게 표현했습니다. 이는 코드의 가독성을 높이고 API를 더 자명하게 만듭니다.domain/src/main/java/com/threegap/bitnagil/domain/auth/model/AuthSession.kt (1)
3-7: 잘 설계된 도메인 모델입니다.인증 세션을 나타내는 데이터 클래스가 적절하게 구성되었습니다. 원시 타입 대신 도메인 특화 타입(
UserRole)을 사용하고, 불변 객체로 설계하여 도메인 모델의 원칙을 잘 따르고 있습니다.app/src/main/java/com/threegap/bitnagil/di/core/DataStoreModule.kt (1)
30-33: 의존성 주입 설정이 올바릅니다.
AuthTokenSerializer의 프로바이더 메서드가 적절하게 구성되었습니다. 싱글톤 스코프와 의존성 주입이 올바르게 설정되어 있으며, Dagger/Hilt 모범 사례를 잘 따르고 있습니다.data/src/main/java/com/threegap/bitnagil/data/auth/mapper/AuthMapper.kt (1)
7-11: 매핑 함수가 적절하게 구현되었습니다.DTO에서 도메인 모델로의 변환 로직이 깔끔하게 구현되었습니다. 확장 함수 방식을 사용하여 가독성을 높였고,
UserRole.from()을 통한 역할 변환이 적절히 처리되어 있습니다.presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginScreen.kt (1)
24-26: 함수 파라미터 다중 줄 포맷팅 개선함수 파라미터를 다중 줄로 포맷팅하여 가독성이 향상되었습니다.
data/src/main/java/com/threegap/bitnagil/data/auth/datasource/AuthLocalDataSource.kt (1)
3-5: 인터페이스 설계 우수로컬 데이터 소스 인터페이스가 깔끔하게 설계되었습니다. Result 반환 타입으로 에러 처리가 적절히 구현되었고, suspend 함수로 비동기 처리가 고려되었습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/login/model/LoginSideEffect.kt (1)
10-12: 새로운 네비게이션 사이드 이펙트 추가가 적절합니다.
NavigateToHome과NavigateToTermsOfService사이드 이펙트가 기존 패턴을 잘 따르고 있으며, MVI 아키텍처에서 네비게이션을 처리하는 적절한 방법입니다.presentation/src/main/java/com/threegap/bitnagil/presentation/login/model/LoginState.kt (1)
8-9: 상태 관리 개선이 우수합니다.
isLoggedIn을 제거하고isLoading과isGuest를 추가한 것은 더 세밀한 상태 제어를 가능하게 합니다. 로딩 상태와 게스트 상태를 명확히 구분하여 UI 피드백을 향상시킬 수 있습니다.data/src/main/java/com/threegap/bitnagil/data/auth/datasource/AuthRemoteDataSource.kt (1)
6-8: 깔끔한 인터페이스 설계입니다.
AuthRemoteDataSource인터페이스가 클린 아키텍처 원칙을 잘 따르고 있습니다.Result래퍼를 사용한 에러 처리와 명확한 메서드 시그니처가 우수합니다.app/src/main/java/com/threegap/bitnagil/di/data/ServiceModule.kt (1)
18-19: @Auth 한정자 정의 확인 완료 및 DI 설정 승인Qualifier.kt에서
@Auth한정자가 올바르게 정의(annotation class Auth)되어 있으며, NetworkModule과 ServiceModule 양쪽에서 일관되게 사용되고 있습니다. 추가 변경 없이 현재 DI 설정을 그대로 승인합니다.app/src/main/java/com/threegap/bitnagil/di/data/RepositoryModule.kt (1)
15-17: 리포지토리 바인딩이 올바르게 구현되었습니다.
@Binds어노테이션을 사용한 인터페이스 바인딩이 효율적이며, 싱글톤 스코프 설정도 리포지토리 레이어에 적합합니다.domain/src/main/java/com/threegap/bitnagil/domain/auth/model/UserRole.kt (1)
3-18: 잘 구현된 UserRole 열거형입니다.코드가 깔끔하고 명확하며, 다음과 같은 장점이 있습니다:
isGuest()메서드로 편리한 역할 확인 제공from()팩토리 메서드로 문자열 변환 지원- 적절한 예외 처리로 안전성 보장
data/src/main/java/com/threegap/bitnagil/data/auth/datasourceimpl/AuthLocalDataSourceImpl.kt (1)
7-18: 로컬 데이터 소스 구현이 올바르게 되어 있습니다.
runCatching을 사용한 에러 처리와 의존성 주입이 적절히 구현되어 있습니다.AuthTokenDataStore에 대한 위임 패턴이 깔끔하게 적용되었습니다.domain/src/main/java/com/threegap/bitnagil/domain/auth/repository/AuthRepository.kt (1)
5-9: 인증 레포지토리 인터페이스가 잘 설계되었습니다.명확한 메서드 시그니처와 일관된
Result<T>반환 타입을 사용하여 에러 처리가 일관성 있게 구현되어 있습니다.data/src/main/java/com/threegap/bitnagil/data/auth/service/AuthService.kt (1)
11-18: 인증 서비스 인터페이스가 올바르게 구현되었습니다.Retrofit 어노테이션이 적절히 사용되었고,
No-Service-Token헤더를 통한 토큰 바이패스 로직이 잘 구현되어 있습니다. API 엔드포인트와 파라미터 구조가 명확합니다.data/src/main/java/com/threegap/bitnagil/data/auth/datasourceimpl/AuthRemoteDataSourceImpl.kt (1)
10-17: 깔끔한 데이터 소스 구현입니다.Clean Architecture 원칙을 잘 따르고 있으며,
safeApiCall을 활용한 일관된 에러 처리가 잘 적용되어 있습니다. 의존성 주입과 인터페이스 구현이 적절합니다.core/network/src/main/java/com/threegap/bitnagil/network/auth/AuthInterceptor.kt (2)
14-18: 로그인 시 토큰 제외 로직이 잘 구현되었습니다.
No-Service-Token헤더를 확인하여 서비스 토큰을 제외하는 로직이 명확하고 적절합니다. 로그인 API 호출 시 순환 참조를 방지하는 좋은 접근 방법입니다.
32-36: 헬퍼 메서드가 명확하고 재사용 가능합니다.
removeNoTokenHeader메서드가 명확하게 구현되어 있고, 단일 책임 원칙을 잘 따르고 있습니다.app/src/main/java/com/threegap/bitnagil/di/data/DataSourceModule.kt (1)
13-24: 의존성 주입 모듈이 표준적으로 잘 구현되었습니다.Dagger Hilt를 사용한 데이터 소스 바인딩이 적절하며,
@Singleton스코프가 올바르게 적용되어 있습니다. 모듈 구조가 명확하고 확장 가능합니다.data/src/main/java/com/threegap/bitnagil/data/auth/repositoryimpl/AuthRepositoryImpl.kt (1)
11-21: 레포지토리 패턴이 잘 구현되었습니다.원격 및 로컬 데이터 소스를 적절히 조합하고 있으며, 도메인 모델로의 매핑이 올바르게 처리되어 있습니다. 코드가 간결하고 명확합니다.
data/src/main/java/com/threegap/bitnagil/data/common/SafeApiCall.kt (1)
10-22: 전반적으로 잘 구현된 API 에러 처리 유틸리티입니다.기본적인 에러 처리 로직이 잘 구현되어 있고, 널 데이터 케이스도 적절히 처리되어 있습니다. 제안된 개선사항을 적용하면 더욱 견고한 구현이 될 것입니다.
app/src/main/java/com/threegap/bitnagil/di/core/NetworkModule.kt (1)
67-68: TokenAuthenticator 통합 필요
provideAuthOkHttpClient에서 토큰 재발급을 처리할TokenAuthenticator가 빠져 있습니다. OkHttpClient에.authenticator(...)로 설정하고, 이를 주입하는 함수도 추가해주세요.
위치:
app/src/main/java/com/threegap/bitnagil/di/core/NetworkModule.kt
provideAuthOkHttpClient메서드 내OkHttpClient.Builder체인예시 수정
@Provides @Singleton fun provideTokenAuthenticator(tokenProvider: TokenProvider): Authenticator = TokenAuthenticator(tokenProvider) @Provides @Singleton @Auth fun provideAuthOkHttpClient( httpLoggingInterceptor: HttpLoggingInterceptor, @Auth authInterceptor: Interceptor, tokenAuthenticator: Authenticator // ← 추가 ): OkHttpClient = OkHttpClient.Builder() .addInterceptor(authInterceptor) .addInterceptor(httpLoggingInterceptor) .authenticator(tokenAuthenticator) // ← 추가 .connectTimeout(10L, TimeUnit.SECONDS) .writeTimeout(30L, TimeUnit.SECONDS) .readTimeout(30L, TimeUnit.SECONDS) .build()위와 같이
TokenAuthenticator를 등록해 토큰 만료 시 자동 갱신 로직이 동작하도록 해주세요.⛔ Skipped due to learnings
Learnt from: wjdrjs00 PR: YAPP-Github/Bitnagil-Android#16 File: core/network/src/main/java/com/threegap/bitnagil/network/auth/TokenAuthenticator.kt:12-46 Timestamp: 2025-07-03T09:05:30.067Z Learning: 이 프로젝트에서는 네트워크 모듈을 점진적으로 개발하고 있으며, TokenAuthenticator 같은 인증 관련 기능은 실제 API 연동 작업 시점에 NetworkModule에 연결할 예정입니다.Learnt from: wjdrjs00 PR: YAPP-Github/Bitnagil-Android#19 File: core/network/src/main/java/com/threegap/bitnagil/network/auth/TokenAuthenticator.kt:16-20 Timestamp: 2025-07-06T04:26:03.870Z Learning: TokenAuthenticator 클래스는 현재 임시 코드로 구현되어 있으며, 실제 토큰 재발급 API 연동 시점에 올바른 구현으로 수정될 예정입니다.core/datastore/src/main/java/com/threegap/bitnagil/datastore/auth/storage/AuthTokenDataStoreImpl.kt (1)
13-57: 토큰 관리 메서드 구현이 잘 되었습니다.try-catch 블록을 사용한 명시적 에러 처리와 적절한 로깅이 구현되었습니다. 에러를 다시 throw하여 호출자가 처리할 수 있도록 한 점도 좋습니다.
core/datastore/src/main/java/com/threegap/bitnagil/datastore/auth/storage/AuthTokenDataStore.kt (1)
9-15: 인터페이스 개선이 잘 되었습니다.토큰을 개별적으로 업데이트할 수 있도록 메서드 시그니처를 변경한 것이 좋습니다. 이는 액세스 토큰만 갱신하는 경우에 유용합니다.
domain/src/main/java/com/threegap/bitnagil/domain/auth/usecase/LoginUseCase.kt
Show resolved
Hide resolved
presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginViewModel.kt
Show resolved
Hide resolved
- mapCatching을 사용하여 예외 발생 시 전파하도록 수정
- firstOrNull()로 변경하여, 토큰이 존재하지 않을 경우 NullPointerException이 발생하는 문제를 해결
presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginViewModel.kt
Show resolved
Hide resolved
LoginIntent를 세분화하여 각 상황에 맞는 Intent를 사용하도록 수정
- KakaoLoginHandlerImpl 추가하여 카카오 로그인 관련 로직 위임 - LoginScreen 카카오톡 설치 여부에 따른 분기 처리 제거 - OnKakaoLoginClick Intent 제거
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.
Actionable comments posted: 0
🧹 Nitpick comments (3)
presentation/src/main/java/com/threegap/bitnagil/presentation/login/kakao/KakaoLoginHandlerImpl.kt (1)
7-8: 테스트 가능성을 위한 구조 개선을 고려해보세요.
object로 구현하면 테스트 시 모킹이 어려울 수 있습니다. 향후 단위 테스트를 고려한다면 다음과 같은 구조를 고려해보세요:-object KakaoLoginHandlerImpl : KakaoLoginHandler { - private val client = UserApiClient.instance +@Singleton +class KakaoLoginHandlerImpl @Inject constructor( + private val client: UserApiClient = UserApiClient.instance +) : KakaoLoginHandler {presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginViewModel.kt (2)
84-85: 소셜 타입 하드코딩 개선을 고려해보세요.
socialType = "KAKAO"가 하드코딩되어 있습니다. 향후 다른 소셜 로그인 지원 시 유연성을 위해 상수나 enum으로 관리하는 것을 고려해보세요.// 예시: 상수 또는 enum 사용 object SocialType { const val KAKAO = "KAKAO" const val GOOGLE = "GOOGLE" } // 사용 socialType = SocialType.KAKAO
93-96: 에러 로깅 중복 개선이 필요합니다.과거 리뷰에서 지적되었던 에러 로깅 중복 문제가 여전히 존재합니다. 다음과 같이 개선할 수 있습니다:
- if (e is BitnagilError) { - Log.e("Login", "${e.code} ${e.message}") - } - Log.e("Login", "${e.message}") + when (e) { + is BitnagilError -> { + Log.e("Login", "BitnagilError: ${e.code} - ${e.message}") + } + else -> { + Log.e("Login", "Login error: ${e.message}") + } + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginScreen.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginViewModel.kt(2 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/login/kakao/KakaoLoginHandler.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/login/kakao/KakaoLoginHandlerImpl.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/login/model/LoginIntent.kt(1 hunks)presentation/src/main/java/com/threegap/bitnagil/presentation/login/model/LoginSideEffect.kt(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- presentation/src/main/java/com/threegap/bitnagil/presentation/login/kakao/KakaoLoginHandler.kt
🚧 Files skipped from review as they are similar to previous changes (1)
- presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginScreen.kt
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: wjdrjs00
PR: YAPP-Github/Bitnagil-Android#16
File: core/network/src/main/java/com/threegap/bitnagil/network/auth/TokenAuthenticator.kt:12-46
Timestamp: 2025-07-03T09:05:30.067Z
Learning: 이 프로젝트에서는 네트워크 모듈을 점진적으로 개발하고 있으며, TokenAuthenticator 같은 인증 관련 기능은 실제 API 연동 작업 시점에 NetworkModule에 연결할 예정입니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginViewModel.kt (1)
Learnt from: wjdrjs00
PR: YAPP-Github/Bitnagil-Android#16
File: core/network/src/main/java/com/threegap/bitnagil/network/auth/TokenAuthenticator.kt:12-46
Timestamp: 2025-07-03T09:05:30.067Z
Learning: 이 프로젝트에서는 네트워크 모듈을 점진적으로 개발하고 있으며, TokenAuthenticator 같은 인증 관련 기능은 실제 API 연동 작업 시점에 NetworkModule에 연결할 예정입니다.
🧬 Code Graph Analysis (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginViewModel.kt (1)
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt (2)
sendSideEffect(23-23)sendIntent(30-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (6)
presentation/src/main/java/com/threegap/bitnagil/presentation/login/model/LoginSideEffect.kt (1)
7-8: 로그인 플로우 개선이 잘 반영되었습니다.카카오 로그인 처리를 별도 핸들러로 분리하고, 사이드 이펙트를 로그인 성공 후의 네비게이션에 집중하도록 개선한 것이 좋습니다. 게스트 사용자와 정회원 사용자의 플로우를 명확히 구분할 수 있게 되었네요.
presentation/src/main/java/com/threegap/bitnagil/presentation/login/kakao/KakaoLoginHandlerImpl.kt (1)
14-18: 카카오톡 로그인 가용성 체크 로직이 명확합니다.카카오톡 앱 설치 여부에 따른 로그인 방식 분기 처리가 잘 구현되어 있습니다. 사용자 경험을 고려한 좋은 접근법이네요.
presentation/src/main/java/com/threegap/bitnagil/presentation/login/LoginViewModel.kt (3)
23-23: 도메인 유즈케이스 도입으로 아키텍처가 개선되었습니다.
LoginUseCase를 의존성 주입으로 받아 도메인 로직을 분리한 것이 좋습니다. 클린 아키텍처 원칙에 잘 맞는 구조네요.
28-59: MVI 패턴 준수가 잘 개선되었습니다.이전 리뷰 피드백을 잘 반영하여
sendIntent를 통한 상태 변경으로 구조를 개선했네요. 각 인텐트별로 명확한 상태 변경과 사이드 이펙트 처리가 구현되어 있습니다.
61-80: 코루틴 기반 로그인 처리 로직이 잘 구현되었습니다.OAuth 토큰과 에러를 매개변수로 받아 적절히 분기 처리하는 구조가 명확합니다. 특히 카카오 로그인 취소에 대한 별도 처리가 사용자 경험을 고려한 좋은 접근법입니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/login/model/LoginIntent.kt (1)
6-9: 인텐트 구조가 크게 개선되었습니다.기존의 카카오 특화 인텐트들을 제거하고 일반적인 로그인 플로우 인텐트로 리팩토링한 것이 좋습니다. 특히 다음 개선점들이 돋보입니다:
SetLoading: 로딩 상태 관리를 위한 명확한 인텐트LoginSuccess: 게스트 여부를 포함한 성공 상태 처리KakaoTalkLoginCancel: 카카오톡 로그인 취소 시 계정 로그인으로 fallback 처리LoginFailure: 명확한 실패 상태 처리향후 다른 소셜 로그인 추가 시에도 재사용 가능한 구조네요.
l5x5l
left a comment
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.
오늘 스크럼에서 나온 context이용한 부분을 인터페이스로 분리해 viewModel에서 참조하도록 하는 것 관련해서는 서로 이해하는 방식이 달랐던 것 같습니다!
일단 현재 큰 문제가 될만한 부분은 아니니 일단 머지 진행하시고, 주말에 다시 한번 얘기 나눠보죠!
[ PR Content ]
소셜 로그인을 통해 발급받는 소셜 토큰값을 기반으로 자체(빛나길)서비스 로그인 구현
Related issue
Screenshot 📸
Work Description
To Reviewers 📢
커스텀Result<T>를 정의하여 사용하는 경우 기본Result<T>의 확장함수들을 사용 못해서 예외 클래스를 정의하고 서비스 에러를 잡는 방향으로 구현했습니다.Summary by CodeRabbit
신규 기능
버그 수정
리팩터
문서화/설정