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.
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.
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.
오늘 스크럼에서 나온 context이용한 부분을 인터페이스로 분리해 viewModel에서 참조하도록 하는 것 관련해서는 서로 이해하는 방식이 달랐던 것 같습니다!
일단 현재 큰 문제가 될만한 부분은 아니니 일단 머지 진행하시고, 주말에 다시 한번 얘기 나눠보죠!
[ PR Content ]
소셜 로그인을 통해 발급받는 소셜 토큰값을 기반으로 자체(빛나길)서비스 로그인 구현
Related issue
Screenshot 📸
Work Description
To Reviewers 📢
커스텀Result<T>를 정의하여 사용하는 경우 기본Result<T>의 확장함수들을 사용 못해서 예외 클래스를 정의하고 서비스 에러를 잡는 방향으로 구현했습니다.Summary by CodeRabbit
신규 기능
버그 수정
리팩터
문서화/설정