Skip to content

#1 [init] : 초기 세팅#3

Merged
fredleeJH merged 1 commit intodevelopfrom
init/#1-project-setting
Sep 29, 2025
Merged

#1 [init] : 초기 세팅#3
fredleeJH merged 1 commit intodevelopfrom
init/#1-project-setting

Conversation

@fredleeJH
Copy link
Contributor

@fredleeJH fredleeJH commented Sep 23, 2025

Related issue 🛠

  • closed #이슈넘버

Work Description 📝

  • 작업 내용

Screenshot 📸

Uncompleted Tasks 😅

  • Task1

PR Point 📌

트러블 슈팅 💥

Summary by CodeRabbit

  • New Features
    • 홈 화면 추가 및 상태별 UI 제공(로딩/성공/실패/빈 상태).
    • 공통 디자인 시스템(테마, 타이포그래피, 버튼) 도입으로 일관된 UI 제공.
    • 보안 데이터스토어로 액세스/리프레시 토큰 암호화 저장.
  • Changes
    • 앱 테마를 MaterialComponents 기반으로 업데이트하고 런처 액티비티 구성을 정비.
    • 네트워크 통신을 위한 권한 및 설정 추가(INTERNET, 위치, 진동; 평문 트래픽 허용).
  • Chores
    • 멀티 모듈 구조와 빌드 플러그인 정비로 성능·유지보수성 향상.

@fredleeJH fredleeJH self-assigned this Sep 23, 2025
@fredleeJH fredleeJH added 🐶 종훈 ⚙️ [SETTING] 프로젝트 기초 세팅 labels Sep 23, 2025
@coderabbitai
Copy link

coderabbitai bot commented Sep 23, 2025

Walkthrough

모놀리식 앱을 멀티모듈( core/, data/, domain/, feature/ ) 구조로 재편하고, 커스텀 Gradle 컨벤션 플러그인(build-logic/*)을 도입했습니다. 앱은 Hilt Application을 사용하도록 변경됐고, 네트워크/빌드컨피그/데이터스토어/디자인시스템/네비게이션/모델 등 핵심 코어 모듈과 홈 기능의 도메인/데이터/피처 모듈이 추가되었습니다. 루트/모듈 .gitignore와 빌드 스크립트가 정리/확장되었습니다.

Changes

Cohort / File(s) Summary
레포 설정 & IDE
/.gitignore, /.idea/vcs.xml
.gitignore 대폭 확장 및 재구성(Android/Kotlin/Studio/플러그인/패치 항목 추가), VCS 매핑을 Git에 명시.
루트 빌드 스크립트
/build.gradle.kts
플러그인 alias 정리 및 추가(compose.compiler, android.library, serialization, ksp, hilt, ktlint, kotlin.jvm).
빌드 로직(컨벤션 플러그인)
/build-logic/settings.gradle.kts, /build-logic/convention/build.gradle.kts, /build-logic/convention/.gitignore, /build-logic/convention/src/main/java/*, /build-logic/convention/src/main/java/com/umcspot/spot/convention/...
Spot 전용 플러그인 다수 등록(애플리케이션/라이브러리/Compose/Hilt/데이터/피처/테스트/자바), Kotlin/Android/Compose/Coroutine/BuildConfig 설정 헬퍼, 의존성 헬퍼/버전카탈로그 확장 추가.
앱 모듈 구성 변경
/app/build.gradle.kts, /app/src/main/AndroidManifest.xml, /app/src/main/java/com/umcspot/spot/SpotApplication.kt, /app/src/main/java/com/umcspot/spot/MainActivity.kt(삭제), /app/src/main/java/com/umcspot/spot/ui/theme/*(삭제), /app/src/main/res/values/themes.xml
Hilt Application 도입, 퍼미션/테마/액티비티 패키지 경로 변경, Compose 테마 코드 제거, XML 테마 정의 교체, 모듈 의존성 전환.
core-common
/core/common/*
BuildConfigFields 데이터/프로바이더 인터페이스 추가, 모듈 스켈레톤 및 빌드 스크립트.
core-buildconfig
/core/buildconfig/*
Hilt 모듈과 구현체로 BuildConfigFields 제공(로컬 프로퍼티 기반), 모듈 스켈레톤/프로가드.
core-network
/core/network/*
Retrofit/OkHttp/Json 컨버터 DI 모듈 추가(BuildConfigProvider로 baseUrl 주입), BaseResponse/서비스 스켈레톤 추가, 빌드 스크립트/매니페스트.
core-datastore(보안 저장소)
/core/datastore/*
AES-GCM(AndroidKeystore) 기반 Serializer, SpotTokenData, DataStore Hilt 모듈 추가, 빌드 스크립트.
core-ui
/core/ui/*
Compose 유틸 확장(screenWidth/Height 스케일, noRipple 클릭), UI 상태 모델(UiState) 추가, 빌드 스크립트.
core-designsystem
/core/designsystem/*
컬러 팔레트/타이포그래피/테마(CompositionLocal 포함)와 공용 버튼 컴포넌트, 아이콘 리소스 추가, 빌드 스크립트.
core-model
/core/model/*
직렬화 지원 자바 라이브러리 설정 및 예시 enum 추가.
core-navigation
/core/navigation/*
기본 Route/MainTabRoute 인터페이스 추가, 모듈 스켈레톤.
domain-home
/domain/home/*
Home 도메인 모델(Dummy/DummyResult)과 리포지토리 인터페이스 추가, 빌드 스크립트.
data-home
/data/home/*
Retrofit 서비스/DTO/데이터소스/리포지토리 구현, 매퍼, DI 모듈(HomeService/HomeDataSource/HomeRepository 바인딩) 추가.
feature-home
/feature/home/*
HomeScreen 컴포저블 추가(viewModel 상태에 따라 출력), 모듈 스켈레톤/빌드 스크립트.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Android as Android OS
  participant App as SpotApplication(Hilt)
  participant DI as Hilt Graph
  participant DS as DataStore<SpotTokenData>
  participant Net as NetworkModule

  User->>Android: 앱 실행
  Android->>App: Application.onCreate()
  App->>DI: Hilt 그래프 초기화
  DI-->>DS: SpotSecureDataStoreSerializer로 DataStore 제공
  DI-->>Net: Retrofit(OkHttp+Json+baseUrl) 제공
  note over Net: baseUrl은 BuildConfigFieldProvider.get() 사용
Loading
sequenceDiagram
  autonumber
  participant UI as HomeScreen
  participant VM as HomeViewModel
  participant Repo as HomeRepository
  participant Svc as HomeService(Retrofit)
  participant Map as Mapper
  participant State as UiState

  UI->>VM: 구독 시작(collectAsStateWithLifecycle)
  VM->>Repo: getDummies(Dummy)
  Repo->>Svc: POST /api/v1/service (HomeRequestDto)
  Svc-->>Repo: BaseResponse<HomeResponseDto>
  Repo->>Map: response.data.toDomain()
  Map-->>Repo: DummyResult
  Repo-->>VM: Result<DummyResult>
  alt 성공
    VM-->>UI: State.Success(data)
  else 실패
    VM-->>UI: State.Failure(msg)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

깡충! 새 모듈에 햇살이 쏟아져요 ☀️
빌드-로직 숲에 토끼 길을 냈지요 🛠️
데이터는 금고에, 열쇠는 키스토어에 🔐
Hilt 바람 타고 의존성은 춤추고—💃
홈 탭엔 응답이 톡톡, UI는 빛나요 ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning PR 설명은 템플릿 구조를 모두 포함하고 있으나 대부분이 플레이스홀더(예: "closed #이슈넘버", "작업 내용", 빈 스크린샷 src, 비어있는 PR Point/트러블슈팅)로 남아 있어 실제 변경 내용, 리뷰 요청 포인트, 리스크를 판단할 수 없습니다. 실제 이슈 번호/링크를 기재하고 작업 내용에 주요 변경 파일·의도·브레이킹 체인지·빌드 영향 등을 구체적으로 작성하며 PR Point에 리뷰어에게 요청할 검토 항목을 명시하고 스크린샷은 유효한 이미지로 교체 또는 설명을 추가하고 미완료 항목과 트러블슈팅에는 알려진 문제 및 후속 작업을 적어 주세요.
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 (1 passed)
Check name Status Explanation
Title Check ✅ Passed PR 제목 "#1 [init] : 초기 세팅"은 변경사항의 주된 목적(프로젝트 초기 세팅 및 모듈/빌드 로직 추가)을 명확히 요약하고 있어 PR의 핵심을 잘 전달합니다. 다만 "#1" 접두사와 대괄호 표기는 메타데이터로 약간의 잡음을 줄 수 있습니다.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch init/#1-project-setting

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: 22

🧹 Nitpick comments (71)
core/common/src/main/AndroidManifest.xml (2)

2-4: 내용이 전혀 없다면 파일 제거 제안

현재 선언/권한/컴포넌트가 전무하다면 이 매니페스트 파일을 삭제해도 빌드에 영향이 없습니다(필요 시 나중에 추가). 저장소 노이즈를 줄일 수 있습니다.

-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android">
-
-</manifest>
+// 파일 삭제

4-4: EOF 개행 추가 권장

파일 말미 개행이 없어 diff가 불필요하게 시끄러워질 수 있습니다. 한 줄 개행을 추가해 주세요.

-</manifest>
+</manifest>
+
core/ui/src/main/AndroidManifest.xml (1)

1-4: 의도 명시 코멘트 추가(선택): 추후 오사용 방지

팀 합의가 “core/ui에서는 Android 컴포넌트 미선언”이라면 파일 상단에 의도 주석을 남겨 오사용을 줄이는 것을 권장합니다.

 <?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+<!-- Intentionally empty manifest for core/ui library module.
+     Do not declare components here; use the app or feature manifests instead. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
 
 </manifest>
core/ui/src/main/java/com/umcspot/spot/ui/state/UiState.kt (4)

12-14: Failure에 원인(cause) 포함 권장.

디버깅/로깅/리트라이 판단을 위해 메시지 외에 Throwable?을 함께 보유하는 편이 실용적입니다.

다음과 같이 확장 제안드립니다:

-    data class Failure(
-        val msg: String
-    ) : UiState<Nothing>
+    data class Failure(
+        val message: String,
+        val cause: Throwable? = null
+    ) : UiState<Nothing>

추가로 i18n을 고려하면 String 대신 UiText(stringRes/문자열 래퍼)로의 전환을 후속으로 검토해 주세요.


4-7: Empty의 의미 모호성(Idle vs. 비어있는 결과) 정리 제안.

요청 전 초기 상태(Idle)와 "성공했으나 데이터가 비어있음"은 종종 다른 의미입니다. 혼동을 줄이려면 초기 상태를 Idle로 명명하고, 빈 결과는 Success(emptyList()) 등으로 표현하는 패턴을 권장합니다.

가능한 변경 예:

-    data object Empty : UiState<Nothing>
+    data object Idle : UiState<Nothing>

(참고: 사용처 전부 리네이밍 필요)


3-3: Compose 사용 시 안정성 힌트: @immutable 부여.

Compose 기반이라면 불필요한 재구성을 줄이기 위해 루트에 @Immutable을 부여하세요.

예시:

+import androidx.compose.runtime.Immutable
+
+@Immutable
 sealed interface UiState<out T> {

3-15: 편의 확장 추가 제안(map/fold/getOrNull).

상태 전파/변환이 잦다면 다음과 같은 확장을 별도 파일에 두면 호출부가 간결해집니다.

// 예: core/ui/.../UiStateExt.kt
inline fun <T, R> UiState<T>.map(transform: (T) -> R): UiState<R> = when (this) {
    is UiState.Success -> UiState.Success(transform(data))
    is UiState.Loading -> UiState.Loading
    is UiState.Failure -> UiState.Failure(message, cause)
    is UiState.Empty /* or Idle */ -> this
}

inline fun <T, R> UiState<T>.fold(
    onSuccess: (T) -> R,
    onLoading: () -> R,
    onFailure: (String, Throwable?) -> R,
    onEmpty: () -> R
): R = when (this) {
    is UiState.Success -> onSuccess(data)
    is UiState.Loading -> onLoading()
    is UiState.Failure -> onFailure(message, cause)
    is UiState.Empty /* or Idle */ -> onEmpty()
}

fun <T> UiState<T>.getOrNull(): T? = (this as? UiState.Success)?.data

원하시면 PR에 맞춰 보일러플레이트 생성 도와드리겠습니다.

core/ui/src/main/java/com/umcspot/spot/ui/extension/DimensionExt.kt (7)

11-16: 함수 이름이 의미와 불일치 (height를 “화면 높이”가 아닌 “스케일 값”으로 반환).

현재 이름(screenHeightDp)은 “화면 높이(dp)”를 돌려주는 듯 보이나, 실제로는 입력값을 Figma 기준으로 스케일링합니다. 오해를 줄이기 위해 의미가 드러나는 이름으로 교체를 권장합니다.

다음과 같이 이름과 파라미터를 명확화하세요:

-@Composable
-fun screenHeightDp(height: Dp): Dp {
-    val screenHeight = LocalConfiguration.current.screenHeightDp.dp
-    val ratio = screenHeight / figmaScreenHeight
-    return height * ratio
-}
+/**
+ * Figma 기준 높이(baseline)에 비례해 value를 스케일링합니다.
+ */
+@Composable
+fun scaleHeight(value: Dp, baselineHeight: Dp = figmaScreenHeight): Dp {
+    val screenHeight = LocalConfiguration.current.screenHeightDp.dp
+    val ratio = screenHeight / baselineHeight
+    return value * ratio
+}

18-23: 동일 이슈: width 함수도 스케일 함수로 명확화.

width 역시 화면 너비 자체를 반환하는 함수처럼 보입니다. 의미를 드러내는 이름으로 교체하세요.

-@Composable
-fun screenWidthDp(width: Dp): Dp {
-    val screenWidth = LocalConfiguration.current.screenWidthDp.dp
-    val ratio = screenWidth / figmaScreenWidth
-    return width * ratio
-}
+/**
+ * Figma 기준 너비(baseline)에 비례해 value를 스케일링합니다.
+ */
+@Composable
+fun scaleWidth(value: Dp, baselineWidth: Dp = figmaScreenWidth): Dp {
+    val screenWidth = LocalConfiguration.current.screenWidthDp.dp
+    val ratio = screenWidth / baselineWidth
+    return value * ratio
+}

8-10: 하드코딩된 Figma 기준값을 상수 형태로 명확화 및 주석 추가.

의도를 드러내는 네이밍과 간단한 주석을 추가하면 재사용성과 가독성이 좋아집니다.

-private val figmaScreenWidth = 360.dp
-private val figmaScreenHeight = 800.dp
+// Figma 디자인 기준 화면 크기 (dp)
+private val figmaScreenWidth: Dp = 360.dp
+private val figmaScreenHeight: Dp = 800.dp

13-15: 시스템 바/내비게이션 바 Inset 미고려로 실제 사용 가능한 영역 기준과 오차 가능.

screenHeightDp/WidthDp는 윈도우 크기 기준이라 시스템 바가 차지하는 영역을 제외하지 않습니다. 실 컨텐츠 영역 기준의 스케일이 필요하면 systemBars inset을 반영하세요.

+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.ui.platform.LocalDensity
@@
-    val screenHeight = LocalConfiguration.current.screenHeightDp.dp
-    val ratio = screenHeight / baselineHeight
+    val configuration = LocalConfiguration.current
+    val density = LocalDensity.current
+    val rawHeight = configuration.screenHeightDp.dp
+    val verticalInsets = with(density) {
+        (WindowInsets.systemBars.getTop(this) + WindowInsets.systemBars.getBottom(this)).toDp()
+    }
+    val usableHeight = (rawHeight - verticalInsets).coerceAtLeast(0.dp)
+    val ratio = usableHeight / baselineHeight
@@
-    val screenWidth = LocalConfiguration.current.screenWidthDp.dp
-    val ratio = screenWidth / baselineWidth
+    val configuration = LocalConfiguration.current
+    val rawWidth = configuration.screenWidthDp.dp
+    // 일반적으로 가로 inset은 미미하지만, 필요 시 아래처럼 적용 가능:
+    // val horizontalInsets = with(LocalDensity.current) {
+    //   (WindowInsets.systemBars.getLeft(this) + WindowInsets.systemBars.getRight(this)).toDp()
+    // }
+    // val usableWidth = (rawWidth - horizontalInsets).coerceAtLeast(0.dp)
+    val ratio = rawWidth / baselineWidth

Also applies to: 20-22


11-23: “디바이스 크기 비례 스케일” 접근은 Compose 권장 패턴과 어긋날 수 있음.

dp는 밀도 독립 단위라, 화면이 커질수록 모든 여백/컴포넌트를 비례 확대하면 태블릿/폴더블에서 과도한 여백과 부자연스러운 UI가 나올 수 있습니다. 레이아웃은 weight/percent, BoxWithConstraints, WindowSizeClass 기반 토큰 전환으로 대응하는 것이 일반적입니다. 최소한 스케일 범위를 클램프하세요.

-    return value * ratio
+    // 예: 0.85x ~ 1.25x 범위로 클램프
+    val clamped = ratio.coerceIn(0.85f, 1.25f)
+    return value * clamped

대안 제안(참고):

  • Breakpoint 기반 토큰 전환: smallestScreenWidthDp(<=360/480/600/840 등)에 따라 Dimens를 교체.
  • 퍼센트 레이아웃: Modifier.fillMaxWidth(fraction)/weight로 가변 폭 대응.
  • 텍스트는 MaterialTheme.typography 혹은 sp 사용. 본 스케일 함수로 텍스트 크기를 조절하지 않기.

3-6: 패키지명이 ui.extension이지만 실제로는 일반 함수 유틸.

확장 함수가 아니라 유틸 함수이므로 패키지/파일 네이밍을 ui.util 또는 ui.scaling 등으로 정리하면 추후 유지보수에 유리합니다.


11-23: KDoc 추가 — 텍스트(fontSize) 용도로 사용 금지

screenWidthDp / screenHeightDp는 패딩·간격·컴포넌트 크기 전용으로 KDoc에 명시하세요. 텍스트는 sp/typography 사용.

검증 결과: fontSize 연관 사용 없음. 현재 사용처:

  • feature/main/src/main/java/com/umcspot/spot/main/component/MainBottomBar.kt — .padding(vertical = screenHeightDp(10.dp)) (라인 ~57)
  • core/designsystem/src/main/java/com/umcspot/spot/designsystem/component/button/SpotButton.kt — .padding(vertical = screenHeightDp(16.dp)) (라인 ~40)
data/home/.gitignore (1)

1-1: 모듈별 build 산출물 무시 추가 LGTM
현 상태로 충분합니다. 선택적으로, 루트 .gitignore에 **/build/를 추가하면 모듈별 .gitignore 중복을 줄일 수 있습니다.

# root .gitignore 예시
+**/build/
domain/home/.gitignore (1)

1-1: 간결한 .gitignore 규칙 OK
모듈 단위로 /build를 무시하는 방향 문제 없습니다. 추후 일관성을 위해 루트에 **/build/를 두고 모듈 파일을 줄이는 것도 고려해주세요.

core/datastore/.gitignore (1)

1-1: LGTM
데이터스토어 모듈의 빌드 산출물만 무시하는 최소 규칙으로 적절합니다. 중복 제거를 원하면 루트 .gitignore로의 집약을 검토해주세요.

core/ui/.gitignore (1)

1-1: OK — 표준적인 /build 무시
유지해도 무방하나, 전역 패턴(**/build/)로 통합 시 모듈별 파일 관리가 줄어듭니다.

feature/home/.gitignore (1)

1-1: LGTM
필요 최소 규칙입니다. 저장소 전역 패턴으로의 통합은 선택 사항입니다.

build-logic/convention/.gitignore (1)

1-1: Gradle 컨벤션 플러그인 모듈에도 /build 무시 필요 — 적절합니다
build-logic 영역은 빌드 출력이 비교적 많으니 현재 규칙 유지 추천. 전역 패턴으로의 통합은 팀 규칙에 맞춰 결정하세요.

core/model/.gitignore (1)

1-1: 모델 모듈 빌드 산출물 제외 LGTM
추가로 제외할 항목은 없어 보입니다. 전역 패턴 통합은 선택입니다.

domain/home/src/main/java/com/umcspot/spot/home/model/Dummy.kt (1)

3-6: 더미 모델의 명명과 구조 개선 권장

현재 Dummy 클래스는 초기 설정을 위한 임시 모델로 보이지만, 실제 도메인을 반영하는 의미 있는 이름으로 변경하는 것을 권장합니다. 또한 email 필드의 유효성 검증 로직이나 타입 안전성을 고려해볼 수 있습니다.

실제 홈 도메인에 맞는 모델로 리팩토링하는 예시:

-data class Dummy(
-    val id: Int,
-    val email: String
-)
+data class User(
+    val id: Long,
+    val email: String
+) {
+    init {
+        require(email.isNotBlank()) { "Email cannot be blank" }
+        require(android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) { "Invalid email format" }
+    }
+}

또는 이메일을 위한 값 객체를 사용하는 방법:

@JvmInline
value class Email(val value: String) {
    init {
        require(value.isNotBlank()) { "Email cannot be blank" }
        require(android.util.Patterns.EMAIL_ADDRESS.matcher(value).matches()) { "Invalid email format" }
    }
}

data class User(
    val id: Long,
    val email: Email
)
data/home/proguard-rules.pro (1)

1-21: 라이브러리 ProGuard 규칙 연결 방식 확인 필요.

현재 파일은 템플릿만 있고 규칙이 비어 있습니다. 이 모듈이 라이브러리라면 파일명을 consumer-rules.pro로 변경하거나, build.gradle(.kts)에서 consumerProguardFiles로 명시해 앱에 전파되도록 해주세요(빌드 로직 플러그인에서 공통 적용도 가능).

예시:

android {
  defaultConfig {
    consumerProguardFiles("proguard-rules.pro")
  }
}
core/ui/proguard-rules.pro (1)

1-21: consumer 규칙 전파 경로 점검 권장.

이 파일이 활성 규칙을 담게 될 경우, 라이브러리 모듈이면 consumer-rules.pro로 이름을 맞추거나 consumerProguardFiles로 연결되어 있는지 확인해주세요(공통 플러그인에서 일괄 세팅 권장).

core/common/proguard-rules.pro (1)

1-21: 동일: consumer 규칙 전파 확인.

라이브러리 모듈이라면 consumer-rules.pro 사용 또는 consumerProguardFiles 연결 여부를 확인해주세요.

core/designsystem/proguard-rules.pro (1)

1-21: 동일: ProGuard 규칙 파일 전파 경로 정합성.

consumer-rules.pro로 통일하거나 빌드 로직에서 consumerProguardFiles로 묶어주는지 확인 부탁드립니다.

.idea/vcs.xml (1)

3-5: IDE 전용 파일 커밋 지양 권장.

VCS 매핑(.idea/vcs.xml)은 개인 환경에 종속됩니다. 팀 합의가 없다면 버전 관리에서 제외하는 편이 안전합니다. 필요한 경우 .gitignore에 다음을 추가하고, 코드스타일/검사 프로필만 예외적으로 포함하세요.

+.idea/
+!.idea/codeStyles/
+!.idea/inspectionProfiles/
feature/home/proguard-rules.pro (1)

1-21: 라이브러리/피처 모듈이면 consumerProguardFiles로 전파하세요.

feature/home가 Android 라이브러리(또는 dynamic feature)라면 이 파일(proguard-rules.pro)은 소비 앱에 전파되지 않습니다. 빌드 스크립트에서 consumerProguardFiles("proguard-rules.pro")로 연결하거나, 관례적으로 consumer-rules.pro로 파일명을 두고 자동 인식을 활용하세요.

core/navigation/proguard-rules.pro (1)

1-21: Navigation 모듈 규칙은 consumer 규칙으로 노출 필요.

코어 네비게이션은 라이브러리 성격이므로, 외부 앱/모듈 소비 시 난독화 예외가 전파되도록 consumerProguardFiles에 연결하거나 consumer-rules.pro로 관리하는 것을 권장합니다.

core/network/proguard-rules.pro (1)

1-21: 네트워크 레이어의 모델/리플렉션 의존 타입은 consumer 규칙화 고려.

Retrofit/Moshi/Gson 등 리플렉션 기반이면 DTO/어댑터의 keep 규칙이 소비자에게 전파되어야 합니다. consumerProguardFiles("proguard-rules.pro") 또는 consumer-rules.pro로 전환 검토 부탁드립니다.

domain/home/src/main/java/com/umcspot/spot/home/model/DummyResult.kt (1)

3-5: 도메인 컬렉션의 불변성 강화 제안.

List<String>은 읽기 전용 인터페이스지만 내부가 가변일 수 있습니다. 계층 간 안전성을 위해 kotlinx.collections.immutable.PersistentList로의 전환을 고려해 주세요.

feature/home/src/main/java/com/umcspot/spot/home/HomeScreen.kt (3)

21-27: 하드코딩 색상 대신 테마 사용.

Color.White/Color.Gray/Color.Red는 다크 모드/테마와 어긋납니다. MaterialTheme.colorScheme로 치환하세요.

-            .background(Color.White),
+            .background(MaterialTheme.colorScheme.background),

또한 텍스트 색상도 MaterialTheme.colorScheme.onBackground/error 등을 사용하세요.


34-36: 스크롤 가능한 리스트는 LazyColumn 사용.

forEachIndexed로 직접 그리기보다 LazyColumn이 메모리/성능에 안전합니다.

-            is UiState.Success -> {
-                state.data.info.forEachIndexed { index, item ->
-                    Text(text = "Info[$index]: $item")
-                }
-            }
+            is UiState.Success -> {
+                LazyColumn(
+                    modifier = Modifier.fillMaxSize(),
+                    horizontalAlignment = Alignment.CenterHorizontally
+                ) {
+                    itemsIndexed(state.data.info) { index, item ->
+                        Text(text = "Info[$index]: $item")
+                    }
+                }
+            }

30-45: 문자열 리터럴은 stringResource로 국제화.

고정 문자열(“로딩 중…”, “에러: …”, “데이터가 없습니다.”)은 stringResource(id = …)로 분리하세요.

core/ui/src/main/java/com/umcspot/spot/ui/extension/ModifierExt.kt (1)

11-21: 불필요한 Lint 억제 제거 제안.

현재 두 함수 모두 this를 참조하면 @SuppressLint("ModifierFactoryUnreferencedReceiver")는 필요 없습니다. 제거하여 신호 대 잡음비를 개선하세요.

.gitignore (1)

183-187: 비밀/서명 속성 파일 추가 무시 권장.

secrets.properties(Gradle Secrets), keystore.properties/signing.properties 등 누락되어 있습니다. 유출 위험을 줄이세요.

 # End of https://www.toptal.com/developers/gitignore/api/android,androidstudio,kotlin
+#
+# Secrets & signing properties
+secrets.properties
+keystore.properties
+signing.properties
+.env
+.env.*
core/network/src/main/java/com/umcspot/spot/network/service/TokenRefreshService.kt (1)

3-4: 빈 클래스의 용도를 명확히 하세요.

TokenRefreshService 클래스가 비어있습니다. TODO 주석을 추가하거나 향후 구현 계획을 문서화하는 것을 권장합니다.

클래스에 용도를 설명하는 주석을 추가하세요:

+/**
+ * TODO: 토큰 갱신 관련 네트워크 서비스 구현 예정
+ */
 class TokenRefreshService {
 }
core/designsystem/src/main/res/drawable/ic_home.xml (1)

1-6: 벡터 드로어블 최적화를 권장합니다.

홈 아이콘이 적절히 정의되어 있지만, 다음 사항들을 개선할 수 있습니다:

  1. 너비 값이 소수점으로 설정되어 있어 픽셀 정렬에 문제가 있을 수 있습니다
  2. 빈 줄들이 포함되어 있습니다

다음과 같이 최적화하세요:

-<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="58" android:viewportWidth="54" android:width="22.344828dp">
-      
+<vector xmlns:android="http://schemas.android.com/apk/res/android" 
+    android:height="24dp" 
+    android:width="24dp"
+    android:viewportHeight="58" 
+    android:viewportWidth="54">
     <path android:fillColor="#1E1E1E" android:pathData="M22.65,1.596C23.867,0.57 25.408,0.008 27,0.008C28.592,0.008 30.133,0.57 31.35,1.596L51.6,18.672C53.121,19.956 54,21.843 54,23.832V51.762C54,53.155 53.447,54.49 52.462,55.475C51.478,56.459 50.142,57.012 48.75,57.012H38.25C36.858,57.012 35.522,56.459 34.538,55.475C33.553,54.49 33,53.155 33,51.762V36.741C33,36.542 32.921,36.352 32.78,36.211C32.64,36.07 32.449,35.991 32.25,35.991H21.75C21.551,35.991 21.36,36.07 21.22,36.211C21.079,36.352 21,36.542 21,36.741V51.762C21,53.155 20.447,54.49 19.462,55.475C18.478,56.459 17.142,57.012 15.75,57.012H5.25C4.561,57.012 3.878,56.877 3.241,56.613C2.604,56.349 2.025,55.962 1.538,55.475C1.05,54.987 0.663,54.409 0.4,53.771C0.136,53.134 0,52.452 0,51.762V23.832C0,21.843 0.879,19.956 2.4,18.672L22.65,1.596ZM28.449,5.037C28.043,4.696 27.53,4.509 27,4.509C26.47,4.509 25.957,4.696 25.551,5.037L5.301,22.11C5.05,22.321 4.849,22.584 4.711,22.881C4.572,23.178 4.5,23.502 4.5,23.829V51.759C4.5,52.173 4.836,52.509 5.25,52.509H15.75C15.949,52.509 16.14,52.43 16.28,52.29C16.421,52.149 16.5,51.958 16.5,51.759V36.738C16.5,33.837 18.852,31.488 21.75,31.488H32.25C35.148,31.488 37.5,33.837 37.5,36.738V51.759C37.5,52.173 37.836,52.509 38.25,52.509H48.75C48.949,52.509 49.14,52.43 49.28,52.29C49.421,52.149 49.5,51.958 49.5,51.759V23.829C49.5,23.502 49.428,23.178 49.29,22.881C49.151,22.584 48.95,22.321 48.699,22.11L28.449,5.037Z"/>
-    
 </vector>
-
core/designsystem/build.gradle.kts (1)

8-11: flexible.bottomsheet 의존성 삭제 검토 — 모듈에서 사용되지 않음

core/designsystem/build.gradle.kts(라인 10)에 선언만 존재하며, 모듈 소스에서 'bottomsheet'/'BottomSheet' 검색 결과 없음. 사용 의도가 없으면 의존성 제거, 필요하면 이유를 주석으로 남기세요.

build-logic/settings.gradle.kts (1)

1-14: 저장소 고정 및 플러그인 해상도 명시를 추가해 초기 설정 안정화

프로젝트 전역의 저장소 일관성과 플러그인 해상도 실패를 예방하기 위해 아래 보완을 권장합니다.

적용 diff:

 dependencyResolutionManagement {
+    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
     repositories {
         google()
         mavenCentral()
     }
     versionCatalogs {
         create("libs") {
             from(files("../gradle/libs.versions.toml"))
         }
     }
 }
 
+pluginManagement {
+    repositories {
+        gradlePluginPortal()
+        google()
+        mavenCentral()
+    }
+}
 
 rootProject.name = "build-logic"
 include(":convention")
core/navigation/src/main/java/com/umcspot/spot/navigation/MainTabRoute.kt (1)

3-3: 간단 KDoc 추가 제안

공용 API 표면이라, 의도 파악을 돕는 한 줄 KDoc을 권장합니다.

 package com.umcspot.spot.navigation
 
+/** 메인 탭 영역의 최상위 라우트를 나타내는 마커 인터페이스. */
 interface MainTabRoute : Route
core/buildconfig/proguard-rules.pro (1)

1-21: 향후 난독화 활성화 대비: kotlinx.serialization 기본 keep 규칙 추가 권장

minifyEnabled를 켤 경우 직렬화 리플렉션/생성기 유지가 필요합니다.

적용 diff:

 # If you keep the line number information, uncomment this to
 # hide the original source file name.
 #-renamesourcefileattribute SourceFile
+
+# kotlinx.serialization
+-keep class kotlinx.serialization.** { *; }
+-keepclassmembers class ** {
+    @kotlinx.serialization.SerialName *;
+    @kotlinx.serialization.Serializable *;
+}
+-keepattributes *Annotation*,Signature
data/home/src/main/java/com/umcspot/spot/home/dto/response/HomeResponseDto.kt (1)

3-10: 보일러플레이트 감소 + 널/스키마 변화 내성 강화 제안

동일한 이름이면 @SerialName은 불필요합니다. 또 기본값을 부여하면 응답 필드 누락 시 역직렬화 실패를 줄일 수 있습니다.

-package com.umcspot.spot.home.dto.response
-
-import kotlinx.serialization.SerialName
+package com.umcspot.spot.home.dto.response
+
 import kotlinx.serialization.Serializable
@@
 @Serializable
 data class HomeResponseDto(
-    @SerialName("info")
-    val info: List<String>
+    val info: List<String> = emptyList()
 )
build-logic/convention/src/main/java/SpotDataPlugin.kt (1)

1-28: 플러그인 클래스 패키지화 권장

패키지 선언이 없어 충돌/가독성 이슈가 있을 수 있습니다. 다른 컨벤션들과 동일한 패키지로 맞춰 주세요.

+package com.umcspot.spot.convention
+
 import com.umcspot.spot.convention.extension.getLibrary
 import com.umcspot.spot.convention.extension.implementation
 import com.umcspot.spot.convention.extension.libs
@@
 class SpotDataPlugin : Plugin<Project> {
data/home/src/main/java/com/umcspot/spot/home/di/HomeServiceModule.kt (1)

14-18: 함수 네이밍 정교화

providesDummyService는 실제 타입과 맞지 않습니다. 일관성과 검색성을 위해 providesHomeService로 변경 권장.

-    fun providesDummyService(retrofit: Retrofit): HomeService = retrofit.create(
+    fun providesHomeService(retrofit: Retrofit): HomeService = retrofit.create(
         HomeService::class.java
     )
domain/home/src/main/java/com/umcspot/spot/home/repository/HomeRepository.kt (1)

6-8: 네이밍/계약 정합성 소폭 개선 제안

getDummies가 단수 결과(DummyResult)를 반환해 의미가 모호합니다. getDummyResult 등으로 정밀화하거나, 실제로 다중을 의도하면 반환 타입을 컬렉션으로 맞추는 것을 고려해 주세요. 또한 Result<T> 노출은 모듈 경계를 경직시킬 수 있으니 도메인 고유의 sealed class 에러 모델도 검토해 볼 만합니다.

domain/home/build.gradle.kts (1)

1-3: Android 플러그인 → JVM 플러그인 전환 권장

domain/에서 android. 참조는 없고 domain/home/build.gradle.kts(1–3)에 Android 플러그인(alias(libs.plugins.spot.android.java.library))만 적용되어 있습니다. 해당 plugins 블록을 순수 JVM 플러그인(예: libs.plugins.spot.jvm.library 또는 libs.plugins.spot.kotlin.jvm)으로 교체하세요.

core/buildconfig/src/main/java/com/umcspot/spot/buildconfig/impl/BuildConfigFieldsProviderImpl.kt (1)

11-17: 하드코딩된 isDebug 값 개선 권장

Line 16에서 isDebug = true로 하드코딩되어 있습니다. BuildConfig.DEBUG를 사용하여 빌드 타입에 따라 자동으로 설정되도록 개선하는 것이 좋겠습니다.

다음과 같이 수정하는 것을 권장합니다:

-            isDebug = true
+            isDebug = BuildConfig.DEBUG

이를 위해 BuildConfig.DEBUG import도 추가해야 합니다:

 import com.umcspot.spot.buildconfig.BuildConfig.BASE_URL
+import com.umcspot.spot.buildconfig.BuildConfig.DEBUG
 import com.umcspot.spot.buildconfig.BuildConfig.KAKAO_NATIVE_KEY
data/home/src/main/java/com/umcspot/spot/home/di/HomeRepositoryModule.kt (1)

12-17: 리포지토리 DI 바인딩이 적절합니다

HomeRepositoryImpl을 HomeRepository 인터페이스에 바인딩하는 설정이 올바르게 구현되어 있습니다. 메서드명 bindsDummyRepository는 더 명확한 이름으로 변경하는 것을 고려해볼 수 있습니다.

메서드명을 더 명확하게 변경하는 것을 고려해보세요:

-    abstract fun bindsDummyRepository(dummyRepositoryImpl: HomeRepositoryImpl): HomeRepository
+    abstract fun bindsHomeRepository(homeRepositoryImpl: HomeRepositoryImpl): HomeRepository
core/network/src/main/java/com/umcspot/spot/network/model/BaseResponse.kt (1)

1-1: 패키지명이 프로젝트 네이밍 컨벤션과 일치하지 않습니다

다른 파일들에서는 com.umcspot.spot. 접두사를 사용하는데, 이 파일만 network.model을 사용하고 있습니다.

-package network.model
+package com.umcspot.spot.network.model
build-logic/convention/src/main/java/SpotFeaturePlugin.kt (1)

13-16: 모든 피처에 직렬화 플러그인 강제 적용은 과도합니다.

직렬화를 사용하지 않는 피처까지 org.jetbrains.kotlin.plugin.serialization을 적용하면 빌드 시간/복잡도가 불필요하게 늘 수 있습니다. 필요 모듈에서만 적용하거나 플러그인을 분리(예: spot.feature.serialization)하세요.

core/designsystem/src/main/java/com/umcspot/spot/designsystem/component/button/SpotButton.kt (2)

33-41: 접근성(Role) 및 클릭 가능 상태 반영, 조건부 배경/보더 적용 제안.

  • Role.Button 미설정
  • Color.Unspecified에도 항상 background/border 호출
  • 클릭 가능 상태 미반영

수정안:

+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.runtime.remember
@@
-    Row(
-        modifier = modifier
-            .fillMaxWidth()
-            .clip(RoundedCornerShape(12.dp))
-            .background(color = buttonBackgroundColor)
-            .border(width = 1.dp, color = buttonStrokeColor, shape = RoundedCornerShape(12.dp))
-            .noRippleClickable(onClick = onClick)
-            .padding(vertical = screenHeightDp(16.dp)),
+    Row(
+        modifier = modifier
+            .fillMaxWidth()
+            .clip(RoundedCornerShape(12.dp))
+            .let { m -> if (buttonBackgroundColor != Color.Unspecified) m.background(buttonBackgroundColor) else m }
+            .let { m -> if (buttonStrokeColor != Color.Unspecified) m.border(1.dp, buttonStrokeColor, RoundedCornerShape(12.dp)) else m }
+            .padding(vertical = screenHeightDp(16.dp))
+            .semantics { role = Role.Button }
+            .clickable(
+                enabled = enabled,
+                indication = null,
+                interactionSource = remember { MutableInteractionSource() },
+                onClick = onClick
+            ),

40-40: 패딩의 스크린 비율 스케일링은 과도합니다.

screenHeightDp(16.dp)는 기기별 일관성이 떨어집니다. 고정 토큰(dp) 또는 테마 스페이싱 사용을 권장합니다.

build-logic/convention/src/main/java/UnitTestPlugin.kt (1)

20-26: 애플리케이션 모듈 적용 시 타입 미스매치 위험.

LibraryExtension에만 한정하면 앱 모듈에서 플러그인 적용 시 실패합니다. ApplicationExtension도 지원하거나 findByType로 안전하게 처리하세요.

수정안:

+import com.android.build.api.dsl.ApplicationExtension
@@
-            extensions.configure<LibraryExtension> {
-                testOptions {
-                    unitTests {
-                        isIncludeAndroidResources = true
-                    }
-                }
-            }
+            extensions.findByType(LibraryExtension::class.java)?.apply {
+                testOptions.unitTests.isIncludeAndroidResources = true
+            }
+            extensions.findByType(ApplicationExtension::class.java)?.apply {
+                testOptions.unitTests.isIncludeAndroidResources = true
+            }
data/home/src/main/java/com/umcspot/spot/home/repositoryimpl/HomeRepositoryImpl.kt (1)

15-19: 널 안전성과 에러 매핑 강화 권장.

response.data가 널인 경우 NPE 가능. mapCatchingrequireNotNull로 의미 있는 실패를 반환하세요.

수정안:

-    override suspend fun getDummies(request: Dummy): Result<DummyResult> =
-        runCatching {
-            val response = homeService.getDummies(request = request.toData())
-            response.data.toDomain()
-        }
+    override suspend fun getDummies(request: Dummy): Result<DummyResult> =
+        runCatching { homeService.getDummies(request = request.toData()) }
+            .mapCatching { response ->
+                requireNotNull(response.data) { "HomeService.getDummies(): response.data == null" }
+                    .toDomain()
+            }
build-logic/convention/src/main/java/JavaLibraryPlugin.kt (1)

21-28: JDK 17 툴체인/호환성 설정 적절합니다.

구성 타당. 작은 제안: javax.inject는 런타임 필요성이 낮아 compileOnly로도 충분한 경우가 많습니다(프레임워크에 따라 상이).

대안:

-                implementation(libs.getLibrary("javax.inject"))
+                compileOnly(libs.getLibrary("javax.inject"))
build.gradle.kts (1)

10-10: ktlint 적용 범위 확인 (서브모듈 포함 여부).

루트에만 플러그인이 적용되어 서브모듈이 체크되지 않을 수 있습니다. 컨벤션 플러그인에서 공통 적용하거나 subprojects { apply(plugin = libs.plugins.ktlint.get().pluginId) }로 전체 모듈에 적용해 주세요.

build-logic/convention/src/main/java/com/umcspot/spot/convention/extension/VersionCatalogExt.kt (1)

9-25: 예외 타입을 GradleException으로 통일하면 빌드 로그 가독성이 좋아집니다.

NoSuchElementException 대신 org.gradle.api.GradleException을 사용하면 원인 표시와 스택트레이스가 Gradle UX에 더 어울립니다.

적용 예:

-        NoSuchElementException("Bundle with name $bundleName not found in the catalog")
+        org.gradle.api.GradleException("Bundle '$bundleName' not found in version catalog.")

동일하게 getLibrary, getVersion에도 적용해주세요.

core/datastore/src/main/java/com/umcspot/spot/datastore/di/DataStoreModule.kt (1)

25-29: DataStore 손상 처리기 추가로 안전성 강화.

암호화 DataStore는 역직렬화/복호화 실패 시 손상으로 간주하는 편이 안전합니다. ReplaceFileCorruptionHandler를 설정해 주세요.

+import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
@@
-        DataStoreFactory.create(
-            serializer = spotSecureDataStoreSerializer
-        ) {
-            context.dataStoreFile(DATASTORE_PREFERENCES)
-        }
+        DataStoreFactory.create(
+            serializer = spotSecureDataStoreSerializer,
+            corruptionHandler = ReplaceFileCorruptionHandler { SpotTokenData() },
+            produceFile = { context.dataStoreFile(DATASTORE_PREFERENCES) }
+        )
core/network/src/main/java/com/umcspot/spot/network/di/NetworkModule.kt (3)

31-33: 네트워크 타임아웃 기본값을 지정하세요.

기본 타임아웃(무한 대기)에 의존하면 호출이 걸려 시스템 리소스를 잡아먹습니다.

-        OkHttpClient.Builder()
-            .addInterceptor(loggingInterceptor)
-            .build()
+        OkHttpClient.Builder()
+            .addInterceptor(loggingInterceptor)
+            .connectTimeout(java.time.Duration.ofSeconds(10))
+            .readTimeout(java.time.Duration.ofSeconds(15))
+            .writeTimeout(java.time.Duration.ofSeconds(15))
+            .callTimeout(java.time.Duration.ofSeconds(30))
+            .build()

35-41: kotlinx.serialization Json 설정값 명시 추천.

서버 필드 증감에 강인하게 대응하려면 ignoreUnknownKeys 등을 켜두세요.

-    fun providesConverterFactory(): Converter.Factory = Json.asConverterFactory(
-        "application/json".toMediaType()
-    )
+    fun providesConverterFactory(): Converter.Factory {
+        val json = Json {
+            ignoreUnknownKeys = true
+            coerceInputValues = true
+            explicitNulls = false
+        }
+        return json.asConverterFactory("application/json".toMediaType())
+    }

49-53: baseUrl의 트레일링 슬래시 보장.

Retrofit baseUrl은 반드시 /로 끝나야 합니다. 제공자 값이 보장하지 않으면 여기서 보정하세요.

-            .baseUrl(buildConfigProvider.get().baseUrl)
+            .baseUrl(buildConfigProvider.get().baseUrl.let { if (it.endsWith("/")) it else "$it/" })
core/designsystem/src/main/java/com/umcspot/spot/designsystem/theme/Theme.kt (2)

52-57: darkTheme 파라미터가 미사용입니다.

테마 선택과 시스템 바 아이콘 색에 반영해 주세요. 야간 색상 팔레트가 없다면 TODO로 남기거나 임시 분기라도 두는 편이 좋습니다.


66-70: MaterialTheme와의 브릿지 고려.

앱 전반에서 MaterialTheme.colorScheme/typography를 참조할 가능성이 있으면 최소한의 bridge를 주입해 불일치를 줄이세요(예: colorScheme = lightColorScheme(...) 등). 현재는 content만 전달되고 있어 기본 스킴과 괴리가 생길 수 있습니다.

core/datastore/src/main/java/com/umcspot/spot/datastore/SpotSecureDataStoreSerializer.kt (2)

82-86: Json 인스턴스 설정 분리.

ignoreUnknownKeys 등을 활성화한 Json 인스턴스를 재사용하세요.

-import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.Json
@@
+    private val json = Json {
+        ignoreUnknownKeys = true
+        explicitNulls = false
+        coerceInputValues = true
+    }
@@
-            val serializedData = Json.encodeToString(
+            val serializedData = json.encodeToString(
                 serializer = SpotTokenData.serializer(),
                 value = t
             )
-            Json.decodeFromString(
+            json.decodeFromString(
                 deserializer = SpotTokenData.serializer(),
                 string = decryptedBytes.decodeToString()
             )

42-46: 키 생성 시 무작위화 요구 플래그를 명시하세요.

AES-GCM은 매번 새로운 IV가 필요합니다. KeySpec에 무작위화 요구를 명시해 안전장치를 추가하세요.

         val keyGenParameterSpec = KeyGenParameterSpec.Builder(
             KEY_ALIAS,
             KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
         )
             .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
             .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
             .setKeySize(256)
+            .setRandomizedEncryptionRequired(true)
             .build()
core/designsystem/src/main/java/com/umcspot/spot/designsystem/theme/TypoGraphy.kt (1)

119-207: 함수명과 타입명이 동일 — 혼동 가능.

SpotTypography() 함수가 SpotTypography 클래스와 동일명입니다. 호출부 가독성을 위해 spotTypography() 같은 네이밍으로 바꾸는 것을 권장합니다(선택).

build-logic/convention/build.gradle.kts (1)

10-10: build-logic에는 Compose compiler 의존성이 불필요합니다.

컨벤션 플러그인 컴파일에 compose compiler 아티팩트가 필요하지 않습니다. 제거해 빌드 시간과 결합도를 낮추세요.

-    compileOnly(libs.compose.compiler.extension)
build-logic/convention/src/main/java/com/umcspot/spot/convention/extension/DependencyHandlerScope.kt (1)

49-55: 라이브러리 노출용 api 헬퍼 추가 제안.

Android/Java 라이브러리에서 재노출이 필요한 경우가 많습니다. api(...) 헬퍼를 함께 제공하면 DSL 일관성이 좋아집니다.

 fun DependencyHandlerScope.testImplementation(provider: Provider<*>) {
     "testImplementation"(provider)
 }
 
 fun DependencyHandlerScope.compileOnly(provider: Provider<*>) {
     "compileOnly"(provider)
 }
+
+fun DependencyHandlerScope.api(provider: Provider<*>) {
+    "api"(provider)
+}
core/designsystem/src/main/java/com/umcspot/spot/designsystem/theme/Color.kt (2)

236-237: isLight의 setter를 private으로 제한 권장.

외부에서 임의 변경되면 테마 일관성이 깨질 수 있습니다. 필요 시 update로만 변경되도록 막는 편이 안전합니다.

-var isLight by mutableStateOf(isLight)
+var isLight by mutableStateOf(isLight)
+    private set

345-446: SpotDayColors 파라미터 네이밍을 lowerCamelCase로 통일 권장.

Kotlin 컨벤션(매개변수는 lowerCamelCase)에 맞추면 가독성과 자동완성 품질이 좋아집니다. 예) Primary50primary50. 공개 API면 바이너리 호환성 고려해 deprecate 경로도 검토하세요.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 204b9e6 and 63e4ee0.

⛔ Files ignored due to path filters (3)
  • core/designsystem/src/main/res/font/pretendard_medium.otf is excluded by !**/*.otf
  • core/designsystem/src/main/res/font/pretendard_regular.otf is excluded by !**/*.otf
  • core/designsystem/src/main/res/font/pretendard_semibold.otf is excluded by !**/*.otf
📒 Files selected for processing (107)
  • .gitignore (1 hunks)
  • .idea/vcs.xml (1 hunks)
  • app/build.gradle.kts (1 hunks)
  • app/src/main/AndroidManifest.xml (1 hunks)
  • app/src/main/java/com/umcspot/spot/MainActivity.kt (0 hunks)
  • app/src/main/java/com/umcspot/spot/SpotApplication.kt (1 hunks)
  • app/src/main/java/com/umcspot/spot/ui/theme/Color.kt (0 hunks)
  • app/src/main/java/com/umcspot/spot/ui/theme/Theme.kt (0 hunks)
  • app/src/main/java/com/umcspot/spot/ui/theme/Type.kt (0 hunks)
  • app/src/main/res/values/themes.xml (1 hunks)
  • build-logic/convention/.gitignore (1 hunks)
  • build-logic/convention/build.gradle.kts (1 hunks)
  • build-logic/convention/src/main/java/AndroidApplicationPlugin.kt (1 hunks)
  • build-logic/convention/src/main/java/AndroidComposeLibraryPlugin.kt (1 hunks)
  • build-logic/convention/src/main/java/AndroidLibraryPlugin.kt (1 hunks)
  • build-logic/convention/src/main/java/AndroidTestPlugin.kt (1 hunks)
  • build-logic/convention/src/main/java/BuildConfigPlugin.kt (1 hunks)
  • build-logic/convention/src/main/java/HiltPlugin.kt (1 hunks)
  • build-logic/convention/src/main/java/JavaLibraryPlugin.kt (1 hunks)
  • build-logic/convention/src/main/java/SpotDataPlugin.kt (1 hunks)
  • build-logic/convention/src/main/java/SpotFeaturePlugin.kt (1 hunks)
  • build-logic/convention/src/main/java/UnitTestPlugin.kt (1 hunks)
  • build-logic/convention/src/main/java/com/umcspot/spot/convention/AndroidCompose.kt (1 hunks)
  • build-logic/convention/src/main/java/com/umcspot/spot/convention/BuildConfig.kt (1 hunks)
  • build-logic/convention/src/main/java/com/umcspot/spot/convention/KotlinAndroid.kt (1 hunks)
  • build-logic/convention/src/main/java/com/umcspot/spot/convention/KotlinCoroutine.kt (1 hunks)
  • build-logic/convention/src/main/java/com/umcspot/spot/convention/extension/DependencyHandlerScope.kt (1 hunks)
  • build-logic/convention/src/main/java/com/umcspot/spot/convention/extension/ProjectExt.kt (1 hunks)
  • build-logic/convention/src/main/java/com/umcspot/spot/convention/extension/VersionCatalogExt.kt (1 hunks)
  • build-logic/settings.gradle.kts (1 hunks)
  • build.gradle.kts (1 hunks)
  • core/buildconfig/.gitignore (1 hunks)
  • core/buildconfig/build.gradle.kts (1 hunks)
  • core/buildconfig/proguard-rules.pro (1 hunks)
  • core/buildconfig/src/main/AndroidManifest.xml (1 hunks)
  • core/buildconfig/src/main/java/com/umcspot/spot/buildconfig/di/BuildConfigModule.kt (1 hunks)
  • core/buildconfig/src/main/java/com/umcspot/spot/buildconfig/impl/BuildConfigFieldsProviderImpl.kt (1 hunks)
  • core/common/.gitignore (1 hunks)
  • core/common/build.gradle.kts (1 hunks)
  • core/common/proguard-rules.pro (1 hunks)
  • core/common/src/main/AndroidManifest.xml (1 hunks)
  • core/common/src/main/java/com/umcspot/spot/common/BuildConfigFields.kt (1 hunks)
  • core/common/src/main/java/com/umcspot/spot/common/BuildConfigProvider.kt (1 hunks)
  • core/datastore/.gitignore (1 hunks)
  • core/datastore/build.gradle.kts (1 hunks)
  • core/datastore/proguard-rules.pro (1 hunks)
  • core/datastore/src/main/AndroidManifest.xml (1 hunks)
  • core/datastore/src/main/java/com/umcspot/spot/datastore/SpotSecureDataStoreSerializer.kt (1 hunks)
  • core/datastore/src/main/java/com/umcspot/spot/datastore/SpotTokenData.kt (1 hunks)
  • core/datastore/src/main/java/com/umcspot/spot/datastore/di/DataStoreModule.kt (1 hunks)
  • core/designsystem/.gitignore (1 hunks)
  • core/designsystem/build.gradle.kts (1 hunks)
  • core/designsystem/proguard-rules.pro (1 hunks)
  • core/designsystem/src/main/AndroidManifest.xml (1 hunks)
  • core/designsystem/src/main/java/com/umcspot/spot/designsystem/component/button/SpotButton.kt (1 hunks)
  • core/designsystem/src/main/java/com/umcspot/spot/designsystem/theme/Color.kt (1 hunks)
  • core/designsystem/src/main/java/com/umcspot/spot/designsystem/theme/Theme.kt (1 hunks)
  • core/designsystem/src/main/java/com/umcspot/spot/designsystem/theme/TypoGraphy.kt (1 hunks)
  • core/designsystem/src/main/res/drawable/ic_home.xml (1 hunks)
  • core/designsystem/src/main/res/drawable/ic_user.xml (1 hunks)
  • core/model/.gitignore (1 hunks)
  • core/model/build.gradle.kts (1 hunks)
  • core/model/src/main/java/com/umcspot/spot/model/CoreDummy.kt (1 hunks)
  • core/navigation/.gitignore (1 hunks)
  • core/navigation/build.gradle.kts (1 hunks)
  • core/navigation/proguard-rules.pro (1 hunks)
  • core/navigation/src/main/AndroidManifest.xml (1 hunks)
  • core/navigation/src/main/java/com/umcspot/spot/navigation/MainTabRoute.kt (1 hunks)
  • core/navigation/src/main/java/com/umcspot/spot/navigation/Route.kt (1 hunks)
  • core/network/.gitignore (1 hunks)
  • core/network/build.gradle.kts (1 hunks)
  • core/network/proguard-rules.pro (1 hunks)
  • core/network/src/main/AndroidManifest.xml (1 hunks)
  • core/network/src/main/java/com/umcspot/spot/network/di/NetworkModule.kt (1 hunks)
  • core/network/src/main/java/com/umcspot/spot/network/model/BaseResponse.kt (1 hunks)
  • core/network/src/main/java/com/umcspot/spot/network/service/TokenRefreshService.kt (1 hunks)
  • core/ui/.gitignore (1 hunks)
  • core/ui/build.gradle.kts (1 hunks)
  • core/ui/proguard-rules.pro (1 hunks)
  • core/ui/src/main/AndroidManifest.xml (1 hunks)
  • core/ui/src/main/java/com/umcspot/spot/ui/extension/DimensionExt.kt (1 hunks)
  • core/ui/src/main/java/com/umcspot/spot/ui/extension/ModifierExt.kt (1 hunks)
  • core/ui/src/main/java/com/umcspot/spot/ui/state/UiState.kt (1 hunks)
  • data/home/.gitignore (1 hunks)
  • data/home/build.gradle.kts (1 hunks)
  • data/home/proguard-rules.pro (1 hunks)
  • data/home/src/main/AndroidManifest.xml (1 hunks)
  • data/home/src/main/java/com/umcspot/spot/home/datasource/HomeDataSource.kt (1 hunks)
  • data/home/src/main/java/com/umcspot/spot/home/datasourceimpl/HomeDataSourceImpl.kt (1 hunks)
  • data/home/src/main/java/com/umcspot/spot/home/di/HomeDataModule.kt (1 hunks)
  • data/home/src/main/java/com/umcspot/spot/home/di/HomeRepositoryModule.kt (1 hunks)
  • data/home/src/main/java/com/umcspot/spot/home/di/HomeServiceModule.kt (1 hunks)
  • data/home/src/main/java/com/umcspot/spot/home/dto/request/HomeRequestDto.kt (1 hunks)
  • data/home/src/main/java/com/umcspot/spot/home/dto/response/HomeResponseDto.kt (1 hunks)
  • data/home/src/main/java/com/umcspot/spot/home/mapper/HomeMapper.kt (1 hunks)
  • data/home/src/main/java/com/umcspot/spot/home/repositoryimpl/HomeRepositoryImpl.kt (1 hunks)
  • data/home/src/main/java/com/umcspot/spot/home/service/HomeService.kt (1 hunks)
  • domain/home/.gitignore (1 hunks)
  • domain/home/build.gradle.kts (1 hunks)
  • domain/home/src/main/java/com/umcspot/spot/home/model/Dummy.kt (1 hunks)
  • domain/home/src/main/java/com/umcspot/spot/home/model/DummyResult.kt (1 hunks)
  • domain/home/src/main/java/com/umcspot/spot/home/repository/HomeRepository.kt (1 hunks)
  • feature/home/.gitignore (1 hunks)
  • feature/home/build.gradle.kts (1 hunks)
  • feature/home/proguard-rules.pro (1 hunks)
  • feature/home/src/main/AndroidManifest.xml (1 hunks)
  • feature/home/src/main/java/com/umcspot/spot/home/HomeScreen.kt (1 hunks)
⛔ Files not processed due to max files limit (22)
  • feature/home/src/main/java/com/umcspot/spot/home/HomeState.kt
  • feature/home/src/main/java/com/umcspot/spot/home/HomeViewModel.kt
  • feature/home/src/main/java/com/umcspot/spot/home/navigation/HomeNavigation.kt
  • feature/main/.gitignore
  • feature/main/build.gradle.kts
  • feature/main/proguard-rules.pro
  • feature/main/src/main/AndroidManifest.xml
  • feature/main/src/main/java/com/umcspot/spot/main/MainActivity.kt
  • feature/main/src/main/java/com/umcspot/spot/main/MainNavHost.kt
  • feature/main/src/main/java/com/umcspot/spot/main/MainNavTab.kt
  • feature/main/src/main/java/com/umcspot/spot/main/MainNavigator.kt
  • feature/main/src/main/java/com/umcspot/spot/main/MainScreen.kt
  • feature/main/src/main/java/com/umcspot/spot/main/component/MainBottomBar.kt
  • feature/main/src/main/res/values/strings.xml
  • feature/mypage/.gitignore
  • feature/mypage/build.gradle.kts
  • feature/mypage/proguard-rules.pro
  • feature/mypage/src/main/AndroidManifest.xml
  • feature/mypage/src/main/java/com/umcspot/spot/mypage/MypageScreen.kt
  • feature/mypage/src/main/java/com/umcspot/spot/mypage/navigation/MypageNavigation.kt
  • gradle/libs.versions.toml
  • settings.gradle.kts
💤 Files with no reviewable changes (4)
  • app/src/main/java/com/umcspot/spot/MainActivity.kt
  • app/src/main/java/com/umcspot/spot/ui/theme/Type.kt
  • app/src/main/java/com/umcspot/spot/ui/theme/Theme.kt
  • app/src/main/java/com/umcspot/spot/ui/theme/Color.kt
🧰 Additional context used
🧬 Code graph analysis (12)
build-logic/convention/src/main/java/AndroidComposeLibraryPlugin.kt (1)
build-logic/convention/src/main/java/com/umcspot/spot/convention/AndroidCompose.kt (1)
  • configureAndroidCompose (14-34)
build-logic/convention/src/main/java/HiltPlugin.kt (1)
build-logic/convention/src/main/java/com/umcspot/spot/convention/extension/DependencyHandlerScope.kt (2)
  • ksp (33-35)
  • kspTest (37-39)
build-logic/convention/src/main/java/UnitTestPlugin.kt (1)
build-logic/convention/src/main/java/com/umcspot/spot/convention/extension/DependencyHandlerScope.kt (1)
  • testImplementation (49-51)
build-logic/convention/build.gradle.kts (1)
build-logic/convention/src/main/java/com/umcspot/spot/convention/extension/DependencyHandlerScope.kt (1)
  • compileOnly (53-55)
core/designsystem/src/main/java/com/umcspot/spot/designsystem/component/button/SpotButton.kt (1)
core/ui/src/main/java/com/umcspot/spot/ui/extension/DimensionExt.kt (1)
  • screenHeightDp (11-16)
core/designsystem/src/main/java/com/umcspot/spot/designsystem/theme/Theme.kt (2)
core/designsystem/src/main/java/com/umcspot/spot/designsystem/theme/Color.kt (1)
  • SpotDayColors (345-446)
core/designsystem/src/main/java/com/umcspot/spot/designsystem/theme/TypoGraphy.kt (1)
  • SpotTypography (119-207)
build-logic/convention/src/main/java/AndroidApplicationPlugin.kt (2)
build-logic/convention/src/main/java/com/umcspot/spot/convention/KotlinAndroid.kt (1)
  • configureKotlinAndroid (12-50)
build-logic/convention/src/main/java/com/umcspot/spot/convention/AndroidCompose.kt (1)
  • configureAndroidCompose (14-34)
build-logic/convention/src/main/java/AndroidLibraryPlugin.kt (2)
build-logic/convention/src/main/java/com/umcspot/spot/convention/KotlinAndroid.kt (1)
  • configureKotlinAndroid (12-50)
build-logic/convention/src/main/java/com/umcspot/spot/convention/KotlinCoroutine.kt (1)
  • configureKotlinCoroutine (10-18)
build-logic/convention/src/main/java/BuildConfigPlugin.kt (1)
build-logic/convention/src/main/java/com/umcspot/spot/convention/BuildConfig.kt (1)
  • configureBuildConfig (7-30)
build-logic/convention/src/main/java/AndroidTestPlugin.kt (1)
build-logic/convention/src/main/java/com/umcspot/spot/convention/extension/DependencyHandlerScope.kt (2)
  • androidTestImplementation (45-47)
  • debugImplementation (25-27)
build-logic/convention/src/main/java/com/umcspot/spot/convention/AndroidCompose.kt (1)
build-logic/convention/src/main/java/com/umcspot/spot/convention/extension/DependencyHandlerScope.kt (1)
  • debugImplementation (25-27)
core/ui/build.gradle.kts (1)
build-logic/convention/src/main/java/com/umcspot/spot/convention/extension/DependencyHandlerScope.kt (1)
  • androidTestImplementation (45-47)

Comment on lines 1 to 5
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.spot.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.spot.android.hilt)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

🧩 Analysis chain

기본 설정이 컨벤션 플러그인에 위임됐는지 확인 필요.

defaultConfig(applicationId/minSdk/targetSdk 등)가 spot.android.application에서 설정되는지 확인해주세요. 미설정 시 빌드 실패합니다.

다음 스크립트로 컨벤션 플러그인에서의 설정을 탐색하세요.


🏁 Script executed:

#!/bin/bash
rg -n -C3 -g 'build-logic/**' -P '(class\s+AndroidApplicationPlugin|pluginManager\.apply\("com\.android\.application"\))|defaultConfig\s*\{|applicationId\s*='

Length of output: 2991


컨벤션 플러그인이 minSdk/compileSdk/BuildConfig 등은 설정하지만 applicationId는 설정하지 않습니다 — app 모듈에 applicationId 필요

  • 확인: build-logic/convention/src/main/java/com/umcspot/spot/convention/KotlinAndroid.kt 에서 compileSdk/minSdk 및 defaultConfig 설정 확인.
  • 확인: build-logic/convention/src/main/java/com/umcspot/spot/convention/BuildConfig.kt 에서 buildConfigField 설정 확인.
  • 확인: build-logic/convention/src/main/java/com/umcspot/spot/convention/AndroidTestPlugin.kt 에서 testInstrumentationRunner 설정 확인.
  • 미발견: build-logic/** 내에서 applicationId 설정 없음 — app 모듈에 applicationId를 명시하거나 컨벤션 플러그인에 applicationId 설정을 추가해야 함(미설정 시 빌드 실패).
🤖 Prompt for AI Agents
In app/build.gradle.kts around lines 1-5: the convention plugins set
compileSdk/minSdk/BuildConfig/test runner but do not provide applicationId,
which must be declared for the app module; add an applicationId entry to the app
module's defaultConfig in this file (e.g., defaultConfig { applicationId
"com.yourcompany.yourapp" }) or alternatively add applicationId configuration to
the convention plugin (build-logic/*) so the app module receives it; ensure the
chosen package string matches your AndroidManifest and flavors and update any
CI/build scripts if they expect a specific applicationId.

Comment on lines +10 to +15
signingConfigs {
getByName("debug") {
keyAlias = "androiddebugkey"
keyPassword = "android"
storeFile = file("debug.keystore")
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

디버그 키스토어를 스크립트에 하드코딩하지 마세요.

AGP 기본 디버그 키스토어를 사용하면 별도 설정이 불필요합니다. 현재처럼 파일/패스워드를 레포에 남기면 관리 오버헤드와 실수 위험이 있습니다.

권장 수정:

-    signingConfigs {
-        getByName("debug") {
-            keyAlias = "androiddebugkey"
-            keyPassword = "android"
-            storeFile = file("debug.keystore")
-        }
-    }
+    // 디버그 서명은 AGP 기본값 사용 (커스텀 불필요)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
signingConfigs {
getByName("debug") {
keyAlias = "androiddebugkey"
keyPassword = "android"
storeFile = file("debug.keystore")
}
// 디버그 서명은 AGP 기본값 사용 (커스텀 불필요)
🤖 Prompt for AI Agents
In app/build.gradle.kts around lines 10 to 15, the debug keystore data
(keyAlias, keyPassword, storeFile) is hardcoded in signingConfigs; remove this
hardcoded debug keystore block and rely on the Android Gradle Plugin's default
debug keystore instead, or if a custom debug keystore is absolutely required,
load its path/password from secure external configuration (environment variables
or gradle.properties with .gitignore) rather than embedding them in the script.

Comment on lines +19 to 24
debug {
signingConfig = signingConfigs.getByName("debug")
}
release {
signingConfig = signingConfigs.getByName("debug")
isMinifyEnabled = false
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

릴리스 빌드가 디버그 키로 서명되고 있습니다. 반드시 차단.

releasesigningConfig = signingConfigs.getByName("debug")는 보안/배포상 금지입니다. 실제 릴리스 서명은 별도 keystore.properties 등 외부 비밀로 주입하세요.

수정안:

-        debug {
-            signingConfig = signingConfigs.getByName("debug")
-        }
+        debug { /* 기본 디버그 서명 사용 */ }

         release {
-            signingConfig = signingConfigs.getByName("debug")
+            // TODO: keystoreProperties로 릴리스 서명 구성 (레포에 비밀값 저장 금지)
             isMinifyEnabled = false
             proguardFiles(
                 getDefaultProguardFile("proguard-android-optimize.txt"),
                 "proguard-rules.pro"
             )
         }
🤖 Prompt for AI Agents
In app/build.gradle.kts around lines 19–24, the release build is incorrectly
using the debug signing config; replace the debug signing for release with a
proper release signing setup that reads keystore credentials from an external
secret (e.g. keystore.properties or CI secrets) and registers a release
signingConfig, then reference that release signingConfig here (do not use
signingConfigs.getByName("debug") for release). Ensure the keystore file path,
alias, storePassword and keyPassword are injected from the external file/CI and
not hard-coded in the repo.

Comment on lines 12 to 14
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

백업/데이터 추출 정책에 토큰 DataStore 파일 제외 규칙 반영 필요.

앱 백업이 활성화(allowBackup="true")이고 rules가 지정되어 있습니다. 토큰을 저장하는 DataStore 파일(com.umcspot.spot.datastore)이 백업/전송에 포함되지 않도록 backup_rules.xmldata_extraction_rules.xml에 명시적으로 제외 규칙을 넣어주세요.

android:supportsRtl="true"
android:theme="@style/Theme.SPOT"
android:theme="@style/Theme.Spot"
android:usesCleartextTraffic="true"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

릴리즈에서 cleartext 금지 또는 빌드타입별로 제어하세요.

android:usesCleartextTraffic="true"는 보안/스토어 심사 리스크입니다. 디버그만 허용하고 릴리즈는 차단하도록 전환을 권장합니다.

다음처럼 매니페스트 플레이스홀더로 전환하세요:

-        android:usesCleartextTraffic="true"
+        android:usesCleartextTraffic="${cleartextTrafficPermitted}"

추가로 app/build.gradle.kts에 빌드타입별 플레이스홀더를 설정하세요:

android {
  buildTypes {
    debug { manifestPlaceholders["cleartextTrafficPermitted"] = true }
    release { manifestPlaceholders["cleartextTrafficPermitted"] = false }
  }
}

또는 networkSecurityConfig로 디버그만 cleartext 허용을 분리해도 됩니다.

🤖 Prompt for AI Agents
In app/src/main/AndroidManifest.xml around line 20,
android:usesCleartextTraffic="true" is applied globally which is a
security/store risk; replace the literal with a manifest placeholder (e.g.
android:usesCleartextTraffic="${cleartextTrafficPermitted}") and then set
build-type-specific manifestPlaceholders in app/build.gradle.kts (debug true,
release false). Alternatively, remove the global attribute and configure a
networkSecurityConfig that permits cleartext only for debug builds and reference
that config via a placeholder tied to buildTypes.

Comment on lines +23 to +26
fun providesLoggingInterceptor() =
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

로그 레벨을 환경별로 분기하세요.

현재 BODY로 고정되어 있어 릴리즈에서 민감 정보가 노출될 수 있습니다. isDebug를 주입해 분기하세요.

-    fun providesLoggingInterceptor() =
-        HttpLoggingInterceptor().apply {
-            level = HttpLoggingInterceptor.Level.BODY
-        }
+    fun providesLoggingInterceptor(buildConfigProvider: BuildConfigFieldProvider) =
+        HttpLoggingInterceptor().apply {
+            level = if (buildConfigProvider.get().isDebug)
+                HttpLoggingInterceptor.Level.BODY
+            else
+                HttpLoggingInterceptor.Level.NONE
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fun providesLoggingInterceptor() =
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
fun providesLoggingInterceptor(buildConfigProvider: BuildConfigFieldProvider) =
HttpLoggingInterceptor().apply {
level = if (buildConfigProvider.get().isDebug)
HttpLoggingInterceptor.Level.BODY
else
HttpLoggingInterceptor.Level.NONE
}
🤖 Prompt for AI Agents
In core/network/src/main/java/com/umcspot/spot/network/di/NetworkModule.kt
around lines 23 to 26, the HttpLoggingInterceptor level is hardcoded to BODY;
change the provider to accept an injected Boolean (e.g., isDebug) and set level
to HttpLoggingInterceptor.Level.BODY when isDebug is true and
HttpLoggingInterceptor.Level.NONE (or a less verbose level) when false so
sensitive data isn’t logged in release builds; update the DI binding to provide
the isDebug value and adjust the function signature accordingly.

@@ -0,0 +1,4 @@
package network.service
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

패키지명 불일치 수정이 필요합니다.

파일 경로는 com.umcspot.spot.network.service이지만 패키지 선언은 network.service로 되어 있습니다.

다음과 같이 수정하세요:

-package network.service
+package com.umcspot.spot.network.service
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
package network.service
package com.umcspot.spot.network.service
🤖 Prompt for AI Agents
In
core/network/src/main/java/com/umcspot/spot/network/service/TokenRefreshService.kt
around line 1, the package declaration is incorrect (currently
"network.service"); change it to the correct package
"com.umcspot.spot.network.service" by updating the top-of-file package statement
to match the file path so Kotlin package and directory structure are consistent.

Comment on lines +3 to +9
import com.umcspot.spot.home.dto.request.HomeRequestDto
import com.umcspot.spot.home.dto.response.HomeResponseDto
import network.model.BaseResponse

interface HomeDataSource {
suspend fun getDummies(request: HomeRequestDto): BaseResponse<HomeResponseDto>
} No newline at end of file
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

컴파일 오류: BaseResponse import 경로 수정 필요

패키지 접두사가 누락된 것으로 보입니다. core/network의 패키지 규칙을 따르면 아래처럼 수정되어야 합니다.

-import network.model.BaseResponse
+import com.umcspot.spot.network.model.BaseResponse
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import com.umcspot.spot.home.dto.request.HomeRequestDto
import com.umcspot.spot.home.dto.response.HomeResponseDto
import network.model.BaseResponse
interface HomeDataSource {
suspend fun getDummies(request: HomeRequestDto): BaseResponse<HomeResponseDto>
}
import com.umcspot.spot.home.dto.request.HomeRequestDto
import com.umcspot.spot.home.dto.response.HomeResponseDto
import com.umcspot.spot.network.model.BaseResponse
interface HomeDataSource {
suspend fun getDummies(request: HomeRequestDto): BaseResponse<HomeResponseDto>
}
🤖 Prompt for AI Agents
In data/home/src/main/java/com/umcspot/spot/home/datasource/HomeDataSource.kt
around lines 3-9, the import for BaseResponse is missing the core/network
package prefix; replace the current import (network.model.BaseResponse) with the
correct package import (com.umcspot.core.network.model.BaseResponse) so the
compiler can resolve BaseResponse, then recompile to verify the error is gone.

Comment on lines +6 to +15
import network.model.BaseResponse
import retrofit2.http.Body
import retrofit2.http.POST


interface HomeService {
@POST("/api/v1/service")
suspend fun getDummies(
@Body request: HomeRequestDto
): BaseResponse<HomeResponseDto>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

🧩 Analysis chain

컴파일 오류: BaseResponse import 경로 및 엔드포인트 표기 개선

  • 잘못된 import로 컴파일 실패합니다.
  • @POST 경로는 선행 /를 빼는 것이 일반적이며, 베이스 URL path segment 무시 이슈를 예방합니다.
-import network.model.BaseResponse
+import com.umcspot.spot.network.model.BaseResponse
@@
-    @POST("/api/v1/service")
+    @POST("api/v1/service")
     suspend fun getDummies(
         @Body request: HomeRequestDto
     ): BaseResponse<HomeResponseDto>

레포 전반의 잘못된 import를 일괄 확인:


🏁 Script executed:

#!/bin/bash
rg -n 'import\s+network\.model\.BaseResponse' -S

Length of output: 334


컴파일 오류: BaseResponse import 경로 및 @post 경로 즉시 수정 필요

다음 파일들에서 잘못된 import로 컴파일 실패합니다. import 경로를 com.umcspot.spot.network.model.BaseResponse로 변경하고, HomeService.kt의 @post에서 선행 '/'를 제거하세요.

  • data/home/src/main/java/com/umcspot/spot/home/datasource/HomeDataSource.kt:5
  • data/home/src/main/java/com/umcspot/spot/home/service/HomeService.kt:6 (추가로 @post 수정 필요)
  • data/home/src/main/java/com/umcspot/spot/home/datasourceimpl/HomeDataSourceImpl.kt:7
-import network.model.BaseResponse
+import com.umcspot.spot.network.model.BaseResponse
@@
-    @POST("/api/v1/service")
+    @POST("api/v1/service")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import network.model.BaseResponse
import retrofit2.http.Body
import retrofit2.http.POST
interface HomeService {
@POST("/api/v1/service")
suspend fun getDummies(
@Body request: HomeRequestDto
): BaseResponse<HomeResponseDto>
import com.umcspot.spot.network.model.BaseResponse
import retrofit2.http.Body
import retrofit2.http.POST
interface HomeService {
@POST("api/v1/service")
suspend fun getDummies(
@Body request: HomeRequestDto
): BaseResponse<HomeResponseDto>
🤖 Prompt for AI Agents
In data/home/src/main/java/com/umcspot/spot/home/service/HomeService.kt around
lines 6 to 15 (and also update the same import in
data/home/src/main/java/com/umcspot/spot/home/datasource/HomeDataSource.kt line
5 and
data/home/src/main/java/com/umcspot/spot/home/datasourceimpl/HomeDataSourceImpl.kt
line 7), the BaseResponse import is incorrect and the @POST path contains a
leading '/'; change the import to com.umcspot.spot.network.model.BaseResponse in
each file and remove the leading slash from the @POST annotation value in
HomeService.kt so it reads a relative path (e.g., "api/v1/service").

Comment on lines +5 to +7
implementation(projects.core.model)
implementation(libs.bundles.coroutine)
} No newline at end of file
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

🧩 Analysis chain

Coroutines 번들에 android 아티팩트가 포함되어 있지 않은지 확인 필요

domainkotlinx-coroutines-android에 의존하지 않는 것이 바람직합니다. 번들이 안드로이드 아티팩트를 포함한다면 제외하거나 core만 직접 의존하도록 바꿔주세요.

두 가지 대안 예시:

  • 번들에서 안드로이드 모듈만 제외
 dependencies {
-    implementation(libs.bundles.coroutine)
+    implementation(libs.bundles.coroutine) {
+        exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-android")
+    }
 }
  • 또는 core만 직접 의존(카탈로그 키에 맞춰 조정)
-dependencies {
-    implementation(libs.bundles.coroutine)
-}
+dependencies {
+    implementation(libs.kotlinx.coroutines.core)
+}

번들 구성 확인:


🏁 Script executed:

#!/bin/bash
# libs.versions.toml 에 coroutines 번들 구성 확인
rg -n -C2 'coroutine|coroutines-android' **/libs.versions.toml

Length of output: 1539


coroutine 번들에 android 아티팩트 포함 — domain 모듈에서 android 의존 제거 필요

확인: libs.versions.toml의 coroutine 번들이 kotlinx-coroutines-androidkotlinx-coroutines-core를 포함합니다 (coroutine = ["kotlinx-coroutines-android", "kotlinx-coroutines-core"]). 따라서 domain/home/build.gradle.kts(5-7)의 implementation(libs.bundles.coroutine)는 android 아티팩트를 transitively 포함합니다.

조치(둘 중 하나 선택):

  • 번들에서 android 모듈만 제외
 dependencies {
-    implementation(libs.bundles.coroutine)
+    implementation(libs.bundles.coroutine) {
+        exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-android")
+    }
 }
  • 또는 core만 직접 의존
-dependencies {
-    implementation(libs.bundles.coroutine)
-}
+dependencies {
+    implementation(libs.kotlinx.coroutines.core)
+}

수정 위치: domain/home/build.gradle.kts (lines 5-7).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
implementation(projects.core.model)
implementation(libs.bundles.coroutine)
}
implementation(projects.core.model)
implementation(libs.bundles.coroutine) {
exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-android")
}
}
Suggested change
implementation(projects.core.model)
implementation(libs.bundles.coroutine)
}
implementation(projects.core.model)
implementation(libs.kotlinx.coroutines.core)
}
🤖 Prompt for AI Agents
In domain/home/build.gradle.kts around lines 5 to 7, the
implementation(libs.bundles.coroutine) brings in kotlinx-coroutines-android
transitively which is an Android-only artifact and should not be in the domain
module; either replace the bundle reference with a direct dependency on
kotlinx-coroutines-core (implementation(libs.kotlinx.coroutines.core)) or keep
the bundle but explicitly exclude the android artifact from the dependency
(exclude group/module for kotlinx-coroutines-android) so the domain module only
depends on core.

@fredleeJH fredleeJH merged commit c399ce5 into develop Sep 29, 2025
1 check passed
starshape7 added a commit that referenced this pull request Jan 10, 2026
starshape7 added a commit that referenced this pull request Jan 14, 2026
feat : 지명 검색결과 없는 경우 추가
@coderabbitai coderabbitai bot mentioned this pull request Feb 16, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚙️ [SETTING] 프로젝트 기초 세팅 🐶 종훈

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant