728x90
1. 목표와 범위
- 목표
- 기본적인 운영 데이터 분석을 위한 유저 활동 데이터(페이지뷰, 액션) 수집
- 밴드룸 상세 페이지에서 일/주 단위 방문자 수(PV/UV) 통계 제공
- 운영 모니터링(성능/지연/에러율) 및 로그 수집 기반 문제 진단
- 범위
- Web/모바일 클라이언트/서버에서의 이벤트 수집
- 이벤트 스트리밍, 실시간 카운팅, 집계/서빙 API
- 운영 지표 수집·알림 체계
- 제외
- 마케팅 퍼널/리텐션/고급 코호트 분석(향후 OLAP 확장 시 포함)
- 세션 리플레이, 히트맵 등 고급 프론트 분석(외부 솔루션 연동 고려)
2. 용어 정의
- 페이지뷰(PV): 특정 리소스(밴드룸 상세/리스트 등)에 대한 조회 사건 수
- 고유방문자(UV): 중복 없는 방문자 수(사용자 또는 세션 기준)
- 이벤트: 유저 활동 로그(페이지뷰, 클릭 등), 추적 가능한 단위 레코드
- 핫 레이어: 저지연 조회/카운팅을 위한 휘발성/근실시간 스토리지(예: Redis)
- 콜드 레이어: 장기 보관/OLAP 분석 저장소(예: S3 + ClickHouse/BigQuery)
- SDK: 수집 클라이언트 라이브러리(웹/앱/서버)
3. 준거 법규/컴플라이언스(필수)
- 최소 수집·목적 제한: 필요한 항목만 수집
- 개인정보 처리방침 명시: 수집 목적/항목/보관기간/위탁/국외 이전 등
- 동의 관리: 분석/마케팅 쿠키·추적 동의(CMP) 적용 (해외 사용자 대상 시 ePrivacy/GDPR 고려)
- 보유 기간/파기: 예) 원본 이벤트 6
13개월, 핫 카운팅 Redis 1560일 - PII 처리: IP는 /24 마스킹 또는 지오파생치만 저장, user_id/session_id는 가명화(솔트+해시)
- 데이터 주체 권리: 삭제/정정/열람 요청 처리 흐름 준비
- 보안: TLS, at-rest 암호화(KMS), RBAC/접근 로그/감사
4. 전반 아키텍처(개요)
- 수집 계층: SDK(웹/서버) → 수집 API(엣지/게이트웨이)
- 스트리밍: Kafka(배치 전송 및 압축/멱등/재시도)
- 핫 카운팅: Redis(INCR, PFADD/HLL)로 일/주 PV/UV 반영, TTL 관리
- 콜드 저장: S3/오브젝트 스토리지에 원본 Parquet/JSON 적재, ClickHouse 등 OLAP에서 쿼리/머티리얼라이즈 뷰
- 서빙: 밴드룸 상세 API에서 Redis 기반 일/주 통계 즉시 제공, 필요 시 OLAP 백필
- 운영: Prometheus + Grafana + Alertmanager(지표/알림), 구조화 로그(Loki/OpenSearch)로 검색/진단
5. 이벤트 스키마(초안)
- 공통 필드
- event_id: UUID (클라이언트 생성 권장, 멱등키)
- event_type: "page_view" | "action" | ...
- occurred_at: 클라이언트 이벤트 시간(UTC epoch_ms)
- received_at: 서버 수신 시간(UTC)
- tenant/site_id: 멀티테넌시 고려 시
- 컨텍스트
- band_room_id: Long (페이지뷰 대상)
- user_key: String (가명화 user_id 또는 session_id; 둘 중 하나 필수)
- session_id: String (가명화)
- url_path: 정규화된 경로(쿼리 제거)
- referrer_domain: 선택
- user_agent_family / os / device_type: 선택
- ip_truncated: /24 수준 or geolocation(country, city) 파생
- ab_bucket/experiment: 선택
- 확장 필드
- custom: key-value(제한된 whitelist)
스키마의 진화성 고려(필드 추가 시 backward/forward compatibility).
6. 수집/전송 정책
- 클라이언트 SDK
- 디바운스/배치: 0.3~2초 내 모아서 서버로 전송
- 실패시 재시도(지수 백오프), 전송량 제한(샘플링 가능)
- 서명/HMAC(Optional)로 위변조 방지
- 서버 측 수집 API
- JSON 스키마 검증, IP 마스킹, UA 파싱
- 비정상 이벤트는 DLQ(사망 큐)로 격리
- Kafka 프로듀서(서버 사이드)
- linger.ms: 10~50ms
- batch.size: 32KB~128KB
- compression.type: lz4 또는 zstd
- acks: all(신뢰) 또는 1(성능) 환경별 선택
- enable.idempotence: true (중복 방지)
- retries / delivery.timeout.ms: 운영 환경에 맞게 상향
7. 핫 카운팅(실시간 통계: Redis)
- 키 설계
- PV(일): pv:{bandRoomId}:{yyyyMMdd}
- PV(주): pvw:{bandRoomId}:{isoYear-isoWeek}
- UV(일): uv:{bandRoomId}:{yyyyMMdd} (PFADD)
- UV(주): uvw:{bandRoomId}:{isoYear-isoWeek} (PFADD 또는 일별 합산)
- 연산
- PV: INCR
- UV: PFADD(hash(user_key))
- TTL(권장)
- 일 키: 15~60일
- 주 키: 8~16주
- 조회
- 상세 API에서 해당 bandRoomId에 대한 일/주 PV/UV 즉시 반환
- 일관성
- 근실시간 eventual consistency 허용(수 초 지연)
- Cache miss 시 0 반환 또는 백필 로직 별도
8. 콜드 저장/OLAP
- 원본 로그
- S3/오브젝트 스토리지 파티셔닝: dt=yyyy/MM/dd/HH
- 포맷: Parquet + Snappy/ZSTD 압축
- OLAP
- ClickHouse or BigQuery (선호도/인프라에 따라)
- 머티리얼라이즈 뷰: 일간/주간 PV/UV, UTM 코스트/성능 분석 등
- 보관기간
- 원본: 6~13개월(목적에 따라)
- 집계 테이블: 장기 보관 가능(저장 비용 고려)
9. 배치/스트림 처리
- 스트림(Kafka Streams/Flink)
- 중복 제거: dedup window(몇 분), key=event_id
- 세션화(옵션): inactivity 30분 윈도우
- 봇/내부 트래픽 제외: known bot UA, 내부 IP, 속도 기반
- OLAP 적재 Sink
- 배치(Spark/DBT)
- 정합성 보정, 대규모 집계, 리포팅 스케줄
10. 이중 버퍼/배치 전송 전략
- 1차: Kafka 프로듀서 배치(tuning)로 I/O 절감
- 2차(필요 시): 애플리케이션 인메모리 이중버퍼(건수/시간 기준 flush)
- maxBatch 500
2000, maxWait 100500ms - 비동기 flush, 실패시 재시도/백오프
- 주의: 프로세스 크래시 시 유실 위험 → 중요 이벤트는 Redis Streams/로컬 WAL 고려
- maxBatch 500
- 내구성 버퍼(옵션)
- Redis Streams에 임시 적재 → 워커가 Kafka로 전송, 장애 복구 용이
11. 분산 환경 부작용(사이드 이펙트) 대책
- 멱등성
- event_id 기준 idempotent 처리(중복 이벤트 재수집 방지)
- Redis 카운팅 중복 최소화: PV는 중복 허용(약간의 오차 감수), UV는 HLL으로 근사치 관리
- 순서 보장
- Kafka 파티셔닝 키를 band_room_id 기반으로 설정하면 동일 리소스 이벤트는 순서성↑
- 시간/클록 스큐
- occurred_at(클라이언트)와 received_at(서버) 병행 저장
- 집계는 서버 수신 시간 기준 기본, 필요시 클라이언트 시간 보정
- 재시도/백오프
- SDK/수집 API/프로듀서 전 구간에서 정책 일관화
- 백프레셔
- Kafka 큐 적체 모니터링, 프로듀서 스로틀, 수집 API 레이트 리밋
- 장애 격리
- DLQ로 비정상 이벤트 격리
- Kafka/Redis 장애 시 서비스 요청 경로는 degrade(카운트 미반영 허용), 사용자 지연 최소화
12. API 요구사항(서빙)
- 밴드룸 상세 API 응답 내 포함
- visit_stats.daily_pv: Long
- visit_stats.weekly_pv: Long
- visit_stats.daily_uv: Long (옵션)
- visit_stats.weekly_uv: Long (옵션)
- 지연 목표(SLO)
- P95 < 100ms (Redis 조회 1~2ms + 기타 오버헤드)
- 오류 처리
- Redis 미가용 시 0 반환 또는 fallback 문구(운영 경보 발송)
13. 모니터링/관측성
- Prometheus (Micrometer/Actuator)
- http_server_requests_seconds{route="/bandroom/{id}"}: 지연/에러율
- kafka_producer/consumer metrics: 전송/지연/오프셋 랙
- redis ops: latency, hits/misses, memory
- 커스텀 지표: page_request_total{route, status}, event_ingest_total{type}, visit_stats_request_total
- Alert
- P95 지연 상승, 5xx 비율 상승, Kafka lag 초과, Redis 메모리 임계, 쓰기 실패율
- 로그
- JSON 구조화, 상관ID(traceId), 필수 필드: band_room_id, route, latency
- Loki/OpenSearch로 집계/검색
14. 성능/용량 계획
- 추정 트래픽
- QPS(최대/평균), 동시 접속자 수, 이벤트 전송 빈도
- Redis 용량
- 키 수: bandRoomId × (일 키 + 주 키 + UV 키)
- TTL 감안하여 메모리 추정, eviction 정책 No(권장하지 않음), 알람 설정
- Kafka
- 파티션 수: 스루풋/사이드 보장 고려(예: 6~24), 보관 기간(원본 로그 보관 필요치 수준)
- 압축 zstd/lz4, 디스크/네트워크 대역폭 추정
- OLAP/스토리지
- 일별 데이터량(행 수, 바이트), 압축률, 쿼리 패턴에 따른 인덱스/파티션 전략
15. 보안/권한/프라이버시
- 전송/저장 암호화(TLS, at-rest + KMS)
- 접근 제어: RBAC/ABAC, 비식별 데이터 우선
- PII 분리 저장(필요 시), 데이터 마스킹/익명화
- 감사 로그, 접근 이력 보관
16. 데이터 보정/삭제 프로세스
- 삭제 요청
- user_key 기준 원본/파생 데이터 삭제 또는 가명화
- Redis 키의 UV(HLL)는 정확 삭제가 어려움 → UV는 집계 수준에서 대체/보정 정책 문서화
- 보정
- 누락/중복 발생 시 재처리 파이프라인(리플레이), 보정 Job 설계
17. 롤아웃 전략
- 점진 도입
- 10% → 50% → 100% 트래픽에 SDK/수집 적용
- 샘플링/배치 설정(linger.ms 등) 가변 파라미터화
- 카나리/피처 플래그
- 환경별/채널별 온·오프 가능
- 성능 검증
- Synthetic 트래픽/로드 테스트, 알람 임계값 튜닝
18. 테스트 계획
- 단위/통합
- SDK 전송/재시도/배치, 수집 API 검증, Kafka 프로듀서 설정
- Redis 카운팅 정확도(PV/UV), TTL 만료 테스트
- 비기능
- 성능/부하, 장애주입(네트워크/브로커 다운), 복구 시나리오
- 보안(권한/인증/입력 검증)
- 데이터 품질
- 중복률, 결측률, 이상치 감지(봇/내부 트래픽 필터링 효과)
19. 운영 가이드(런북)
- 장애 유형별 대응
- Kafka 장애: 수집 지연/적체 알림 → 프로듀서 스로틀/버퍼 증가 → 복구 후 리커버
- Redis 장애: 통계 0/캐시 미스 처리, 운영 알림
- 지연 상승: 핫스팟 키/분산 키 설계 재검토, 스케일 아웃
- 정기 운영
- TTL/키 수 모니터링, Kafka 토픽 보관/컴팩션 관리
- 비용 최적화(압축/보관 기간/샘플링)
20. 오픈 이슈/의사결정(ADR)
- UV 기준: user_key vs session_id → 서비스 정책에 맞춰 결정 필요
- Kafka acks 설정: 성능 vs 내구성 트레이드오프
- Redis UV(HLL) 오차 허용치(±0.8%~2%) 문서화
- OLAP 선택(ClickHouse vs BigQuery) 및 비용/운영 고려
- SDK/수집 API에서의 샘플링 비율(초기 100% → 50% 가능성)
21. 부록: 기본 파라미터 권장값(초기)
- Kafka Producer
- linger.ms=30ms, batch.size=64KB, compression=zstd, acks=all, enable.idempotence=true, retries=Int
- Redis
- TTL: 일 키 30일, 주 키 12주(초기), 메모리 알람 70/85/95%
- Prometheus
- scrape_interval=15s, 주요 대시보드: API 지연/에러율, Kafka lag, Redis ops/memory
- SDK
- 배치 전송: 0.5
1.0초 또는 2050건(둘 중 먼저), 실패 재시도 최대 3회(백오프)
- 배치 전송: 0.5
728x90
'BindProject' 카테고리의 다른 글
| 리뷰 정렬부터 이메일 미인증 유저 정리까지 (3) | 2025.08.17 |
|---|---|
| 리뷰 모듈 기획·설계·구현 정리서 (review × bandroom-info 메시징 & 캐싱 중심) (8) | 2025.08.16 |
| 지금까지 프로젝트 리팩토링 시즌 도입 (7) | 2025.08.12 |
| 메시징 플레이그라운드 만들기 (4) | 2025.08.12 |
| 구현된 모든 서비스를 컨테이너화 시키는 여정기 (7) | 2025.08.05 |