mirror of
https://github.com/ChangJoo-Park/learn-flutter.git
synced 2025-06-13 11:35:22 +00:00
535 lines
16 KiB
Markdown
535 lines
16 KiB
Markdown
# 사용자 분석 도구
|
|
|
|
앱을 배포한 후에는 사용자들이 앱을 어떻게 사용하는지 분석하는 것이 중요합니다. 이를 통해 UX를 개선하고, 사용자 행동 패턴을 파악하며, 비즈니스 결정을 내리는 데 도움이 됩니다. 이 문서에서는 Flutter 앱에서 사용할 수 있는 주요 분석 도구인 Firebase Analytics와 PostHog를 살펴보겠습니다.
|
|
|
|
## 분석 도구의 중요성
|
|
|
|
```mermaid
|
|
graph LR
|
|
A[사용자 행동] --> B[데이터 수집]
|
|
B --> C[데이터 분석]
|
|
C --> D[인사이트 도출]
|
|
D --> E[제품 개선]
|
|
E --> A
|
|
style B fill:#f9d5e5
|
|
style C fill:#f9d5e5
|
|
style D fill:#d5e5f9
|
|
```
|
|
|
|
분석 도구를 사용하면 다음과 같은 이점이 있습니다:
|
|
|
|
1. **사용자 행동 이해**: 어떤 기능을 많이 사용하는지, 어디서 이탈하는지 파악
|
|
2. **앱 성능 모니터링**: 오류 발생률, 응답 시간 등 측정
|
|
3. **비즈니스 목표 추적**: 전환율, 사용자 유지율 등 측정
|
|
4. **A/B 테스트**: 여러 변형을 테스트하여 최적의 UX 결정
|
|
5. **마케팅 효과 측정**: 다양한 마케팅 채널의 효과 분석
|
|
|
|
## Firebase Analytics
|
|
|
|
Firebase Analytics는 Google의 모바일 앱 분석 도구로, 무료이면서도 강력한 기능을 제공합니다.
|
|
|
|
### Firebase Analytics 설정하기
|
|
|
|
#### 1. Firebase 프로젝트 설정
|
|
|
|
먼저 [Firebase Console](https://console.firebase.google.com/)에서 프로젝트를 생성하고 Flutter 앱을 등록해야 합니다:
|
|
|
|
1. Firebase Console에 로그인하고 프로젝트 생성
|
|
2. Flutter 앱 등록 (Android 및 iOS 패키지 이름 입력)
|
|
3. 설정 파일 다운로드(`google-services.json` 및 `GoogleService-Info.plist`)
|
|
4. 각 파일을 프로젝트의 적절한 위치에 배치:
|
|
- Android: `android/app/google-services.json`
|
|
- iOS: `ios/Runner/GoogleService-Info.plist`
|
|
|
|
#### 2. 필요한 패키지 추가
|
|
|
|
pubspec.yaml에 다음 패키지를 추가합니다:
|
|
|
|
```yaml
|
|
dependencies:
|
|
firebase_core: ^2.15.0
|
|
firebase_analytics: ^10.4.4
|
|
```
|
|
|
|
그리고 패키지를 설치합니다:
|
|
|
|
```bash
|
|
flutter pub get
|
|
```
|
|
|
|
#### 3. Firebase 초기화
|
|
|
|
앱의 메인 파일에서 Firebase를 초기화합니다:
|
|
|
|
```dart
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
import 'package:firebase_analytics/firebase_analytics.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
Future<void> main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
await Firebase.initializeApp();
|
|
runApp(MyApp());
|
|
}
|
|
|
|
class MyApp extends StatelessWidget {
|
|
// Firebase Analytics 인스턴스 생성
|
|
static FirebaseAnalytics analytics = FirebaseAnalytics.instance;
|
|
static FirebaseAnalyticsObserver observer =
|
|
FirebaseAnalyticsObserver(analytics: analytics);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(
|
|
title: 'Firebase Analytics Demo',
|
|
navigatorObservers: [observer], // 화면 전환 추적을 위한 설정
|
|
home: MyHomePage(),
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
### 이벤트 추적하기
|
|
|
|
Firebase Analytics에서 사용자 행동을 추적하려면 이벤트를 기록해야 합니다:
|
|
|
|
```dart
|
|
class AnalyticsService {
|
|
final FirebaseAnalytics _analytics = FirebaseAnalytics.instance;
|
|
|
|
// 화면 보기 이벤트 로깅
|
|
Future<void> logScreenView({
|
|
required String screenName,
|
|
String screenClass = 'Flutter',
|
|
}) async {
|
|
await _analytics.logScreenView(
|
|
screenName: screenName,
|
|
screenClass: screenClass,
|
|
);
|
|
}
|
|
|
|
// 로그인 이벤트 로깅
|
|
Future<void> logLogin({String? loginMethod}) async {
|
|
await _analytics.logLogin(loginMethod: loginMethod);
|
|
}
|
|
|
|
// 구매 이벤트 로깅
|
|
Future<void> logPurchase({
|
|
required double price,
|
|
required String currency,
|
|
required String itemId,
|
|
required String itemName,
|
|
}) async {
|
|
await _analytics.logPurchase(
|
|
currency: currency,
|
|
value: price,
|
|
items: [
|
|
AnalyticsEventItem(
|
|
itemId: itemId,
|
|
itemName: itemName,
|
|
price: price,
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
// 사용자 속성 설정
|
|
Future<void> setUserProperty({
|
|
required String name,
|
|
required String value,
|
|
}) async {
|
|
await _analytics.setUserProperty(name: name, value: value);
|
|
}
|
|
|
|
// 사용자 ID 설정 (식별 가능한 정보는 피해야 함)
|
|
Future<void> setUserId(String? id) async {
|
|
await _analytics.setUserId(id: id);
|
|
}
|
|
|
|
// 커스텀 이벤트 로깅
|
|
Future<void> logCustomEvent({
|
|
required String name,
|
|
Map<String, dynamic>? parameters,
|
|
}) async {
|
|
await _analytics.logEvent(
|
|
name: name,
|
|
parameters: parameters,
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
### 이벤트 사용 예시
|
|
|
|
위의 서비스를 사용하여 앱 내에서 이벤트를 추적하는 방법:
|
|
|
|
```dart
|
|
class ProductDetailPage extends StatelessWidget {
|
|
final Product product;
|
|
final AnalyticsService _analyticsService = AnalyticsService();
|
|
|
|
ProductDetailPage({required this.product});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// 화면이 표시될 때 화면 보기 이벤트 로깅
|
|
_analyticsService.logScreenView(
|
|
screenName: 'product_detail',
|
|
screenClass: 'ProductDetailPage',
|
|
);
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(title: Text(product.name)),
|
|
body: Column(
|
|
children: [
|
|
// 제품 상세 정보...
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
// 구매 버튼 클릭 시 이벤트 로깅
|
|
_analyticsService.logCustomEvent(
|
|
name: 'add_to_cart',
|
|
parameters: {
|
|
'item_id': product.id,
|
|
'item_name': product.name,
|
|
'item_price': product.price,
|
|
},
|
|
);
|
|
// 장바구니에 추가 로직...
|
|
},
|
|
child: Text('장바구니에 추가'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Riverpod과 함께 사용하기
|
|
|
|
Riverpod을 사용하는 경우 다음과 같이 분석 서비스를 제공할 수 있습니다:
|
|
|
|
```dart
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
final analyticsServiceProvider = Provider<AnalyticsService>((ref) {
|
|
return AnalyticsService();
|
|
});
|
|
|
|
// 사용 예시
|
|
class ProductDetailPage extends ConsumerWidget {
|
|
final Product product;
|
|
|
|
ProductDetailPage({required this.product});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final analyticsService = ref.read(analyticsServiceProvider);
|
|
|
|
// 화면 로깅
|
|
analyticsService.logScreenView(
|
|
screenName: 'product_detail',
|
|
screenClass: 'ProductDetailPage',
|
|
);
|
|
|
|
// 나머지 UI 코드...
|
|
}
|
|
}
|
|
```
|
|
|
|
### 디버그 모드에서 이벤트 검증
|
|
|
|
개발 중에는 이벤트가 올바르게 전송되는지 확인하는 것이 중요합니다. Firebase Analytics는 다음과 같은 디버그 기능을 제공합니다:
|
|
|
|
```dart
|
|
// 디버그 모드 활성화 (개발 중에만 사용)
|
|
await FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);
|
|
|
|
// iOS 디버그 모드 활성화
|
|
if (Platform.isIOS) {
|
|
await FirebaseAnalytics.instance.setIosAnalyticsCollectionEnabled(true);
|
|
}
|
|
|
|
// Android 디버그 모드 활성화
|
|
if (Platform.isAndroid) {
|
|
await FirebaseAnalytics.instance.setAndroidAnalyticsCollectionEnabled(true);
|
|
}
|
|
```
|
|
|
|
Firebase Console의 DebugView에서 실시간으로 전송되는 이벤트를 확인할 수 있습니다.
|
|
|
|
## PostHog
|
|
|
|
PostHog는 오픈소스 제품 분석 플랫폼으로, 자체 호스팅이 가능하고 고급 기능을 제공합니다.
|
|
|
|
### PostHog 특징
|
|
|
|
- **오픈소스**: 자체 호스팅 가능
|
|
- **제품 중심 분석**: 사용자 행동 흐름 및 퍼널 분석
|
|
- **세션 레코딩**: 사용자 세션 녹화 및 재생
|
|
- **히트맵**: 클릭, 스크롤 등의 사용자 상호작용 시각화
|
|
- **피처 플래그**: A/B 테스트 및 기능 출시 제어
|
|
- **개인정보 중심**: EU GDPR 준수를 위한 기능 제공
|
|
|
|
### PostHog 설정하기
|
|
|
|
#### 1. 패키지 추가
|
|
|
|
pubspec.yaml에 다음 패키지를 추가합니다:
|
|
|
|
```yaml
|
|
dependencies:
|
|
posthog_flutter: ^3.1.0
|
|
```
|
|
|
|
그리고 패키지를 설치합니다:
|
|
|
|
```bash
|
|
flutter pub get
|
|
```
|
|
|
|
#### 2. PostHog 초기화
|
|
|
|
앱의 메인 파일에서 PostHog를 초기화합니다:
|
|
|
|
```dart
|
|
import 'package:flutter/material.dart';
|
|
import 'package:posthog_flutter/posthog_flutter.dart';
|
|
|
|
Future<void> main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
// PostHog 초기화
|
|
await Posthog.initAsync(
|
|
apiKey: 'YOUR_API_KEY',
|
|
options: PosthogOptions(
|
|
host: 'https://app.posthog.com', // 또는 자체 호스팅 URL
|
|
captureApplicationLifecycleEvents: true,
|
|
persistenceStrategy: PersistenceStrategy.memory,
|
|
flushAt: 20, // 이벤트가 20개 쌓이면 서버로 전송
|
|
flushInterval: 30, // 30초마다 서버로 전송
|
|
debug: true, // 개발 중에만 true로 설정
|
|
),
|
|
);
|
|
|
|
runApp(MyApp());
|
|
}
|
|
```
|
|
|
|
### 이벤트 추적하기
|
|
|
|
PostHog를 사용하여 이벤트를 추적하는 방법:
|
|
|
|
```dart
|
|
class PostHogAnalyticsService {
|
|
// 이벤트 캡처
|
|
void captureEvent(String eventName, {Map<String, dynamic>? properties}) {
|
|
Posthog.capture(
|
|
eventName: eventName,
|
|
properties: properties,
|
|
);
|
|
}
|
|
|
|
// 화면 보기 이벤트 캡처
|
|
void captureScreenView(String screenName, {Map<String, dynamic>? properties}) {
|
|
final screenProperties = {
|
|
'screen_name': screenName,
|
|
...?properties,
|
|
};
|
|
Posthog.capture(
|
|
eventName: 'Screen View',
|
|
properties: screenProperties,
|
|
);
|
|
}
|
|
|
|
// 사용자 식별
|
|
void identify(String userId, {Map<String, dynamic>? userProperties}) {
|
|
Posthog.identify(
|
|
userId: userId,
|
|
userProperties: userProperties,
|
|
);
|
|
}
|
|
|
|
// 사용자 속성 설정
|
|
void setUserProperties(Map<String, dynamic> properties) {
|
|
Posthog.identify(userProperties: properties);
|
|
}
|
|
|
|
// 그룹 설정 (팀, 조직 등)
|
|
void setGroup(String groupType, String groupKey) {
|
|
Posthog.group(
|
|
groupType: groupType,
|
|
groupKey: groupKey,
|
|
);
|
|
}
|
|
|
|
// 이벤트 플러시 (즉시 서버로 전송)
|
|
void flush() {
|
|
Posthog.flush();
|
|
}
|
|
|
|
// 추적 중지 (예: 로그아웃 시)
|
|
void reset() {
|
|
Posthog.reset();
|
|
}
|
|
}
|
|
```
|
|
|
|
### 피처 플래그 사용하기
|
|
|
|
PostHog의 주요 기능 중 하나는 피처 플래그(Feature Flags)로, 런타임에 특정 기능을 활성화하거나 비활성화할 수 있습니다:
|
|
|
|
```dart
|
|
class FeatureFlagService {
|
|
// 피처 플래그 값 가져오기
|
|
Future<bool> isFeatureEnabled(String flagKey) async {
|
|
return await Posthog.isFeatureEnabled(flagKey) ?? false;
|
|
}
|
|
|
|
// 모든 피처 플래그 가져오기
|
|
Future<Map<String, bool>> getAllFeatureFlags() async {
|
|
return await Posthog.getAllFeatureFlags() ?? {};
|
|
}
|
|
|
|
// 특정 피처 플래그와 연관된 페이로드 가져오기
|
|
Future<dynamic> getFeatureFlagPayload(String flagKey) async {
|
|
return await Posthog.getFeatureFlagPayload(flagKey);
|
|
}
|
|
|
|
// 새로운 피처 플래그 가져오기 (서버에서 새로고침)
|
|
Future<void> reloadFeatureFlags() async {
|
|
await Posthog.reloadFeatureFlags();
|
|
}
|
|
}
|
|
```
|
|
|
|
### 피처 플래그 사용 예시
|
|
|
|
```dart
|
|
class NewFeatureWidget extends StatelessWidget {
|
|
final FeatureFlagService _featureFlagService = FeatureFlagService();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FutureBuilder<bool>(
|
|
future: _featureFlagService.isFeatureEnabled('new-ui-design'),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return CircularProgressIndicator();
|
|
}
|
|
|
|
final isNewDesignEnabled = snapshot.data ?? false;
|
|
|
|
return isNewDesignEnabled
|
|
? NewDesignWidget() // 새 디자인 위젯
|
|
: OldDesignWidget(); // 기존 디자인 위젯
|
|
},
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Riverpod과 함께 사용하기
|
|
|
|
```dart
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
final posthogAnalyticsProvider = Provider<PostHogAnalyticsService>((ref) {
|
|
return PostHogAnalyticsService();
|
|
});
|
|
|
|
final featureFlagProvider = Provider<FeatureFlagService>((ref) {
|
|
return FeatureFlagService();
|
|
});
|
|
|
|
// 특정 기능 플래그 상태를 제공하는 provider
|
|
final newUiFeatureFlagProvider = FutureProvider<bool>((ref) async {
|
|
final featureFlagService = ref.read(featureFlagProvider);
|
|
return await featureFlagService.isFeatureEnabled('new-ui-design');
|
|
});
|
|
|
|
// 사용 예시
|
|
class NewFeatureScreen extends ConsumerWidget {
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
// 분석 서비스 사용
|
|
final analyticsService = ref.read(posthogAnalyticsProvider);
|
|
analyticsService.captureScreenView('new_feature_screen');
|
|
|
|
// 피처 플래그 상태 확인
|
|
final isNewUiEnabled = ref.watch(newUiFeatureFlagProvider);
|
|
|
|
return isNewUiEnabled.when(
|
|
data: (isEnabled) => isEnabled ? NewUiWidget() : OldUiWidget(),
|
|
loading: () => CircularProgressIndicator(),
|
|
error: (_, __) => OldUiWidget(), // 오류 시 기본 UI 표시
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
## 분석 데이터 해석 및 활용
|
|
|
|
수집한 분석 데이터를 실제로 활용하는 방법에 대해 알아보겠습니다.
|
|
|
|
### 주요 메트릭 추적
|
|
|
|
일반적으로 추적해야 할 중요한 메트릭:
|
|
|
|
1. **사용자 획득**: 신규 사용자 수, 설치 수, 설치 출처
|
|
2. **사용자 참여**: 일/주/월간 활성 사용자(DAU/WAU/MAU), 세션 길이, 세션 빈도
|
|
3. **사용자 유지**: 리텐션 비율, 이탈률
|
|
4. **전환**: 가입 완료, 구매, 구독 등의 핵심 전환 이벤트
|
|
5. **앱 성능**: 크래시 비율, 응답 시간, ANR(App Not Responding) 발생 수
|
|
|
|
### 분석 데이터 기반 개선 사례
|
|
|
|
수집된 데이터를 기반으로 앱을 개선할 수 있는 예시:
|
|
|
|
1. **사용자 여정 최적화**:
|
|
|
|
- 데이터: 결제 페이지에서 높은 이탈률 발견
|
|
- 개선: 결제 프로세스 단순화, 오류 메시지 개선
|
|
|
|
2. **핵심 기능 강화**:
|
|
|
|
- 데이터: 특정 기능의 사용 빈도가 매우 높음
|
|
- 개선: 해당 기능을 더 쉽게 접근할 수 있도록 UI 개선
|
|
|
|
3. **사용자 유지율 향상**:
|
|
- 데이터: 설치 후 3일 이내 이탈하는 사용자가 많음
|
|
- 개선: 온보딩 개선, 초기 가치 제안 강화
|
|
|
|
### 주의할 점
|
|
|
|
분석 도구를 사용할 때 주의해야 할 사항:
|
|
|
|
1. **개인정보 보호**: GDPR, CCPA 등 데이터 보호 규정 준수
|
|
2. **사용자 동의**: 추적 전에 사용자 동의 획득
|
|
3. **과도한 추적 방지**: 필요한 데이터만 수집
|
|
4. **식별 정보 제한**: 개인 식별 정보는 최소화
|
|
5. **데이터 보관 정책**: 불필요한 데이터는 적절히 폐기
|
|
|
|
## 적절한 도구 선택하기
|
|
|
|
Firebase Analytics와 PostHog 중 어떤 것을 선택해야 할지 결정하는 기준:
|
|
|
|
### Firebase Analytics가 적합한 경우
|
|
|
|
- 무료로 시작하고 싶을 때
|
|
- Google 생태계의 다른 서비스와 통합이 필요할 때
|
|
- 간단한 이벤트 추적과 기본적인 분석 기능이 필요할 때
|
|
- 모바일 앱 성능에 민감한 경우 (경량화된 SDK)
|
|
|
|
### PostHog가 적합한 경우
|
|
|
|
- 데이터 소유권과 개인정보 보호가 중요할 때 (자체 호스팅 가능)
|
|
- 세션 레코딩, 히트맵 등 고급 분석 기능이 필요할 때
|
|
- A/B 테스트와 피처 플래그가 필요할 때
|
|
- 오픈소스 솔루션을 선호할 때
|
|
|
|
## 결론
|
|
|
|
사용자 분석 도구는 앱의 개선과 사용자 경험 향상에 중요한 역할을 합니다. Firebase Analytics는 시작하기 쉽고 Google 생태계와의 통합이 뛰어나며, PostHog는 더 많은 고급 기능과 데이터 소유권을 제공합니다.
|
|
|
|
애플리케이션의 요구사항, 예산, 개인정보 보호 요구 등을 고려하여 적절한 도구를 선택하고, 사용자 행동을 체계적으로 추적하여 데이터 기반 의사 결정을 내리는 것이 중요합니다. 이러한 도구를 활용하면 사용자의 필요와 행동 패턴을 더 잘 이해하고, 더 나은 앱 경험을 제공할 수 있습니다.
|