Skip to content

Conversation

@librawish808
Copy link
Collaborator

@librawish808 librawish808 commented Sep 29, 2025

🔗 관련 이슈

📙 작업 설명

  • API 서비스 패키지를 엔드포인트 prefix 기준으로 재구성했습니다.

    • elders/, member/, payments/, notice/ 각각 전용 패키지 생성 및 분리
  • 인증 관련 API 통합

    • TokenRefreshService, VerificationService → AuthService로 이관
    • SettingService.logout() → AuthService.logout()으로 이동
  • ApiModule 수정

    • provideAuthService 추가
    • provideTokenRefreshService, provideVerificationService 제거
  • UserRepositoryImpl 수정

    • 로그아웃 시 AuthService.logout()을 호출하도록 변경
    • RefreshToken 기반 로그아웃 처리 후 로컬 토큰 삭제 로직 유지
  • AuthAuthenticator

    • 주석제거
  • build.gradle.kts

    • Detekt JVM 타깃을 11로 지정하여 환경 일관성 확보

💬 추가 설명 or 리뷰 포인트 (선택)

  • HomeService에서 prefix가 elders와 care-call로 같이 있는데 분리하는게 좋을까요?
    HomeService.kt는 현재 elders패키지에 있습니다

  • 작업 중 AuthAuthenticator.kt에서 토큰 갱신 로직에 잠재적인 무한 루프 위험이 있는 것을 발견하여, 이를 해결하기 위한 리팩토링을 포함했습니다.

    • dagger.Lazy를 적용하여 순환 참조를 해결했습니다.
    • 런타임 무한 루프 위험 발견: Lazy 적용으로 컴파일은 통과했지만, 토큰 갱신 요청마저 401 에러를 받을 경우 런타임에서 무한 루프에 빠질 수 있는 근본적인 위험은 여전히 남아있습니다.

이 부분을 어떻게 고치면 좋을지 의견이 궁금합니다!

Summary by CodeRabbit

  • Refactor
    • API 서비스 패키지를 도메인별(인증·회원·노티스·결제·어르신)로 재구성하여 모듈화
    • 인증 관련 엔드포인트를 단일 Auth 서비스로 통합하고 로그아웃 경로를 통일
  • Bug Fixes
    • 휴대폰 인증 실패 처리 강화로 오류 전달 개선
    • 토큰 갱신 흐름 안정성 향상
  • Chores
    • 정적 분석(Detekt) JVM 타깃을 11로 설정

@librawish808 librawish808 self-assigned this Sep 29, 2025
@coderabbitai
Copy link

coderabbitai bot commented Sep 29, 2025

Walkthrough

Retrofit 서비스들을 도메인별 패키지로 재구성하고, 인증·검증 API들을 AuthService로 통합했다. DI 모듈과 AuthAuthenticator 시그니처/연결을 재배선했으며, 관련 리포지토리의 임포트를 도메인별 경로로 갱신했다. 또한 Detekt 태스크의 JVM 타깃을 11로 설정했다.

Changes

Cohort / File(s) Change Summary
Build config
app/build.gradle.kts
Detekt 태스크에 jvmTarget = "11" 적용.
Auth API 통합 (신규/삭제)
app/src/main/java/com/konkuk/medicarecall/data/api/auth/AuthService.kt, app/src/main/java/com/konkuk/medicarecall/data/api/TokenRefreshService.kt, app/src/main/java/com/konkuk/medicarecall/data/api/VerificationService.kt
AuthService 추가(토큰 리프레시, 인증 코드 요청/확인, 로그아웃). 기존 TokenRefreshServiceVerificationService 제거.
Elders 패키지 리팩토링
app/src/main/java/com/konkuk/medicarecall/data/api/elders/*ElderRegisterService.kt, EldersInfoService.kt, GlucoseService.kt, HealthService.kt, HomeService.kt, MealService.kt, MedicineService.kt, MentalService.kt, SetCallService.kt, SleepService.kt, StatisticsService.kt, SubscribeService.kt
패키지 선언을 ...data.api...data.api.elders로 변경. 인터페이스 시그니처는 변동 없음.
Member/Notice/Payments 패키지 리팩토링
app/src/main/java/com/konkuk/medicarecall/data/api/member/*, .../data/api/notice/*, .../data/api/payments/*
서비스 파일들을 도메인별 하위 패키지로 이동. SettingService에서 logout 엔드포인트 제거.
DI 재배선 - ApiModule
app/src/main/java/com/konkuk/medicarecall/data/di/ApiModule.kt
도메인별 서비스 바인딩으로 재구성. provideAuthService 추가, provideTokenRefreshService 제거, elders/member/notice/payments 서비스 제공자 정리/추가.
DI 재배선 - NetworkModule
app/src/main/java/com/konkuk/medicarecall/data/di/NetworkModule.kt
provideAuthAuthenticator 파라미터 타입을 Lazy<TokenRefreshService>dagger.Lazy<AuthService>로 변경. provideOkHttpClientAuthAuthenticator를 주입(.authenticator).
AuthAuthenticator 갱신
app/src/main/java/com/konkuk/medicarecall/data/network/AuthAuthenticator.kt
생성자 의존성을 TokenRefreshServiceAuthService로 교체. 토큰 리프레시 호출을 authService.get().refreshToken(...)로 변경. 동기화/401 처리 로직은 유지.
Repository 임포트 경로 정리 (Elders)
app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/*RepositoryImpl.ktElderRegisterRepositoryImpl.kt, EldersHealthInfoRepositoryImpl.kt, EldersInfoRepositoryImpl.kt, GlucoseRepositoryImpl.kt, HealthRepositoryImpl.kt, HomeRepositoryImpl.kt, MealRepositoryImpl.kt, MedicineRepositoryImpl.kt, MentalRepositoryImpl.kt, SetCallRepositoryImpl.kt, SleepRepositoryImpl.kt, StatisticsRepositoryImpl.kt, SubscribeRepositoryImpl.kt, UpdateElderInfoRepositoryImpl.kt
서비스 임포트를 ...data.api.*...data.api.elders.*로 변경. 로직 변화 없음.
Repository 임포트 경로 정리 (기타 도메인)
app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/MemberRegisterRepositoryImpl.kt, NoticeRepositoryImpl.kt, NaverPayRepositoryImpl.kt
서비스 임포트를 member/notice/payments 패키지로 변경. 로직 변화 없음.
Repository 동작 변경 (Auth 관련)
app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/UserRepositoryImpl.kt, .../VerificationRepositoryImpl.kt
UserRepositoryImpl 생성자에 AuthService 추가, 로그아웃 호출을 SettingService.logoutAuthService.logout으로 변경. VerificationRepositoryImplVerificationService 대신 AuthService를 사용하도록 교체하고, 확인 응답 실패 시 HttpException 처리 추가.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant App as App
  participant API as Backend
  participant Auth as AuthService
  participant Store as TokenStore
  note over App,API: 보호된 API 요청 흐름 (리프레시 포함)

  App->>API: 요청(Access Token)
  API-->>App: 401 Unauthorized
  App->>Auth: refreshToken(refresh)
  Auth-->>App: 200 + new tokens / 4xx
  alt success
    App->>Store: saveTokens(new)
    App->>API: 재시도(새 Access Token)
    API-->>App: 200 OK
  else failure
    App->>Store: clearTokens()
    App-->>Client: 인증 필요 (sign-out)
  end
Loading
sequenceDiagram
  autonumber
  actor User
  participant Repo as UserRepository
  participant Auth as AuthService
  participant Store as TokenStore

  User->>Repo: logout()
  Repo->>Store: getRefresh()
  Repo->>Auth: logout(Authorization: Bearer <refresh>)
  Auth-->>Repo: 200/err
  Repo->>Store: clearTokens()
  Repo-->>User: 완료/오류
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • alswlekk

Poem

패키지 나무를 가지마다 옮겨 심고,
Auth가 바람을 잡아 토큰을 다시 불러오네.
인터페이스 모여 한집, DI는 새 길을 잇고,
Detekt는 JVM 열한에 맞춰 춤춘다.
작은 정리, 깔끔한 출발 — 커밋에 박수를 👏

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning 이 PR에는 서비스 패키지 구조 개편과 직접 연관 없는 Detekt JVM 타깃 설정을 위한 build.gradle.kts 변경과 AuthAuthenticator 주석 제거, 파일 끝 newline 추가 같은 범위 외 변경이 포함되어 있어 리팩토링 목적이 혼재되었습니다. 이러한 변경은 본 PR의 핵심 목표와 분리하여 관리하는 것이 변경 내역을 명확히 파악하는 데 도움이 됩니다. 빌드 구성 변경과 주석·newline 수정 등 서비스 패키지 구조 개편 범위 외 변경은 별도의 PR로 분리하거나 이 PR의 linked issue에 해당 내용을 반영해 주세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues Check ✅ Passed 이 PR은 Service 인터페이스를 auth, elders, member, notice, payments 패키지로 분리하고 TokenRefreshService 및 VerificationService를 AuthService로 통합했으며 ApiModule에서 해당 서비스 프로바이더를 갱신하고 AuthAuthenticator와 UserRepositoryImpl을 AuthService 호출에 맞춰 수정하여 #123에 명시된 주요 리팩토링 요구 사항을 충족합니다.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed 제목이 API 서비스 패키지 구조 개편이라는 주요 변경 사항을 명확히 요약하고 있으며 간결하고 구체적이어서 변경 내용의 핵심을 쉽게 파악할 수 있습니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/api-service-package-#123

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (8)
app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/EldersInfoRepositoryImpl.kt (1)

41-62: 치명적: 함수 반환 타입 불일치로 컴파일/런타임 오류 위험.

updateElderResult<Unit>을 반환하도록 선언됐지만, 성공 시 response.body()(EldersInfoResponseDto)를 그대로 반환하고 있어 제네릭이 어긋납니다. 성공 시 Unit을 반환하도록 수정하고 예외 타입도 일관되게 HttpException으로 맞추는 것을 권장합니다.

아래처럼 정리해 주세요:

-    ): Result<Unit> = runCatching {
+    ): Result<Unit> = runCatching {
         val response = eldersInfoService.updateElder(
             id,
             ElderRegisterRequestDto(
                 request.name,
                 birthDate = request.birthDate.formatAsDate(),
                 gender = if (request.gender) GenderType.MALE else GenderType.FEMALE,
                 phone = request.phoneNumber,
-                relationship = RelationshipType.entries.find { it.displayName == request.relationship }!!,
-                residenceType = ElderResidenceType.entries.find { it.displayName == request.livingType }!!,
+                relationship = requireNotNull(
+                    RelationshipType.entries.find { it.displayName == request.relationship }
+                ) { "Unknown relationship: ${request.relationship}" },
+                residenceType = requireNotNull(
+                    ElderResidenceType.entries.find { it.displayName == request.livingType }
+                ) { "Unknown residenceType: ${request.livingType}" },
             ),
         )
-        if (response.isSuccessful) {
-            response.body() ?: throw IllegalStateException("Response body is null")
-        } else {
-            val errorBody = response.errorBody()?.string() ?: "Unknown error"
-            throw Exception(errorBody)
-        }
+        if (response.isSuccessful) {
+            Unit
+        } else {
+            throw HttpException(response)
+        }
     }
app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/SetCallRepositoryImpl.kt (1)

18-26: errorBody를 두 번 .string() 호출 — 두 번째는 항상 빈 값.

ResponseBody.string()은 1회성입니다. 한 번만 읽고 재사용하세요. 그렇지 않으면 로그/예외 메시지가 비게 됩니다.

-            if (!response.isSuccessful) {
-                Log.e("SetCallRepository", "HTTP ${response.code()} ${response.message()}")
-                Log.e("SetCallRepository", "ErrorBody=${response.errorBody()?.string()}")
-                throw Exception(
-                    "Error saving care call times: ${
-                        response.errorBody()?.string()
-                    } / SetCallRepository.kt",
-                )
-            }
+            if (!response.isSuccessful) {
+                val err = response.errorBody()?.string()
+                Log.e("SetCallRepository", "HTTP ${response.code()} ${response.message()}")
+                Log.e("SetCallRepository", "ErrorBody=$err")
+                throw Exception("Error saving care call times: $err / SetCallRepository.kt")
+            }
app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/GlucoseRepositoryImpl.kt (1)

19-24: 에러 바디를 읽고 버리고 있어요(소비 부작용 가능)

errorBody()?.string()은 스트림을 소비합니다. 현재 미사용이므로 제거하거나 로깅에만 사용하세요.

적용 예:

-            } else {
-                val errorBody = response.errorBody()?.string() ?: "Unknown error"
-                throw HttpException(response)
-            }
+            } else {
+                // TODO: 필요 시 여기서 errorBody를 파싱해 사용자 친화적 에러로 매핑
+                throw HttpException(response)
+            }
app/src/main/java/com/konkuk/medicarecall/data/di/NetworkModule.kt (3)

44-48: 로그 인터셉터가 토큰을 노출할 수 있습니다(Release 포함 BODY 레벨)

Authorization 헤더를 redaction하고, Release 빌드에서는 LEVEL을 낮추세요.

     fun provideHttpLoggingInterceptor(): HttpLoggingInterceptor {
-        return HttpLoggingInterceptor().apply {
-            level = HttpLoggingInterceptor.Level.BODY
-        }
+        return HttpLoggingInterceptor().apply {
+            // 민감 헤더 마스킹
+            redactHeader("Authorization")
+            level = if (BuildConfig.DEBUG)
+                HttpLoggingInterceptor.Level.BODY
+            else
+                HttpLoggingInterceptor.Level.BASIC
+        }
     }

33-40: AuthService 직접 주입은 DI 순환을 유발할 수 있습니다

OkHttpClient → Authenticator → AuthService(Retrofit) → OkHttpClient 순환이 발생하기 쉽습니다. Lazy/Provider 주입 또는 리프레시 전용 Retrofit(Authenticator 미적용 클라이언트)로 분리하는 걸 권장합니다.

정석 옵션 중 하나:

  • AuthAuthenticator 생성자: private val authService: Lazy<AuthService> 로 변경
  • NetworkModule: provideAuthAuthenticator(..., authService: Lazy<AuthService>)
  • Authenticator 내부 호출 시 authService.get().refreshToken(...)

52-61: OkHttpClient에 AuthAuthenticator 미등록 — 401 자동 갱신 실패 위험
provideOkHttpClientAuthAuthenticator 의존성을 추가하고 .authenticator(authAuthenticator) 호출을 등록해 주세요. (Lines 52–61)

app/src/main/java/com/konkuk/medicarecall/data/network/AuthAuthenticator.kt (2)

31-38: 새 accessToken이 null/blank인 경우 "Bearer null" 헤더가 붙을 수 있습니다

재시도 분기에서 accessToken null/blank를 체크하고, 없으면 null 반환이 안전합니다.

-            if (oldAccessToken != null && oldAccessToken != accessToken) {
+            if (oldAccessToken != null && oldAccessToken != accessToken) {
+                if (accessToken.isNullOrBlank()) return null
                 return response.request.newBuilder()
                     .header("Authorization", "Bearer $accessToken")
                     .build()
             }

40-49: 토큰 존재 체크는 null 뿐 아니라 blank도 함께 보세요

빈 문자열이 저장된 경우 무한 재시도 루프에 가까운 동작이 나올 수 있습니다.

-            if (refreshToken == null) {
+            if (refreshToken.isNullOrBlank()) {
                 // 여기서 로그인 화면으로 보내는 로직을 추가할 수 있습니다. (예: EventBus, SharedFlow 등)
                 return null
             }
 
             // 6. 토큰 갱신 API 호출 (runBlocking 사용)
-            val refreshResponse = runBlocking {
-                authService.refreshToken(TokenRefreshRequestDto(refreshToken))
-            }
+            val refreshResponse = try {
+                runBlocking {
+                    authService.refreshToken(TokenRefreshRequestDto(refreshToken))
+                }
+            } catch (t: Throwable) {
+                Log.e("AuthAuthenticator", "Token refresh call failed", t)
+                return null
+            }
🧹 Nitpick comments (14)
app/src/main/java/com/konkuk/medicarecall/data/api/elders/EldersInfoService.kt (2)

22-26: 업데이트에 POST 사용 확인 필요 (메서드명/HTTP verb 정합성).

updateElder@POST("elders/{elderId}")를 사용합니다. 서버 스펙이 POST‑update로 정의돼 있다면 그대로 OK이지만, 일반적으로는 PUT/PATCH를 쓰거나 메서드명을 upsertElder처럼 명확히 하는 편이 헷갈림을 줄입니다. 백엔드 스펙 기준으로 한 번만 확인해 주세요.


39-42: 케어콜 API는 SetCallService로 모아 cohesion 높이기 제안.

GET elders/{elderId}/care-call-setting이 여기 있고, 저장은 SetCallService에 있습니다. 조회/저장을 동일 서비스(SetCallService 또는 CareCallService)로 묶으면 탐색성과 변경 파급이 줄어듭니다. 이동 가능하면 옮기는 걸 추천합니다.

app/src/main/java/com/konkuk/medicarecall/data/api/elders/SetCallService.kt (1)

10-15: 메서드명/HTTP verb 확인 한 번만 부탁!

saveCareCallTimes가 POST입니다. 서버가 멱등 업데이트를 요구하면 PUT이 더 적합하고, POST 유지 시엔 이름을 updateCareCallTimes로 바꾸는 것도 선택지입니다. 스펙대로면 그대로 진행해도 무방합니다.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/EldersInfoRepositoryImpl.kt (4)

20-28: 에러 처리 일관성 + 불필요 변수 제거.

getElders()에서 errorBody를 구해놓고 HttpException(response)를 던져 실제로는 사용하지 않습니다. 불필요 변수 제거하거나, 커스텀 예외 메시지로 쓸 거면 Exception(errorBody)로 통일하는 등 한 가지 방식으로 맞추는 게 좋습니다. 현재 파일 내 메서드들 간에도 HttpException/Exception 혼재되어 있습니다.


64-71: DELETE 성공 처리 단순화 제안.

Response<Unit>는 본문이 의미 없으니 성공 시 본문 접근 없이 Unit만 반환하는 게 간결하고 안전합니다(본문 소비에 의존하지 않음).

-        if (response.isSuccessful) {
-            response.body() ?: throw IllegalStateException("Response body is null")
-        } else {
+        if (response.isSuccessful) {
+            Unit
+        } else {
             val errorBody = response.errorBody()?.string() ?: "Unknown error"
             throw HttpException(response)
         }

49-54: 널 단정(!!)

RelationshipType/ElderResidenceType 매핑에 !!을 사용하면 런타임 크래시 납니다. 위 수정안처럼 requireNotNull로 바꾸고 원인 파악 쉬운 메시지를 남기는 쪽이 안전합니다.

매핑 기준이 UI 표시 문자열(displayName)이라 레이아웃/로캘 변경에 취약할 수 있습니다. 서버 표준 코드 기반으로 맵핑할 수 있는지 확인 부탁드립니다.


13-13: 레이어링: data 레이어가 ui 유틸에 의존.

formatAsDateui.common.util에 있어 data→ui 의존이 생깁니다. 공통 모듈(core/util 등)로 옮기고 두 레이어가 그걸 참조하도록 구조를 정리하는 걸 추천합니다.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/SetCallRepositoryImpl.kt (1)

37-46: 시간 변환 입력값 검증 추가 제안.

amPm/h12/m 범위를 보장하지 않으면 이상치가 그대로 서버로 전달됩니다. 간단한 require 검증을 추가해 조기 실패하도록 하죠.

     private fun Triple<Int, Int, Int>.toHHmm(): String {
         val (amPm, h12, m) = this
+        require(amPm in 0..1) { "amPm must be 0(AM) or 1(PM): $amPm" }
+        require(h12 in 1..12) { "hour(12h) must be 1..12: $h12" }
+        require(m in 0..59) { "minute must be 0..59: $m" }
         val h24 = when {
             amPm == 0 && h12 == 12 -> 0
             amPm == 1 && h12 < 12 -> h12 + 12
             else -> h12 % 24
         }
         Log.d("SetCallRepository", "Converting time: $this to 24-hour format: $h24:$m")
         return "%02d:%02d".format(h24, m)
     }
app/src/main/java/com/konkuk/medicarecall/data/api/elders/GlucoseService.kt (1)

13-18: 문자열 대신 타입 세이프 enum 사용 제안.

type 파라미터는 도메인 상 BEFORE_MEAL/AFTER_MEAL 두 값뿐이라 enum으로 제한하면 안전합니다. 서버가 대문자 값을 기대한다면 enum 이름과 정확히 일치시켜 주세요.

-        @Query("type") type: String // BEFORE_MEAL or AFTER_MEAL
+        @Query("type") type: GlucoseType
     ): Response<GlucoseResponseDto>
 }
+
+enum class GlucoseType { BEFORE_MEAL, AFTER_MEAL }
app/src/main/java/com/konkuk/medicarecall/data/api/elders/HomeService.kt (1)

18-21: care-call 엔드포인트 분리 제안
패키지를 prefix 기준으로 재정리한 흐름이라면 /care-call/immediate 엔드포인트는 별도 서비스(예: carecall 전용 서비스)로 떼어내는 편이 정리에 더 잘 맞을 것 같아요. 지금처럼 elders 패키지 안에 두면 이후 유지보수 시 혼선이 생길 여지가 있어 보여요.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/GlucoseRepositoryImpl.kt (1)

12-16: 파라미터 type은 enum/sealed로 제한하는 것을 고려하세요

자유 문자열 대신 enum(예: Day/Week/Month 등)으로 모델링하면 오입력 방지와 호출부 가독성이 좋아집니다.

app/src/main/java/com/konkuk/medicarecall/data/api/member/SettingService.kt (1)

15-18: 요청/응답 DTO를 분리해 주세요

updateMyInfo가 요청 바디로 MyInfoResponseDto를 사용합니다. 요청 전용 DTO(예: MyInfoUpdateRequestDto)로 분리하면 직렬화 안정성과 스키마 진화를 안전하게 처리할 수 있습니다.

app/src/main/java/com/konkuk/medicarecall/data/network/AuthAuthenticator.kt (1)

64-73: 실패 시 토큰 정리는 access/refresh 모두 일관되게 처리하세요

현재 refreshToken만 ""로 저장합니다. 이후 체크를 isNullOrBlank()로 바꿨으니 최소한 둘 다 비우거나 별도 clear 메서드를 쓰는 편이 안전합니다.

-                runBlocking { dataStoreRepository.saveRefreshToken("") }
+                runBlocking {
+                    dataStoreRepository.saveAccessToken("")
+                    dataStoreRepository.saveRefreshToken("")
+                }

추가로 DataStore 층에 clearTokens() 같은 API가 있다면 그걸 사용하세요.

app/src/main/java/com/konkuk/medicarecall/data/api/elders/HealthService.kt (1)

8-14: 서비스 반환 타입 스타일 통일 필요
HealthService는 DTO(HealthResponseDto) 직접 반환하는 반면, NoticeService·SettingService·SubscribeService·EldersInfoService 등에서는 Response를 반환하고 있어요. 팀 가이드에 맞춰 전부 DTO 직접 반환 또는 전부 Response 중 한 가지 방식으로 통일해주세요.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84117bf and f11aef6.

📒 Files selected for processing (42)
  • app/build.gradle.kts (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/TokenRefreshService.kt (0 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/VerificationService.kt (0 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/auth/AuthService.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/ElderRegisterService.kt (2 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/EldersInfoService.kt (2 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/GlucoseService.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/HealthService.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/HomeService.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/MealService.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/MedicineService.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/MentalService.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/SetCallService.kt (2 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/SleepService.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/StatisticsService.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/elders/SubscribeService.kt (2 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/member/MemberRegisterService.kt (2 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/member/SettingService.kt (2 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/notice/NoticeService.kt (2 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/api/payments/NaverPayService.kt (2 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/di/ApiModule.kt (2 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/di/NetworkModule.kt (2 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/network/AuthAuthenticator.kt (4 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/ElderRegisterRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/EldersHealthInfoRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/EldersInfoRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/GlucoseRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/HealthRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/HomeRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/MealRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/MedicineRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/MemberRegisterRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/MentalRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/NaverPayRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/NoticeRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/SetCallRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/SleepRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/StatisticsRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/SubscribeRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/UpdateElderInfoRepositoryImpl.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/UserRepositoryImpl.kt (3 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/VerificationRepositoryImpl.kt (2 hunks)
💤 Files with no reviewable changes (2)
  • app/src/main/java/com/konkuk/medicarecall/data/api/TokenRefreshService.kt
  • app/src/main/java/com/konkuk/medicarecall/data/api/VerificationService.kt
⏰ 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: ci-build
🔇 Additional comments (23)
app/build.gradle.kts (1)

123-125: Detekt JVM 타깃 정렬 좋아요.
Kotlin/Java 컴파일 설정과 동일하게 맞춰 통합 빌드 환경을 유지할 수 있네요.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/EldersInfoRepositoryImpl.kt (1)

1-3: 마이그레이션 잔재 없음 확인
제공한 스크립트 실행 결과, 구 패키지(API 패키지, TokenRefreshService/VerificationService) 및 로그아웃 경로(SettingService.logout, AuthService.logout) 참조가 전부 제거된 것을 확인했습니다.

app/src/main/java/com/konkuk/medicarecall/data/api/elders/MentalService.kt (1)

1-1: 패키지 이동 확인

elders 도메인에 맞게 패키지 경로를 정리한 덕분에 Retrofit 엔드포인트 구조와 한눈에 매칭됩니다. 추가 수정 필요 없어 보입니다.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/EldersHealthInfoRepositoryImpl.kt (1)

4-5: 도메인별 서비스 경로 정리 👍

Elder 관련 서비스 의존성을 data.api.elders로 옮기면서 DI 구성과 일관성이 좋아졌습니다. 다른 레이어 영향도 없네요.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/SubscribeRepositoryImpl.kt (1)

4-4: elders 전용 서비스로 정리 완료

구독 API도 elders 패키지로 이동해 네이밍 체계가 통일되었습니다. 문제 없이 잘 맞물립니다.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/ElderRegisterRepositoryImpl.kt (1)

4-4: Import 경로 정리 잘 됐어요

Elder 등록 흐름이 elders 패키지로 모여서 추후 유지보수에도 도움이 될 듯합니다. 다른 로직 영향 없습니다.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/MedicineRepositoryImpl.kt (1)

3-3: 의약품 API도 elders 묶음으로 이동

MedicineService 의존성도 elders 네임스페이스로 맞춰져 서비스 분리가 자연스럽습니다. 이 상태로 괜찮아요.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/NoticeRepositoryImpl.kt (1)

4-4: 패키지 경로 업데이트 확인 완료

NoticeService를 notice 패키지로 옮긴 흐름이 잘 반영됐네요. 기존 로직에 영향 없이 구조만 더 깔끔해진 것 같아요.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/UpdateElderInfoRepositoryImpl.kt (1)

4-4: elders 패키지로의 이동 적합

EldersInfoService가 elders 패키지로 묶이면서 DI/레포 구조에 맞춰 잘 정리됐어요. 다른 의존성 영향도 없어 보입니다.

app/src/main/java/com/konkuk/medicarecall/data/api/elders/SleepService.kt (1)

1-1: 패키지 네임스페이스 이동 OK

SleepService도 elders 네임스페이스로 맞춰진 덕에 서비스 그룹이 더 명확해졌네요. 인터페이스 자체는 그대로라 안심입니다.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/MentalRepositoryImpl.kt (1)

4-4: MentalService import 정리 👍

MentalService를 elders 패키지로 이동시킨 변경이 잘 반영됐습니다. 레포 로직은 그대로 유지돼서 리스크 없어요.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/HomeRepositoryImpl.kt (1)

4-4: HomeService도 elders 쪽으로 합류 완료

HomeService까지 elders 패키지로 묶이면서 서비스 구조가 한눈에 들어오네요. 기존 기능 흐름은 변함없어 보입니다.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/MemberRegisterRepositoryImpl.kt (1)

3-3: 패키지 리팩터링 반영 깔끔합니다.

새로 분리된 member 패키지 경로로 의존성 정리된 것 확인됐어요. 다른 영향 범위도 없어서 그대로 가면 될 듯합니다.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/VerificationRepositoryImpl.kt (1)

15-16: 비정상 응답 처리 확인 필요

authService.requestCertificationCode(...) 호출 결과가 Response<*> 형태라면, confirmPhoneNumber처럼 isSuccessful 체크 없이 바로 반환하면 4xx/5xx가 성공 케이스로 들어와버려요. 기존 VerificationService 시절과 동일하게 예외가 던져지는지, 아니면 명시적으로 response.isSuccessful 분기 추가가 필요한지 한 번만 더 확인 부탁드립니다.

app/src/main/java/com/konkuk/medicarecall/data/api/elders/StatisticsService.kt (1)

1-15: 패키지 이동 깔끔합니다
패키지 네임스페이스만 정리된 거라 추가 리스크 없어 보입니다. 👍

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/NaverPayRepositoryImpl.kt (1)

3-3: 의존성 경로 업데이트 문제 없습니다
새 패키지 구조에 맞춰 import만 바뀐 거라 동작 영향은 없고, 정리도 잘 된 것 같아요.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/SleepRepositoryImpl.kt (1)

3-3: 패키지 리팩토링 반영 잘 됐어요

새 elders 네임스페이스에 맞춰 import 업데이트된 거 확인했습니다. 다른 레포지토리들도 같은 구조로 정리되어서 일관성이 좋아졌네요.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/StatisticsRepositoryImpl.kt (1)

3-3: elders 서비스 경로로 정리된 부분 좋습니다

StatisticsService도 elders 패키지로 옮겨진 흐름과 맞춰져서 의존성 관계가 한눈에 들어와요. 👍

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/HealthRepositoryImpl.kt (1)

3-3: HealthService import 교체 깔끔해요

리팩토링된 elders 패키지 구조에 맞춰 HealthService 경로도 잘 조정됐습니다. 추가 수정 없이 기존 로직과 잘 이어지네요.

app/src/main/java/com/konkuk/medicarecall/data/api/member/MemberRegisterService.kt (1)

1-16: member 패키지로 이동한 구성 좋아요

파일 위치와 패키지 선언이 일치하도록 정리돼서 구조적 가독성이 확실히 좋아졌습니다. 인터페이스 시그니처도 그대로라 영향도 없겠네요.

app/src/main/java/com/konkuk/medicarecall/data/repositoryimpl/MealRepositoryImpl.kt (1)

3-3: MealService import 동기화 완료 확인했습니다

elders 패키지로 서비스가 정리된 흐름에 따라 import만 교체해 주신 부분 문제없어요.

app/src/main/java/com/konkuk/medicarecall/data/api/elders/HealthService.kt (1)

1-1: 패키지 이동 LGTM

elders 도메인으로의 이동 방향성 좋습니다. 네이밍/경로 일관성도 OK.

app/src/main/java/com/konkuk/medicarecall/data/api/member/SettingService.kt (1)

9-20: SettingService.logout 참조 정리 및 AuthService.logout 전환 확인
SettingService 인터페이스에는 더 이상 logout 메서드가 없으며, ViewModel( MyDataViewModel )과 Repository( UserRepositoryImpl )에서 UserRepository.logout → AuthService.logout 호출로 전환된 것을 확인했습니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
app/src/main/java/com/konkuk/medicarecall/data/network/AuthAuthenticator.kt (2)

19-26: 리프레시 엔드포인트 자기호출(무한 재귀) 차단 가드 필요

authenticate 내에서 토큰 리프레시 요청도 401이 나면 다시 Authenticator가 호출돼 재귀·루프가 발생할 수 있습니다. 리프레시/인증 계열 경로는 즉시 null을 반환하도록 가드를 추가해 주세요.

   override fun authenticate(route: Route?, response: Response): Request? {
     // 1. 401 에러가 아니면 null 반환 (다른 에러는 이 Authenticator가 처리하지 않음)
     if (response.code != 401) {
       return null
     }
+    // 1.5 리프레시/인증 경로에서는 Authenticator 비활성화하여 재귀 방지
+    val path = response.request.url.encodedPath
+    if (path.startsWith("/auth/") || path.startsWith("/verification/")) {
+      return null
+    }

41-44: 빈 문자열 토큰 처리 불일치로 인한 반복 리프레시 시도

현재는 실패 시 refreshToken""로 저장(Line 70)하지만, 존재 여부 체크는 null만 검사(Line 41)합니다. 그 결과 빈 문자열이 저장된 상태에서도 매 401마다 리프레시 호출이 재시도됩니다. isNullOrBlank()로 통일하고 실패 시 액세스/리프레시 토큰을 모두 빈값으로 정리하세요.

-            if (refreshToken == null) {
+            if (refreshToken.isNullOrBlank()) {
               // 여기서 로그인 화면으로 보내는 로직을 추가할 수 있습니다. (예: EventBus, SharedFlow 등)
               return null
             }
 ...
-                runBlocking { dataStoreRepository.saveRefreshToken("") }
+                runBlocking {
+                    dataStoreRepository.saveAccessToken("")
+                    dataStoreRepository.saveRefreshToken("")
+                }

Also applies to: 70-71

app/src/main/java/com/konkuk/medicarecall/data/di/NetworkModule.kt (1)

44-47: 로그 민감정보 노출 위험: BODY 레벨/토큰 미마스킹

HttpLoggingInterceptor.Level.BODY를 상시 사용하면 본문·헤더(Authorization 포함)가 로그에 남습니다. 릴리스에서는 비활성화하고 민감 헤더는 마스킹하세요.

   fun provideHttpLoggingInterceptor(): HttpLoggingInterceptor {
-    return HttpLoggingInterceptor().apply {
-        level = HttpLoggingInterceptor.Level.BODY
-    }
+    return HttpLoggingInterceptor().apply {
+        level = if (BuildConfig.DEBUG)
+            HttpLoggingInterceptor.Level.BODY
+        else
+            HttpLoggingInterceptor.Level.NONE
+        redactHeader("Authorization")
+        redactHeader("Cookie")
+    }
🧹 Nitpick comments (1)
app/src/main/java/com/konkuk/medicarecall/data/di/NetworkModule.kt (1)

57-63: 인터셉터 순서/타임아웃 정비 제안

  • 로깅은 마지막에 두어 최종 요청/응답을 관찰하도록 권장.
  • connectTimeout/writeTimeout도 명시해 일관성 확보.
   return OkHttpClient.Builder()
-      .readTimeout(20, TimeUnit.SECONDS)
+      .readTimeout(20, TimeUnit.SECONDS)
+      .connectTimeout(20, TimeUnit.SECONDS)
+      .writeTimeout(20, TimeUnit.SECONDS)
       .addInterceptor(authInterceptor)
-      .addInterceptor(loggingInterceptor)
-      .authenticator(authAuthenticator)
+      .authenticator(authAuthenticator)
+      .addInterceptor(loggingInterceptor) // 마지막에
       .build()
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f11aef6 and afbd7fc.

📒 Files selected for processing (3)
  • app/src/main/java/com/konkuk/medicarecall/data/api/auth/AuthService.kt (1 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/di/NetworkModule.kt (3 hunks)
  • app/src/main/java/com/konkuk/medicarecall/data/network/AuthAuthenticator.kt (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/com/konkuk/medicarecall/data/api/auth/AuthService.kt
⏰ 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: ci-build
🔇 Additional comments (3)
app/src/main/java/com/konkuk/medicarecall/data/network/AuthAuthenticator.kt (1)

16-16: Lazy 주입으로 순환참조 리스크 해소

dagger.Lazy<AuthService>로 전환한 점 좋습니다. 과거 코멘트에서 제안된 순환 참조 방지 가이드를 충실히 반영했습니다.

app/src/main/java/com/konkuk/medicarecall/data/di/NetworkModule.kt (2)

35-40: AuthAuthenticator에 Lazy 주입 배선 OK

Provider 형태로 주입해 순환 참조 가능성을 낮춘 구성 좋습니다.


52-56: 리프레시 전용 클라이언트 분리 확인 필요
현재 제공된 OkHttpClient(provideOkHttpClient)에는 .authenticator(authAuthenticator)가 장착되어 있어, 같은 인스턴스를 AuthService.refreshToken() 호출에 재사용하면 무한 재귀가 발생할 위험이 있습니다. 별도 인증로직이 배제된 Retrofit/OkHttpClient(@nAmed("noAuth") 등)를 구성했는지 확인 바랍니다.

Comment on lines 47 to 49
val refreshResponse = runBlocking {
tokenRefreshService.get().refreshToken(TokenRefreshRequestDto(refreshToken))
authService.get().refreshToken(TokenRefreshRequestDto(refreshToken))
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

리프레시 호출이 동일 OkHttp(인터셉터/Authentictor 포함)를 타는지 확인 필요

authService.get().refreshToken(...)가 현재 클라이언트의 AuthInterceptor/AuthAuthenticator를 그대로 타면, 401 시 재귀가 발생합니다. 리프레시 전용 Retrofit(인터셉터·Authenticator 미적용) 또는 인터셉터에서 리프레시 경로를 명시적으로 스킵하는지 확인 부탁드립니다. 필요 시 @Named 클라이언트 분리 권장.


🏁 Script executed:

#!/bin/bash
# AuthService 제공자/클라이언트 배선 확인
rg -nP --type=kt -C3 'provideAuthService|Retrofit\\s*\\.\\s*create\\(\\s*AuthService::class' app

# AuthInterceptor가 리프레시/인증 경로를 스킵하는지 확인
rg -nP --type=kt -C3 'class\\s+AuthInterceptor\\b|intercept\\(|encodedPath|auth/refresh|verification' app

# 별도 no-auth/refresh 클라이언트 존재 여부
rg -nP --type=kt -C2 '@Named\\(|@Qualifier|noAuth|unauth|refresh' app

Length of output: 218


스크립트 패턴의 괄호 이스케이프가 빠져 에러가 발생한 것 같습니다. 아래 수정된 스크립트를 실행해 리프레시 전용 클라이언트 분리 여부와 인터셉터/Authenticator 스킵 로직을 확인해 주세요.


🏁 Script executed:

#!/bin/bash
# AuthService 제공자/클라이언트 배선 확인
rg -nP --type=kt -C3 'provideAuthService' app
rg -nP --type=kt -C3 'Retrofit\s*\.create\(\s*AuthService::class\s*\)' app

# AuthInterceptor가 리프레시/인증 경로를 스킵하는지 확인
rg -nP --type=kt -C3 'class\s+AuthInterceptor' app
rg -nP --type=kt -C3 'fun\s+intercept' app
rg -nP --type=kt -C3 'encodedPath.*refresh' app

# 별도 no-auth/refresh 클라이언트 존재 여부
rg -nP --type=kt -C2 '@Named.*(noAuth|unauth|refresh)' app

Length of output: 161


ripgrep에서 --type=kt를 인식하지 못하는 것 같습니다. 글로브 필터로 .kt 파일을 지정해 다시 실행해 보세요.


🏁 Script executed:

#!/bin/bash
# AuthService 제공자/클라이언트 배선 확인
rg -g '*.kt' -n -C3 'provideAuthService' app
rg -g '*.kt' -n -C3 'Retrofit\s*\.create\(\s*AuthService::class\s*\)' app

# AuthInterceptor가 리프레시/인증 경로를 스킵하는지 확인
rg -g '*.kt' -n -C3 'class\s+AuthInterceptor\b' app
rg -g '*.kt' -n -C3 'fun\s+intercept\b' app
rg -g '*.kt' -n -C3 'encodedPath.*refresh' app

# 별도 no-auth/refresh 클라이언트 존재 여부
rg -g '*.kt' -n -C2 '@Named.*(noAuth|unauth|refresh)' app

Length of output: 2204


리프레시 전용 Retrofit 클라이언트 분리 필요
현재 authService.get().refreshToken(...)가 동일한 OkHttp 클라이언트(인터셉터/Authenticator 포함)를 사용해 호출되어 401 응답 시 무한 재귀 위험이 있습니다.
리프레시 전용 Retrofit 클라이언트를 @Named 또는 @Qualifier로 분리하거나, AuthInterceptor에서 refresh 경로를 명시적으로 스킵하도록 구현하세요.

🤖 Prompt for AI Agents
In app/src/main/java/com/konkuk/medicarecall/data/network/AuthAuthenticator.kt
around lines 47-49, the code calls authService.get().refreshToken(...) using the
same OkHttp client (with interceptors/Authenticator), which risks infinite
recursion on 401 during token refresh; create and inject a dedicated
Retrofit/OkHttp client for refresh calls (annotated with @Named or a custom
@Qualifier) that has no Authenticator or request interceptor that triggers token
refresh, or modify the interceptor to explicitly skip the refresh endpoint
(e.g., check request.url.path and return without adding auth/refresh logic);
update DI to provide both the regular authService and a refresh-only authService
and use the refresh-only instance inside runBlocking so refreshToken requests do
not pass through the Authenticator/interceptors.

Copy link
Contributor

@ikseong00 ikseong00 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 +122 to +125

tasks.withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach {
jvmTarget = "11"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

이건 무슨 코드인가요..?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Detekt 실행 시 빌드 실패가 발생해서 추가한 코드입니다!

Comment on lines 35 to +39
fun provideAuthAuthenticator(
dataStoreRepository: DataStoreRepository,
tokenRefreshService: dagger.Lazy<TokenRefreshService>,
authService: dagger.Lazy<AuthService>
): AuthAuthenticator {
return AuthAuthenticator(dataStoreRepository, tokenRefreshService)
return AuthAuthenticator(dataStoreRepository, authService)
Copy link
Contributor

Choose a reason for hiding this comment

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

여기 코드에서 순환 의존성 때문에 Lazy 로 선언하신 것 같습니다.

  • AuthService → Retrofit → OkHttpClient → AuthAuthenticator → AuthService
    현재 위와 같이 순환 의존성이 있어서, 맨 뒤 AuthService 를 Lazy 로 선언해서 빌드 시에 순환 참조가 되지 않도록 하는 셈인데,

위와 같은 상황을 방지하게 위해 지연 생성을 하기 보단, tokenRepository를 사용해서 하면 좋을 것 같습니다!

현재 PR 에 대한 내용은 아니니 추후 참고용으로 달아놓을게요!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

피드백 감사합니다! 말씀 주신 부분 추후 리팩토링 시 참고하면 좋을 것 같아요

@librawish808 librawish808 changed the title [Refactor] API 서비스 패키지 구조 개편 [Refactor] API 서비스 패키지 구조 개편 #123 Oct 3, 2025
@ProtossManse
Copy link
Collaborator

LGTM

Copy link
Collaborator

@alswlekk alswlekk left a comment

Choose a reason for hiding this comment

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

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor] API 서비스 패키지 구조 개편

5 participants