Skip to content

Commit 54bb9b5

Browse files
committed
[feat] #208 apmplitude 객체 구성
1 parent d543a11 commit 54bb9b5

4 files changed

Lines changed: 260 additions & 0 deletions

File tree

Projects/CoreKit/Project.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ let coreKit: Target = .target(
3636
.external(name: "KakaoSDKCommon"),
3737
.external(name: "KakaoSDKShare"),
3838
.external(name: "KakaoSDKTemplate"),
39+
.external(name: "AmplitudeSwift"),
3940
],
4041
settings: .settings()
4142
)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import Foundation
2+
import AmplitudeSwift
3+
4+
/// Amplitude Analytics 관리자
5+
public final class AmplitudeManager {
6+
public static let shared = AmplitudeManager()
7+
8+
private var amplitude: Amplitude?
9+
10+
private init() {}
11+
12+
/// Amplitude 초기화
13+
/// - Parameters:
14+
/// - apiKey: Amplitude API Key
15+
/// - userId: 사용자 ID (옵셔널)
16+
public func initialize(apiKey: String, userId: String? = nil) {
17+
amplitude = Amplitude(configuration: Configuration(
18+
apiKey: apiKey
19+
))
20+
21+
if let userId = userId {
22+
setUserId(userId)
23+
}
24+
}
25+
26+
/// 사용자 ID 설정
27+
/// - Parameter userId: 사용자 ID
28+
public func setUserId(_ userId: String) {
29+
amplitude?.setUserId(userId: userId)
30+
}
31+
32+
/// 사용자 속성 설정
33+
/// - Parameter properties: 사용자 속성
34+
public func setUserProperties(_ properties: [String: Any]) {
35+
let identify = Identify()
36+
properties.forEach { key, value in
37+
identify.set(property: key, value: value)
38+
}
39+
amplitude?.identify(identify: identify)
40+
}
41+
42+
/// 이벤트 전송
43+
/// - Parameter event: AnalyticsEvent
44+
public func track(_ event: AnalyticsEvent) {
45+
guard let amplitude = amplitude else {
46+
print("⚠️ Amplitude가 초기화되지 않았습니다.")
47+
return
48+
}
49+
50+
let eventProperties = event.properties.isEmpty ? nil : event.properties
51+
amplitude.track(
52+
eventType: event.eventName,
53+
eventProperties: eventProperties
54+
)
55+
56+
#if DEBUG
57+
print("📊 [Analytics] \(event.eventName)")
58+
if let properties = eventProperties {
59+
print(" Properties: \(properties)")
60+
}
61+
#endif
62+
}
63+
64+
/// 이벤트 버퍼 즉시 전송
65+
public func flush() {
66+
amplitude?.flush()
67+
}
68+
69+
/// Amplitude 리셋 (로그아웃 시 사용)
70+
public func reset() {
71+
amplitude?.reset()
72+
}
73+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import Foundation
2+
3+
/// Analytics 이벤트 타입
4+
public enum AnalyticsEvent {
5+
case app_open(deviceOS: String, appVersion: String)
6+
case view_splash
7+
case login_start(method: LoginMethod)
8+
case login_complete(method: LoginMethod)
9+
case interest_select(interests: [String])
10+
case onboarding_complete
11+
case view_home_pokit(entryPoint: String)
12+
case view_home_recommend(entryPoint: String)
13+
case add_folder(folderName: String)
14+
case add_link(folderId: String, linkDomain: String)
15+
case view_folder_detail(folderId: String)
16+
case view_link_detail(linkId: String, linkDomain: String)
17+
case share_link(linkId: String, shareTarget: String)
18+
case session_end(duration: Int)
19+
20+
/// 이벤트명 (rawValue)
21+
public var eventName: String {
22+
switch self {
23+
case .app_open: return "app_open"
24+
case .view_splash: return "view_splash"
25+
case .login_start: return "login_start"
26+
case .login_complete: return "login_complete"
27+
case .interest_select: return "interest_select"
28+
case .onboarding_complete: return "onboarding_complete"
29+
case .view_home_pokit: return "view_home_pokit"
30+
case .view_home_recommend: return "view_home_recommend"
31+
case .add_folder: return "add_folder"
32+
case .add_link: return "add_link"
33+
case .view_folder_detail: return "view_folder_detail"
34+
case .view_link_detail: return "view_link_detail"
35+
case .share_link: return "share_link"
36+
case .session_end: return "session_end"
37+
}
38+
}
39+
40+
/// Amplitude에 전송할 속성값
41+
public var properties: [String: Any] {
42+
switch self {
43+
case let .app_open(deviceOS, appVersion):
44+
return [
45+
PropertyKey.device_os.rawValue: deviceOS,
46+
PropertyKey.app_version.rawValue: appVersion
47+
]
48+
49+
case .view_splash:
50+
return [:]
51+
52+
case let .login_start(method):
53+
return [PropertyKey.method.rawValue: method.rawValue]
54+
55+
case let .login_complete(method):
56+
return [PropertyKey.method.rawValue: method.rawValue]
57+
58+
case let .interest_select(interests):
59+
return [PropertyKey.interests.rawValue: interests]
60+
61+
case .onboarding_complete:
62+
return [:]
63+
64+
case let .view_home_pokit(entryPoint):
65+
return [PropertyKey.entry_point.rawValue: entryPoint]
66+
67+
case let .view_home_recommend(entryPoint):
68+
return [PropertyKey.entry_point.rawValue: entryPoint]
69+
70+
case let .add_folder(folderName):
71+
return [PropertyKey.folder_name.rawValue: folderName]
72+
73+
case let .add_link(folderId, linkDomain):
74+
return [
75+
PropertyKey.folder_id.rawValue: folderId,
76+
PropertyKey.link_domain.rawValue: linkDomain
77+
]
78+
79+
case let .view_folder_detail(folderId):
80+
return [PropertyKey.folder_id.rawValue: folderId]
81+
82+
case let .view_link_detail(linkId, linkDomain):
83+
return [
84+
PropertyKey.link_id.rawValue: linkId,
85+
PropertyKey.link_domain.rawValue: linkDomain
86+
]
87+
88+
case let .share_link(linkId, shareTarget):
89+
return [
90+
PropertyKey.link_id.rawValue: linkId,
91+
PropertyKey.share_target.rawValue: shareTarget
92+
]
93+
94+
case let .session_end(duration):
95+
return [PropertyKey.duration.rawValue: duration]
96+
}
97+
}
98+
}
99+
100+
/// Analytics 속성 키
101+
public enum PropertyKey: String {
102+
case device_os
103+
case app_version
104+
case method
105+
case interests
106+
case entry_point
107+
case folder_name
108+
case folder_id
109+
case link_domain
110+
case link_id
111+
case share_target
112+
case duration
113+
}
114+
115+
/// 로그인 방식
116+
public enum LoginMethod: String {
117+
case apple = "Apple"
118+
case google = "Google"
119+
case kakao = "Kakao"
120+
}
121+
122+
extension LoginMethod {
123+
init?(authPlatform: String) {
124+
switch authPlatform.lowercased() {
125+
case "apple":
126+
self = .apple
127+
case "google":
128+
self = .google
129+
case "kakao":
130+
self = .kakao
131+
default:
132+
return nil
133+
}
134+
}
135+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import Dependencies
2+
import Foundation
3+
4+
/// Amplitude Client Protocol
5+
public struct AmplitudeClient {
6+
public var initialize: @Sendable (String, String?) -> Void
7+
public var track: @Sendable (AnalyticsEvent) -> Void
8+
public var setUserId: @Sendable (String) -> Void
9+
public var setUserProperties: @Sendable ([String: Any]) -> Void
10+
public var flush: @Sendable () -> Void
11+
public var reset: @Sendable () -> Void
12+
}
13+
14+
public extension DependencyValues {
15+
var amplitude: AmplitudeClient {
16+
get { self[AmplitudeClientKey.self] }
17+
set { self[AmplitudeClientKey.self] = newValue }
18+
}
19+
}
20+
21+
private enum AmplitudeClientKey: DependencyKey {
22+
static let liveValue = AmplitudeClient(
23+
initialize: { apiKey, userId in
24+
AmplitudeManager.shared.initialize(apiKey: apiKey, userId: userId)
25+
},
26+
track: { event in
27+
AmplitudeManager.shared.track(event)
28+
},
29+
setUserId: { userId in
30+
AmplitudeManager.shared.setUserId(userId)
31+
},
32+
setUserProperties: { properties in
33+
AmplitudeManager.shared.setUserProperties(properties)
34+
},
35+
flush: {
36+
AmplitudeManager.shared.flush()
37+
},
38+
reset: {
39+
AmplitudeManager.shared.reset()
40+
}
41+
)
42+
43+
static let testValue = AmplitudeClient(
44+
initialize: { _, _ in },
45+
track: { _ in },
46+
setUserId: { _ in },
47+
setUserProperties: { _ in },
48+
flush: { },
49+
reset: { }
50+
)
51+
}

0 commit comments

Comments
 (0)