Skip to content

tmrdanny/taghere-analytics

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

55 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

TagHere Analytics Dashboard

MongoDB 기반 B2B λ§€μž₯ 뢄석 λŒ€μ‹œλ³΄λ“œ - 운영 DB 쑰회 λΉ„μš©μ„ μ΅œμ†Œν™”ν•œ κ³ μ„±λŠ₯ 뢄석 ν”Œλž«νΌ

🎯 ν”„λ‘œμ νŠΈ λͺ©ν‘œ

  • MongoDB 쑰회 λΉ„μš© 거의 0: 사전 집계(pre-aggregation) μ „λž΅μœΌλ‘œ 운영 DB 직접 쑰회 차단
  • λ°˜μ‘ν˜• SaaSκΈ‰ UI: λͺ¨λ°”일/PC 지원, Stripe/NotionκΈ‰μ˜ λ―Έλ‹ˆλ©€ν•œ λŒ€μ‹œλ³΄λ“œ
  • μ‹€μ‹œκ°„ KPI: λ§€μž₯별 GMV, κ²°μ œμ•‘, μ£Όλ¬Έ 수, 메뉴 νŒλ§€λŸ‰ λ“± 핡심 μ§€ν‘œ 제곡

πŸ“Š μ£Όμš” κΈ°λŠ₯

λŒ€μ‹œλ³΄λ“œ KPI

  • βœ… 총 GMV (Gross Merchandise Value): 전체 κ±°λž˜μ•‘
  • βœ… 결제 성곡앑: μ‹€μ œ 결제 μ™„λ£Œ κΈˆμ•‘
  • βœ… μ£Όλ¬Έ 수: 전체 μ£Όλ¬Έ 건수
  • βœ… 객단가 (AOV): 평균 μ£Όλ¬Έ κΈˆμ•‘
  • βœ… ν™œμ„± λ§€μž₯ 수: κΈ°κ°„ λ‚΄ 주문이 μžˆλŠ” λ§€μž₯ 수
  • βœ… 결제 성곡λ₯ : 결제 성곡/μ‹€νŒ¨ λΉ„μœ¨

뢄석 κΈ°λŠ₯

  • πŸ“ˆ μ‹œκ³„μ—΄ 차트: 일별 GMV/κ²°μ œμ•‘ νŠΈλ Œλ“œ
  • πŸͺ λ§€μž₯ λž­ν‚Ή: GMV κΈ°μ€€ Top λ§€μž₯
  • πŸ” 메뉴 λž­ν‚Ή: νŒλ§€λŸ‰/맀좜 κΈ°μ€€ 인기 메뉴
  • πŸ” λ‚ μ§œ ν•„ν„°: 였늘/7일/30일/μ΄λ²ˆλ‹¬/μ§€λ‚œλ‹¬/μ»€μŠ€ν…€

πŸ—οΈ μ•„ν‚€ν…μ²˜

λΉ„μš© μ΅œμ†Œν™” μ „λž΅

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  운영 MongoDB   β”‚  ← μ ˆλŒ€ 직접 쑰회 κΈˆμ§€!
β”‚  (orders, ...)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β”‚ 배치 집계 (μ£Ό 1회)
         ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 사전 집계 μ»¬λ ‰μ…˜ β”‚  ← λŒ€μ‹œλ³΄λ“œλŠ” μ—¬κΈ°λ§Œ 쑰회
β”‚ (metrics_*)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β”‚ μΊμ‹œ (5λΆ„ TTL)
         ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Dashboard API  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

사전 집계 μ»¬λ ‰μ…˜

  1. metrics_daily_store: 일별 λ§€μž₯ λ©”νŠΈλ¦­

    • storeId, date, gmv, paidAmount, orderCount, avgOrderValue, paymentSuccessRate
  2. metrics_daily_store_menu: 일별 λ§€μž₯-메뉴 λ©”νŠΈλ¦­

    • storeId, menuId, date, quantity, revenue, orderCount
  3. metrics_hourly_store (선택): μ‹œκ°„λ³„ λ§€μž₯ λ©”νŠΈλ¦­ (히트맡용)

    • storeId, datetime, hour, dayOfWeek, gmv, orderCount

πŸš€ μ‹œμž‘ν•˜κΈ°

1. ν™˜κ²½ μ„€μ •

# μ˜μ‘΄μ„± μ„€μΉ˜
npm install

# ν™˜κ²½ λ³€μˆ˜ μ„€μ •
cp .env.example .env.local

.env.local νŒŒμΌμ— MongoDB μ—°κ²° 정보 μž…λ ₯:

MONGODB_URI=mongodb+srv://<username>:<password>@<cluster>.mongodb.net/<database>
MONGODB_DB_NAME=your_database_name

# 선택: 읽기 μ „μš© μ—°κ²°
MONGODB_READONLY_URI=mongodb+srv://readonly_user:...

# μΊμ‹œ μ„€μ •
CACHE_TTL_SECONDS=300

# λ‚ μ§œ λ²”μœ„ μ œν•œ
MAX_DATE_RANGE_DAYS=180

# 배치 집계 μ£ΌκΈ° (일 λ‹¨μœ„)
BATCH_INCREMENTAL_DAYS=7

2. μŠ€ν‚€λ§ˆ 탐색

μ‹€μ œ μ»¬λ ‰μ…˜ ꡬ쑰λ₯Ό νŒŒμ•…ν•˜κΈ° μœ„ν•΄ μ•ˆμ „ν•œ μŠ€ν‚€λ§ˆ 탐색 도ꡬ μ‹€ν–‰:

npm run dev

λΈŒλΌμš°μ €μ—μ„œ http://localhost:3000/explore 접속

  1. "Load Collections" 클릭
  2. μ£Όλ¬Έ/결제 κ΄€λ ¨ μ»¬λ ‰μ…˜ 선택
  3. ν•„λ“œ ꡬ쑰 확인 (storeId, createdAt, totalAmount, items λ“±)

3. μ†ŒμŠ€ μ»¬λ ‰μ…˜ μ„€μ •

lib/aggregation/pipeline.ts의 SourceCollections λ˜λŠ” ν™˜κ²½ λ³€μˆ˜λ‘œ μ‹€μ œ μ»¬λ ‰μ…˜λͺ… μ§€μ •:

COLLECTION_ORDERS=orders
COLLECTION_PAYMENTS=payments
COLLECTION_MENUS=menus

4. 인덱슀 생성

λ©”νŠΈλ¦­ μ»¬λ ‰μ…˜μ˜ 인덱슀λ₯Ό 생성 (졜초 1회):

npm run setup-indexes

5. 배치 집계 μ‹€ν–‰

λ©”νŠΈλ¦­ 데이터 생성:

npm run aggregate

6. λŒ€μ‹œλ³΄λ“œ μ‹€ν–‰

npm run dev

http://localhost:3000 μ ‘μ†ν•˜μ—¬ λŒ€μ‹œλ³΄λ“œ 확인

πŸ“¦ 배치 집계 μŠ€μΌ€μ€„λ§

Cron (Linux/Mac)

# λ§€μ£Ό μ›”μš”μΌ μ˜€μ „ 0μ‹œμ— μ‹€ν–‰
0 0 * * 1 cd /path/to/project && npm run aggregate >> /var/log/aggregation.log 2>&1

GitHub Actions

.github/workflows/aggregate.yml:

name: Weekly Aggregation

on:
  schedule:
    - cron: '0 0 * * 1'  # λ§€μ£Ό μ›”μš”μΌ 00:00 UTC
  workflow_dispatch:      # μˆ˜λ™ μ‹€ν–‰ κ°€λŠ₯

jobs:
  aggregate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '20'
      - run: npm install
      - run: npm run aggregate
        env:
          MONGODB_URI: ${{ secrets.MONGODB_URI }}
          MONGODB_DB_NAME: ${{ secrets.MONGODB_DB_NAME }}

πŸ”’ λ³΄μ•ˆ & μ„±λŠ₯ 원칙

μ ˆλŒ€ κ·œμΉ™

  1. βœ… 운영 μ»¬λ ‰μ…˜ 직접 쑰회 κΈˆμ§€

    • λŒ€μ‹œλ³΄λ“œ APIλŠ” 였직 metrics_* μ»¬λ ‰μ…˜λ§Œ 쑰회
    • 배치 μ§‘κ³„λ§Œ 운영 μ»¬λ ‰μ…˜ μ ‘κ·Ό ν—ˆμš©
  2. βœ… 인덱슀 기반 쿼리

    • λͺ¨λ“  μΏΌλ¦¬λŠ” 인덱슀 μ‚¬μš© ν•„μˆ˜
    • explain()으둜 μ‹€ν–‰ κ³„νš 검증
  3. βœ… λ‚ μ§œ λ²”μœ„ μ œν•œ

    • μ΅œλŒ€ 180일둜 μ œν•œ (ν™˜κ²½ λ³€μˆ˜λ‘œ μ‘°μ • κ°€λŠ₯)
  4. βœ… 캐싱 ν•„μˆ˜

    • λͺ¨λ“  λŒ€μ‹œλ³΄λ“œ API 응닡 μΊμ‹œ (κΈ°λ³Έ 5λΆ„)
  5. βœ… Projection μ‚¬μš©

    • ν•„μš”ν•œ ν•„λ“œλ§Œ 쑰회

πŸ“ ν”„λ‘œμ νŠΈ ꡬ쑰

taghere-analytics/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ page.tsx              # 메인 λŒ€μ‹œλ³΄λ“œ
β”‚   β”œβ”€β”€ explore/page.tsx      # μŠ€ν‚€λ§ˆ 탐색 UI
β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”œβ”€β”€ dashboard/route.ts  # λŒ€μ‹œλ³΄λ“œ API
β”‚   β”‚   └── explore/route.ts    # μŠ€ν‚€λ§ˆ 탐색 API
β”‚   └── layout.tsx
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ mongodb.ts            # MongoDB μ—°κ²°
β”‚   β”œβ”€β”€ cache.ts              # 인메λͺ¨λ¦¬ μΊμ‹œ
β”‚   β”œβ”€β”€ schema-explorer.ts    # μ•ˆμ „ν•œ μŠ€ν‚€λ§ˆ 탐색
β”‚   β”œβ”€β”€ types/
β”‚   β”‚   └── metrics.ts        # λ©”νŠΈλ¦­ νƒ€μž… μ •μ˜
β”‚   β”œβ”€β”€ queries/
β”‚   β”‚   └── dashboard.ts      # λŒ€μ‹œλ³΄λ“œ 쿼리 (metrics μ „μš©)
β”‚   └── aggregation/
β”‚       └── pipeline.ts       # 배치 집계 νŒŒμ΄ν”„λΌμΈ
β”œβ”€β”€ scripts/
β”‚   └── run-aggregation.ts    # 배치 μ‹€ν–‰ 슀크립트
β”œβ”€β”€ components/ui/            # shadcn/ui μ»΄ν¬λ„ŒνŠΈ
└── README.md

πŸ› οΈ μ£Όμš” λͺ…λ Ήμ–΄

npm run dev          # 개발 μ„œλ²„ μ‹œμž‘
npm run build        # ν”„λ‘œλ•μ…˜ λΉŒλ“œ
npm run start        # ν”„λ‘œλ•μ…˜ μ„œλ²„ μ‹œμž‘

npm run aggregate    # 배치 집계 μ‹€ν–‰ (증뢄)
npm run setup-indexes # 인덱슀 생성 (졜초 1회)

πŸ” μŠ€ν‚€λ§ˆ μš”κ΅¬μ‚¬ν•­

μ£Όλ¬Έ μ»¬λ ‰μ…˜ (orders)

{
  _id: ObjectId,
  storeId: string,           // ν•„μˆ˜
  storeName: string,         // 선택
  createdAt: Date,           // ν•„μˆ˜
  totalAmount: number,       // ν•„μˆ˜
  status: string,            // ν•„μˆ˜ (cancelled μ œμ™Έ)
  items: [                   // ν•„μˆ˜ (메뉴 λΌμΈμ•„μ΄ν…œ)
    {
      menuId: string,
      menuName: string,
      quantity: number,
      price: number
    }
  ]
}

결제 μ»¬λ ‰μ…˜ (payments)

{
  _id: ObjectId,
  orderId: string,           // 선택
  storeId: string,           // ν•„μˆ˜
  amount: number,            // ν•„μˆ˜
  status: string,            // ν•„μˆ˜ ('success' | 'failed')
  paidAt: Date               // ν•„μˆ˜
}

🚒 배포

Vercel

vercel

ν™˜κ²½ λ³€μˆ˜ 섀정은 Vercel Dashboardμ—μ„œ μΆ”κ°€

Docker

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]

πŸ†˜ 문제 ν•΄κ²°

"Failed to connect to MongoDB"

  • .env.local의 MONGODB_URI 확인
  • MongoDB Atlas의 IP ν—ˆμš© λͺ©λ‘ 확인

"No data in dashboard"

  1. 배치 집계 μ‹€ν–‰ 확인: npm run aggregate
  2. λ©”νŠΈλ¦­ μ»¬λ ‰μ…˜ 쑴재 확인
  3. λ‚ μ§œ λ²”μœ„ 확인

"Slow queries"

  1. 인덱슀 생성 확인: npm run setup-indexes
  2. μΊμ‹œ TTL 확인
  3. λ‚ μ§œ λ²”μœ„ μΆ•μ†Œ

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages