-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Google Analytics 화면별, 이벤트별 태그 적용 #157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2dcf3c1
87e3261
8e0f3fd
f46dee2
9c624d9
2e0bd37
992ff4f
12a3361
b9b77b6
2c27921
c91acf6
3105272
3ae7508
cb634d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package com.ninecraft.booket.core.common.analytics | ||
|
|
||
| import com.google.firebase.analytics.FirebaseAnalytics | ||
| import com.google.firebase.analytics.logEvent | ||
| import com.orhanobut.logger.Logger | ||
| import javax.inject.Inject | ||
| import javax.inject.Singleton | ||
|
|
||
| @Singleton | ||
| class AnalyticsHelper @Inject constructor( | ||
| private val firebaseAnalytics: FirebaseAnalytics, | ||
| ) { | ||
|
|
||
| fun logScreenView(screenName: String) { | ||
| Logger.d("Analytics - Screen View: $screenName") | ||
| firebaseAnalytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW) { | ||
| param(FirebaseAnalytics.Param.SCREEN_NAME, screenName) | ||
| } | ||
| } | ||
|
|
||
| fun logEvent(eventName: String) { | ||
| Logger.d("Analytics - Event: $eventName") | ||
| firebaseAnalytics.logEvent(eventName) {} | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package com.ninecraft.booket.core.common.analytics.di | ||
|
|
||
| import com.google.firebase.Firebase | ||
| import com.google.firebase.analytics.FirebaseAnalytics | ||
| import com.google.firebase.analytics.analytics | ||
| import dagger.Module | ||
| import dagger.Provides | ||
| import dagger.hilt.InstallIn | ||
| import dagger.hilt.components.SingletonComponent | ||
| import javax.inject.Singleton | ||
|
|
||
| @Module | ||
| @InstallIn(SingletonComponent::class) | ||
| object AnalyticsModule { | ||
|
|
||
| @Provides | ||
| @Singleton | ||
| fun provideFirebaseAnalytics(): FirebaseAnalytics { | ||
| return Firebase.analytics | ||
| } | ||
| } | ||
|
Comment on lines
+16
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainFirebase.analytics 확장 프로퍼티 사용 시 KTX 의존성 확인 필요
옵션 A) KTX 유지
검증 스크립트: 옵션 B) KTX 미사용 (대안 제공자)
import android.content.Context
import com.google.firebase.Firebase
import com.google.firebase.analytics.FirebaseAnalytics
// import com.google.firebase.analytics.analytics // 제거
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object AnalyticsModule {
@Provides
@Singleton
fun provideFirebaseAnalytics(@ApplicationContext context: Context): FirebaseAnalytics =
FirebaseAnalytics.getInstance(context)
}팀 규칙(ktx 사용 여부)에 맞게 한 가지로 통일해 두면 혼선을 줄일 수 있습니다. 🏁 Script executed: #!/bin/bash
rg -nP --glob '**/build.gradle.kts' 'firebase-analytics-ktx|libs\.firebase\.analyticsKtx'Length of output: 91 스크립트가 🏁 Script executed: #!/bin/bash
# 1. 모든 Gradle 빌드 스크립트(.gradle, .gradle.kts)에서 firebase-analytics(-ktx) 의존성 검색
rg -nP --glob '**/build.gradle*' 'firebase-analytics(-ktx)?'
# 2. 버전 카탈로그(gradle/libs.versions.toml 등)에서 analytics 관련 항목 검색
rg -nP --glob '**/libs.versions.toml' 'analytics'Length of output: 226 Firebase.analytics KTX 의존성 누락 확인 및 조치 필요 다음 사항을 확인했습니다.
따라서 아래 두 가지 옵션 중 하나를 반드시 선택하여 반영해 주세요. 옵션 A) KTX 유지Gradle 의존성에 KTX 모듈을 추가 // build.gradle.kts
dependencies {
implementation("com.google.firebase:firebase-analytics-ktx")
}또는 버전 카탈로그에 alias 등록 # gradle/libs.versions.toml
firebase-analytics-ktx = { group = "com.google.firebase", name = "firebase-analytics-ktx", version.ref = "firebase" }옵션 B) KTX 미사용 (대안 제공자)확장 프로퍼티 대신 애플리케이션 컨텍스트 기반으로 인스턴스 획득 import com.google.firebase.Firebase
import com.google.firebase.analytics.FirebaseAnalytics
// import com.google.firebase.analytics.analytics // 제거
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
import android.content.Context
@Module
@InstallIn(SingletonComponent::class)
object AnalyticsModule {
@Provides
@Singleton
fun provideFirebaseAnalytics(@ApplicationContext context: Context): FirebaseAnalytics =
FirebaseAnalytics.getInstance(context)
}위 두 옵션 중 팀 정책에 맞는 방식을 선택하여 일관성 있게 적용해 주세요. 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ dependencies { | |
| projects.core.common, | ||
|
|
||
| libs.compose.keyboard.state, | ||
| libs.compose.effects, | ||
| libs.logger, | ||
| ) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,7 +23,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape | |
| import androidx.compose.material3.Surface | ||
| import androidx.compose.material3.Text | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.LaunchedEffect | ||
| import androidx.compose.runtime.derivedStateOf | ||
| import androidx.compose.runtime.getValue | ||
| import androidx.compose.runtime.mutableIntStateOf | ||
|
|
@@ -35,6 +34,7 @@ import androidx.compose.ui.Modifier | |
| import androidx.compose.ui.tooling.preview.Preview | ||
| import androidx.compose.ui.unit.dp | ||
| import com.ninecraft.booket.core.designsystem.theme.ReedTheme | ||
| import com.skydoves.compose.effects.RememberedEffect | ||
|
|
||
| // 기기에서 평균적으로 한 화면에 보이는 아이템 개수 | ||
| private const val LIMIT_COUNT = 6 | ||
|
|
@@ -82,7 +82,7 @@ private fun LazyListState.onLoadMore( | |
| } | ||
| } | ||
|
|
||
| LaunchedEffect(reached) { | ||
| RememberedEffect(reached) { | ||
| if (reached && layoutInfo.totalItemsCount > limitCount) action() | ||
| } | ||
|
Comment on lines
+85
to
87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 무한 스크롤 트리거가 한 번만 실행되는 회귀 가능성: RememberedEffect(Boolean) 키 사용
아래처럼 교체하면 - RememberedEffect(reached) {
- if (reached && layoutInfo.totalItemsCount > limitCount) action()
- }
+ LaunchedEffect(reached) {
+ if (reached && layoutInfo.totalItemsCount > limitCount) {
+ action()
+ }
+ }추가로, 더 견고하게 하려면 // 추가 import: import kotlinx.coroutines.flow.*
LaunchedEffect(limitCount, loadOnBottom) {
snapshotFlow { reachedBottom(limitCount, loadOnBottom) to layoutInfo.totalItemsCount }
.distinctUntilChanged() // (reached, count) 변화만 반응
.filter { (reached, count) -> reached && count > limitCount }
.collect { action() }
}필요 시 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ import androidx.compose.runtime.mutableIntStateOf | |
| import androidx.compose.runtime.mutableStateOf | ||
| import androidx.compose.runtime.rememberCoroutineScope | ||
| import androidx.compose.runtime.setValue | ||
| import com.ninecraft.booket.core.common.analytics.AnalyticsHelper | ||
| import com.ninecraft.booket.core.common.constants.BookStatus | ||
| import com.ninecraft.booket.core.common.utils.handleException | ||
| import com.ninecraft.booket.core.data.api.repository.BookRepository | ||
|
|
@@ -28,6 +29,7 @@ import com.slack.circuit.codegen.annotations.CircuitInject | |
| import com.slack.circuit.retained.rememberRetained | ||
| import com.slack.circuit.runtime.Navigator | ||
| import com.slack.circuit.runtime.presenter.Presenter | ||
| import com.slack.circuitx.effects.ImpressionEffect | ||
| import dagger.assisted.Assisted | ||
| import dagger.assisted.AssistedFactory | ||
| import dagger.assisted.AssistedInject | ||
|
|
@@ -46,10 +48,13 @@ class BookDetailPresenter @AssistedInject constructor( | |
| @Assisted private val navigator: Navigator, | ||
| private val bookRepository: BookRepository, | ||
| private val recordRepository: RecordRepository, | ||
| private val analyticsHelper: AnalyticsHelper, | ||
| ) : Presenter<BookDetailUiState> { | ||
| companion object { | ||
| private const val PAGE_SIZE = 20 | ||
| private const val START_INDEX = 0 | ||
| private const val BOOK_DELETE = "library_book_delete" | ||
| private const val BOOK_DELETE_COMPLETE = "library_book_delete_complete" | ||
| } | ||
|
|
||
| private fun getRecordComparator(sortType: RecordSort): Comparator<ReadingRecordModel> { | ||
|
|
@@ -213,6 +218,7 @@ class BookDetailPresenter @AssistedInject constructor( | |
| scope.launch { | ||
| bookRepository.deleteBook(userBookId = userBookId) | ||
| .onSuccess { | ||
| analyticsHelper.logEvent(BOOK_DELETE_COMPLETE) | ||
| onSuccess() | ||
| } | ||
| .onFailure { exception -> | ||
|
|
@@ -328,6 +334,7 @@ class BookDetailPresenter @AssistedInject constructor( | |
| is BookDetailUiEvent.OnDeleteRecordClick -> { | ||
| isRecordMenuBottomSheetVisible = false | ||
| isRecordDeleteDialogVisible = true | ||
| analyticsHelper.logEvent(BOOK_DELETE) | ||
| } | ||
|
|
||
| is BookDetailUiEvent.OnDeleteRecord -> { | ||
|
|
@@ -387,6 +394,10 @@ class BookDetailPresenter @AssistedInject constructor( | |
| } | ||
| } | ||
|
|
||
| ImpressionEffect { | ||
| analyticsHelper.logScreenView(screen.name) | ||
| } | ||
|
Comment on lines
+397
to
+399
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 스크린 뷰 로깅 표준화 권장 여기도 Helper를 🤖 Prompt for AI Agents |
||
|
|
||
| return BookDetailUiState( | ||
| uiState = uiState, | ||
| footerState = footerState, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,11 @@ | ||
| package com.ninecraft.booket.feature.detail.record | ||
|
|
||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.LaunchedEffect | ||
| import androidx.compose.runtime.getValue | ||
| import androidx.compose.runtime.mutableStateOf | ||
| import androidx.compose.runtime.rememberCoroutineScope | ||
| import androidx.compose.runtime.setValue | ||
| import com.ninecraft.booket.core.common.analytics.AnalyticsHelper | ||
| import com.ninecraft.booket.core.common.utils.handleException | ||
| import com.ninecraft.booket.core.data.api.repository.RecordRepository | ||
| import com.ninecraft.booket.core.model.RecordDetailModel | ||
|
|
@@ -16,10 +16,12 @@ import com.ninecraft.booket.feature.screens.RecordEditScreen | |
| import com.ninecraft.booket.feature.screens.arguments.RecordEditArgs | ||
| import com.ninecraft.booket.feature.screens.extensions.delayedGoTo | ||
| import com.orhanobut.logger.Logger | ||
| import com.skydoves.compose.effects.RememberedEffect | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainRememberedEffect 의존성 확인 필요
아래 스크립트로 Gradle 설정에 의존성이 존재하는지 확인하세요: Also applies to: 160-160 🏁 Script executed: #!/bin/bash
set -euo pipefail
# 프로젝트 내 Gradle/TOML에서 compose-effects 또는 skydoves 의존성 검색
rg -n -C2 -S 'compose-effects|skydoves' -g '*.{gradle,gradle.kts,toml}'Length of output: 2034 feature/detail 모듈의 Gradle 설정에서 아래 스크립트를 실행하고 결과를 공유해주세요: 🏁 Script executed: #!/bin/bash
set -euo pipefail
# feature/detail 모듈의 build.gradle(.kts)에서 compose-effects 의존성 사용 확인
rg -n 'compose-effects' -g 'feature/detail/**/build.gradle*'Length of output: 80
🏁 Script executed: #!/bin/bash
set -euo pipefail
# feature/detail 모듈의 build.gradle(.kts)에서 version catalog alias로 compose-effects 사용 확인
rg -n 'libs\.compose-effects' -g 'feature/detail/**/build.gradle*'Length of output: 88 feature/detail 모듈에 compose-effects 의존성 추가 필요
import com.skydoves.compose.effects.RememberedEffect를 사용 중이나, 해결 방법:
🤖 Prompt for AI Agents |
||
| import com.slack.circuit.codegen.annotations.CircuitInject | ||
| import com.slack.circuit.retained.rememberRetained | ||
| import com.slack.circuit.runtime.Navigator | ||
| import com.slack.circuit.runtime.presenter.Presenter | ||
| import com.slack.circuitx.effects.ImpressionEffect | ||
| import dagger.assisted.Assisted | ||
| import dagger.assisted.AssistedFactory | ||
| import dagger.assisted.AssistedInject | ||
|
|
@@ -30,8 +32,14 @@ class RecordDetailPresenter @AssistedInject constructor( | |
| @Assisted private val screen: RecordDetailScreen, | ||
| @Assisted private val navigator: Navigator, | ||
| private val repository: RecordRepository, | ||
| private val analyticsHelper: AnalyticsHelper, | ||
| ) : Presenter<RecordDetailUiState> { | ||
|
|
||
| companion object { | ||
| private const val RECORD_DELETE = "record_delete" | ||
| private const val RECORD_DELETE_COMPLETE = "record_delete_complete" | ||
| } | ||
|
|
||
| @Composable | ||
| override fun present(): RecordDetailUiState { | ||
| val scope = rememberCoroutineScope() | ||
|
|
@@ -72,6 +80,7 @@ class RecordDetailPresenter @AssistedInject constructor( | |
| scope.launch { | ||
| repository.deleteRecord(readingRecordId = readingRecordId) | ||
| .onSuccess { | ||
| analyticsHelper.logEvent(RECORD_DELETE_COMPLETE) | ||
| onSuccess() | ||
| } | ||
| .onFailure { exception -> | ||
|
|
@@ -146,6 +155,7 @@ class RecordDetailPresenter @AssistedInject constructor( | |
| } | ||
|
|
||
| is RecordDetailUiEvent.OnDeleteRecordClick -> { | ||
| analyticsHelper.logEvent(RECORD_DELETE) | ||
| isRecordMenuBottomSheetVisible = false | ||
| isRecordDeleteDialogVisible = true | ||
| } | ||
|
|
@@ -162,10 +172,14 @@ class RecordDetailPresenter @AssistedInject constructor( | |
| } | ||
| } | ||
|
|
||
| LaunchedEffect(Unit) { | ||
| RememberedEffect(Unit) { | ||
| getRecordDetail(screen.recordId) | ||
| } | ||
|
|
||
| ImpressionEffect { | ||
| analyticsHelper.logScreenView(screen.name) | ||
| } | ||
|
|
||
| return RecordDetailUiState( | ||
| uiState = uiState, | ||
| recordDetailInfo = recordDetailInfo, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ import androidx.compose.runtime.mutableStateOf | |
| import androidx.compose.runtime.remember | ||
| import androidx.compose.runtime.rememberCoroutineScope | ||
| import androidx.compose.runtime.setValue | ||
| import com.ninecraft.booket.core.common.analytics.AnalyticsHelper | ||
| import com.ninecraft.booket.core.common.utils.handleException | ||
| import com.ninecraft.booket.core.data.api.repository.RecordRepository | ||
| import com.ninecraft.booket.feature.screens.EmotionEditScreen | ||
|
|
@@ -20,6 +21,7 @@ import com.slack.circuit.foundation.rememberAnsweringNavigator | |
| import com.slack.circuit.retained.rememberRetained | ||
| import com.slack.circuit.runtime.Navigator | ||
| import com.slack.circuit.runtime.presenter.Presenter | ||
| import com.slack.circuitx.effects.ImpressionEffect | ||
| import dagger.assisted.Assisted | ||
| import dagger.assisted.AssistedFactory | ||
| import dagger.assisted.AssistedInject | ||
|
|
@@ -30,8 +32,15 @@ class RecordEditPresenter @AssistedInject constructor( | |
| @Assisted private val screen: RecordEditScreen, | ||
| @Assisted private val navigator: Navigator, | ||
| private val repository: RecordRepository, | ||
| private val analyticsHelper: AnalyticsHelper, | ||
| ) : Presenter<RecordEditUiState> { | ||
|
|
||
| companion object { | ||
| private const val MAX_PAGE = 4032 | ||
| private const val RECORD_EDIT = "record_edit_save" | ||
| private const val RECORD_EDIT_SAVE = "record_edit_save" | ||
| } | ||
|
Comment on lines
+38
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 스크린 뷰 이벤트 키가 잘못됨(복사-붙여넣기 오류로 추정) + 스크린 이름 직접 사용 권장
적용 Diff: companion object {
private const val MAX_PAGE = 4032
- private const val RECORD_EDIT = "record_edit_save"
private const val RECORD_EDIT_SAVE = "record_edit_save"
}
@@
- ImpressionEffect {
- analyticsHelper.logScreenView(RECORD_EDIT)
- }
+ ImpressionEffect {
+ analyticsHelper.logScreenView(RecordEditScreen.name)
+ }Also applies to: 146-149 🤖 Prompt for AI Agents |
||
|
|
||
| @Composable | ||
| override fun present(): RecordEditUiState { | ||
| val scope = rememberCoroutineScope() | ||
|
|
@@ -85,6 +94,7 @@ class RecordEditPresenter @AssistedInject constructor( | |
| emotionTags = emotionTags, | ||
| review = impression, | ||
| ).onSuccess { | ||
| analyticsHelper.logEvent(RECORD_EDIT_SAVE) | ||
| onSuccess() | ||
| }.onFailure { exception -> | ||
| val handleErrorMessage = { message: String -> | ||
|
|
@@ -133,6 +143,10 @@ class RecordEditPresenter @AssistedInject constructor( | |
| } | ||
| } | ||
|
|
||
| ImpressionEffect { | ||
| analyticsHelper.logScreenView(RECORD_EDIT) | ||
| } | ||
|
|
||
| return RecordEditUiState( | ||
| recordInfo = recordInfo, | ||
| recordPageState = recordPageState, | ||
|
|
@@ -153,8 +167,4 @@ class RecordEditPresenter @AssistedInject constructor( | |
| navigator: Navigator, | ||
| ): RecordEditPresenter | ||
| } | ||
|
|
||
| companion object { | ||
| const val MAX_PAGE = 4032 | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,24 @@ | ||
| package com.ninecraft.booket.feature.home | ||
|
|
||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.LaunchedEffect | ||
| import androidx.compose.runtime.getValue | ||
| import androidx.compose.runtime.mutableStateOf | ||
| import androidx.compose.runtime.rememberCoroutineScope | ||
| import androidx.compose.runtime.setValue | ||
| import com.ninecraft.booket.core.common.analytics.AnalyticsHelper | ||
| import com.ninecraft.booket.core.data.api.repository.BookRepository | ||
| import com.ninecraft.booket.core.model.RecentBookModel | ||
| import com.ninecraft.booket.feature.screens.BookDetailScreen | ||
| import com.ninecraft.booket.feature.screens.HomeScreen | ||
| import com.ninecraft.booket.feature.screens.RecordScreen | ||
| import com.ninecraft.booket.feature.screens.SearchScreen | ||
| import com.ninecraft.booket.feature.screens.SettingsScreen | ||
| import com.skydoves.compose.effects.RememberedEffect | ||
| import com.slack.circuit.codegen.annotations.CircuitInject | ||
| import com.slack.circuit.retained.rememberRetained | ||
| import com.slack.circuit.runtime.Navigator | ||
| import com.slack.circuit.runtime.presenter.Presenter | ||
| import com.slack.circuitx.effects.ImpressionEffect | ||
| import dagger.assisted.Assisted | ||
| import dagger.assisted.AssistedFactory | ||
| import dagger.assisted.AssistedInject | ||
|
|
@@ -28,6 +30,7 @@ import kotlinx.coroutines.launch | |
| class HomePresenter @AssistedInject constructor( | ||
| @Assisted private val navigator: Navigator, | ||
| private val repository: BookRepository, | ||
| private val analyticsHelper: AnalyticsHelper, | ||
| ) : Presenter<HomeUiState> { | ||
|
|
||
| @Composable | ||
|
|
@@ -85,10 +88,14 @@ class HomePresenter @AssistedInject constructor( | |
| } | ||
| } | ||
|
|
||
| LaunchedEffect(true) { | ||
| RememberedEffect(true) { | ||
| loadHomeContent() | ||
| } | ||
|
|
||
| ImpressionEffect { | ||
| analyticsHelper.logScreenView(HomeScreen.name) | ||
| } | ||
|
Comment on lines
+95
to
+97
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 스크린 뷰 로깅 방식을 GA4 표준으로 통일 권장
🤖 Prompt for AI Agents |
||
|
|
||
| return HomeUiState( | ||
| uiState = uiState, | ||
| recentBooks = recentBooks, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Firebase BoM + Analytics 추가 OK. KTX 전환 영향(확장 API 사용 여부)만 확인 부탁드립니다.
이번 변경으로
firebase-analytics-ktx→firebase-analytics로 전환되었습니다. 최신 BoM에서는 KTX 확장이 기본 아티팩트로 통합된 경우가 많지만, 코드에서Firebase.analytics등의 KTX 확장을 사용한다면 컴파일이 깨지지 않는지 점검이 필요합니다. 특히AnalyticsHelper/AnalyticsModule에서 어떤 API를 쓰는지 확인해 주세요.다음 스크립트로 KTX 확장 사용 흔적과 잔존 -ktx 의존성 유무를 빠르게 확인할 수 있습니다.
🏁 Script executed:
Length of output: 746
KTX 확장 함수 의존성 누락으로 인한 컴파일 오류 위험
AnalyticsModule.kt에서Firebase.analytics확장 프로퍼티를 사용하고 있는데,firebase-analytics-ktx의존성을 제거하면서 컴파일 오류가 발생할 수 있습니다. 다음 중 하나로 수정해 주세요:libs.firebase.analytics대신 KTX 아티팩트인libs.firebase.analytics.ktx를 추가Firebase.analytics대신FirebaseAnalytics.getInstance(context)호출로 변경🤖 Prompt for AI Agents