You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
다봄은 통신사의 가족 데이터 공유 서비스(SKT 데이터 공유, KT 패밀리 박스, LG U+ 데이터 공유)를 벤치마킹하여 설계한 실시간 데이터 관리 플랫폼입니다.
가족(그룹) 단위로 공유되는 데이터 총량을 실시간으로 집계·시각화하고, 부모/관리자가 정책(차단/개인 한도/시간대 제한 등)을 변경하면 즉시 반영되도록 하는 시스템을 구축합니다.
핵심 가치
가치
설명
실시간 시각화
가족 데이터 사용량 실시간 집계
SSE 기반 대시보드로 가족 구성원별 사용량을 실시간 모니터링
즉시 정책 반영
정책 변경 → 다음 이벤트부터 즉시 적용
한도 변경 시 이미 초과한 사용자도 소급 차단 처리
가족 소통 촉진
이의제기·미션·보상·리캡
데이터 사용을 매개로 한 건강한 가족 간 소통 구조 설계
프로젝트 배경 & 학습 목표
가족 구성원 간 데이터를 실시간으로 공유하고, 부모가 자녀의 데이터 사용을 제어하려는 니즈가 증가하고 있습니다. 이 프로젝트는 단순히 기능을 구현하는 것을 넘어, 대규모 트래픽 처리와 동시성 제어라는 기술적 도전을 학습하기 위해 설계되었습니다.
영역
학습 목표
백엔드
대용량 이벤트 스트리밍 파이프라인, 동시성 제어(정합성), 분산락/원자 연산, 장애 및 재처리(Idempotency) 설계
프론트엔드
실시간 UI(대시보드), 실시간 알림/상태 반영(SSE), PWA 푸시 알림
인프라
IaC(Terraform) 기반 AWS 인프라 프로비저닝, CI/CD 자동화, Observability 통합
왜 이 규모인가?
항목
값
설계 의도
가상 사용자 수
1,000,000명
대규모 트래픽 환경에서의 시스템 안정성 검증
가족 그룹 수
250,000개
그룹당 평균 4인, 최대 10명 — 가족 단위 동시성 제어 학습
이벤트 처리량
5,000 TPS
초당 이벤트 처리 파이프라인의 병목 식별과 최적화
차단 판정 지연
100ms 이하
P99 기준 실시간 정책 판정의 엄격한 성능 요구사항
핵심 기능
기능
설명
실시간
가족 통합 대시보드
가족 잔여 데이터량, 구성원별 사용 비중 시각화
SSE (1초 폴링)
구성원별 한도 설정
슬라이더 UI로 월별 데이터 한도 조절, 즉시 반영
즉시 적용
즉시 차단/해제
Owner가 특정 구성원의 데이터 사용을 즉시 차단 또는 해제
즉시 적용
시간대별 차단 정책
야간 등 특정 시간대 자동 차단 (KST 기준)
즉시 적용
단계별 소진 알림
잔여량 50%/30%/10% 도달 시 임계치당 1회 알림 발송
PWA Push
이의제기 시스템
조르기(부모 승인 필요) + 긴급 요청(월 1회, 자동 승인)
—
미션 & 보상
부모가 미션 생성, 자녀가 달성 시 보상(쿠폰/기프티콘) 지급
—
월간 리캡
배치 기반 월간 리포트 + 소통 지수 정량화
—
백오피스 관리
정책 템플릿 CRUD, 가족/구성원 관리, 감사 로그, 관리자 푸시 발송
—
사용자 역할
Family Member (일반 구성원)
가족 공유 데이터를 사용하는 일반 사용자입니다. 본인의 실시간 사용량 조회, 가족 전체 잔여 데이터 조회, 알림 수신, 이의제기/보상 요청, 월간 리포트 조회가 가능합니다.
Owner (관리 사용자)
가족 그룹 내 수정 권한을 가진 관리 사용자로, 복수 Owner가 가능합니다. 일반 구성원 기능에 더해 구성원별 한도 설정, 실시간 차단/해제, 시간대 정책 설정, 미션 생성/삭제, 보상·이의제기 승인/거절을 수행합니다. 복수 Owner가 동시에 정책을 수정할 경우 Last Write Wins 방식으로 충돌을 해결하며, 모든 변경은 감사 로그에 기록됩니다.
Backoffice Admin (운영자)
시스템 전체를 관리하는 내부 관리자입니다. 정책 템플릿 CRUD, 개별 가족 정책 직접 수정, 사용자/그룹 검색·조회, 권한 관리, 감사 로그 조회, 관리자 직접 푸시 발송을 담당하며, 정책 변경 시 즉시 적용을 보장합니다.
시스템 아키텍처
flowchart TB
classDef client fill:#E3F2FD,stroke:#2196F3,stroke-width:2px,color:#0D47A1
classDef sim fill:#FFF3E0,stroke:#FB8C00,stroke-width:2px,color:#E65100
classDef api fill:#E8F5E9,stroke:#43A047,stroke-width:2px,color:#1B5E20
classDef event fill:#F3E5F5,stroke:#8E24AA,stroke-width:2px,color:#4A0072
classDef proc fill:#FFEBEE,stroke:#E53935,stroke-width:2px,color:#B71C1C
classDef data fill:#ECEFF1,stroke:#607D8B,stroke-width:2px,color:#263238
classDef batch fill:#FFF8E1,stroke:#F9A825,stroke-width:2px,color:#F57F17
subgraph CLIENT["Client Layer"]
subgraph WC["web-core (Turborepo)"]
WS["web-service<br/>www.dabom.site"]
WA["web-admin<br/>admin.dabom.site"]
end
class WS,WA client
end
subgraph SIM["Simulation Layer"]
TG["simulator-usage<br/>Go · 4종 부하 패턴"]
class TG sim
end
subgraph API["API Layer"]
AC["api-core<br/>Spring Boot · 65 endpoints"]
AN["api-notification<br/>SSE · Web Push (VAPID)"]
class AC,AN api
end
subgraph EVENT["Event Backbone"]
KF[["Kafka (MSK)<br/>usage-events | notification-events"]]
class KF event
end
subgraph PROC["Processing Layer"]
UP["processor-usage<br/>Redis Lua · DB 정산 · Outbox"]
class UP proc
end
subgraph BATCH["Batch Layer"]
BC["batch-core<br/>월경계 처리 · 리캡 집계 · Outbox 발행"]
class BC batch
end
subgraph DATA["Data Layer"]
RD[("Redis<br/>(ElastiCache)")]
DB[("MySQL<br/>(RDS)")]
class RD,DB data
end
TG -->|usage-events| KF
WS & WA --> AC
WS --> AN
AC -->|CRUD| DB
AC -->|캐시| RD
KF -->|usage-events| UP
UP -->|Lua 원자 연산| RD
UP -->|직접 DB 정산| DB
UP -->|outbox 적재| DB
BC -->|월경계·리캡| DB
BC -->|캐시 무효화·분산 락| RD
BC -->|notification-events 후행 발행| KF
KF -->|notification-events| AN
AN -->|SSE · Web Push| WS
Loading
계층별 역할
계층
컴포넌트
역할
Client
web-service + web-admin
Turborepo 모노레포, Next.js PWA 기반 가족 앱 + 백오피스
Simulation
simulator-usage
Go 기반 트래픽 시뮬레이터, 4종 부하 패턴, HTTP 제어 API
API
api-core
9개 도메인 REST API, JWT 인증, 정책 변경 트리거
API
api-notification
notification-events 소비, SSE 1초 폴링 + Web Push (VAPID)
문제: 가족 잔여 데이터 10MB 상태에서 4명이 동시에 사용 요청 — 정합성을 어떻게 보장할 것인가?
해결: Kafka 파티션 키를 familyId로 설정하여 동일 가족의 이벤트를 같은 파티션에서 순차 처리하고, Redis Lua Script로 "잔여량 확인 → 차감 → 상태 변경"을 단일 원자 연산으로 처리합니다.
sequenceDiagram
autonumber
participant K as Kafka
participant PE as Policy Engine
participant R as Redis (Lua)
participant NS as Notification
Note over K, NS: 잔여 데이터 10MB 상황
K->>PE: 아빠 5MB, 엄마 3MB, 자녀1 8MB, 자녀2 4MB (순차)
PE->>R: 아빠 5MB → 10MB >= 5MB ✅ (잔여 5MB)
PE->>R: 엄마 3MB → 5MB >= 3MB ✅ (잔여 2MB)
PE->>R: 자녀1 8MB → 2MB < 8MB ❌ 차단
PE->>R: 자녀2 4MB → 2MB < 4MB ❌ 차단
PE->>NS: 자녀1, 자녀2 즉시 차단 알림
Loading
설계 포인트:
선착순 완전 승인: 먼저 도착한 요청만 승인, 나머지 즉시 차단 (부분 승인 없음)
eventId 기반 Idempotency: UUID v4 + Redis SETNX (TTL 24시간)으로 중복 이벤트 무시
100ms 이내 판정: P99 기준 실시간 차단 판정
2. 정책 즉시 반영 & 소급 차단
문제: Owner가 자녀의 한도를 2GB → 500MB로 축소했는데, 자녀는 이미 1.2GB를 사용 중 — 어떻게 처리할 것인가?
해결: 정책 변경 시 DB + Redis + Kafka 이중 경로로 일관성을 보장합니다.
Owner UI → api-core → RDS 저장 (Source of Truth)
→ Redis constraints 즉시 갱신
→ CustomerQuota 한도/차단 상태 반영
→ Outbox 알림 적재
↓
processor-usage → 현재 사용량 vs 신규 한도 → 초과 시 즉시 차단
3. Outbox 패턴 & 배치 후행 발행
문제: 초당 5,000건의 사용량 이벤트를 처리하면서, 알림 발행도 누락 없이 보장해야 합니다.
해결: processor-usage가 Redis/Lua 처리 후 직접 DB 정산 + usage_event_outbox 적재를 수행합니다. batch-core가 Outbox를 polling하여 notification-events로 후행 발행함으로써 At-Least-Once 전달을 보장합니다.
sequenceDiagram
participant PU as processor-usage
participant DB as MySQL
participant BC as batch-core
participant KF as Kafka
participant AN as api-notification
PU->>DB: 직접 DB 정산 + outbox 적재
BC->>DB: PUBLISH_PENDING row polling
BC->>KF: notification-events 발행
BC->>DB: SENT 상태 업데이트
KF->>AN: 알림 이벤트 소비 → DB 저장 + SSE + Web Push
Loading
4. 실시간 알림 & Web Push
문제: 대시보드의 실시간 데이터 갱신과 차단/알림의 즉각적 전달을 어떻게 보장할 것인가?
해결: api-notification이 3채널 동시 배포(DB 영속화 + SSE 실시간 스트림 + Web Push)를 수행합니다.
SSE 사용량 폴링: 1초 주기로 family_quota 테이블 IN 쿼리 → 변경 감지 시 usage-updated 이벤트 전송 (N+1 방지)
SSE 연결 관리: familyId 단위 ConcurrentHashMap, 60초 timeout + 25초 heartbeat
Web Push (VAPID): RFC 8291 기반, BouncyCastle + AES128GCM 암호화, SSRF 방지 내부 IP 차단
14종 알림 타입: 임계치 경고, 차단/해제, 정책 변경, 이의제기, 미션, 보상, 긴급 요청, 관리자 푸시
중복 방지: 임계치당 1회만 발송 (Redis 키 기반 발송 기록)
5. 월경계 운영 안정성 (batch-core)
문제: 월이 바뀔 때 quota 초기화, Redis 캐시 정합성, 리캡 집계를 안정적으로 처리해야 합니다.
해결: batch-core가 5개 핵심 Job + 1개 보조 Job으로 운영 안정성을 보장합니다.
월말 23:30 Monthly Usage Precreate → 다음 달 quota row 선생성
월초 00:01 Monthly Usage Reset → 전월 Redis key 정리
매일 03:00 DB-Redis Reconciliation → DB 기준 캐시 무효화
매주 월 00:10 Weekly Family Recap → 주간 가족 리캡 생성
매월 1일 00:20 Monthly Family Recap → 월간 가족 리캡 생성 (주간 스냅샷 재사용)
상시 Event Outbox Publish → usage_event_outbox 후행 발행
설계 포인트: Redis 분산 락 + 기간 파라미터 기반 멱등성, UPSERT/INSERT IGNORE로 재실행 안전, 최종 실패 시 Slack 알람
서비스 구성
Backend Services
서비스
기술 스택
역할
ECS 스펙
api-core
Spring Boot 3.4, Java 21
9개 도메인 REST API (65 endpoints), JWT 인증, 정책 즉시 반영, R2 이미지 업로드
1 vCPU / 2GB, 1~3 replica
processor-usage
Spring Boot / Go
Kafka 소비, Redis Lua 원자 연산, 직접 DB 정산, Outbox 적재
0.5 vCPU / 1GB, 2~5 replica
api-notification
Spring Boot, Java 21
notification-events 소비, SSE 실시간 스트림, Web Push (VAPID), REST 알림 API