외부 통계 API 추가

This commit is contained in:
2026-08-12 17:57:35 +09:00
parent 65818cf2ee
commit 06442f8344
15 changed files with 518 additions and 22 deletions

View File

@@ -1,5 +1,13 @@
# 변경사항
## v4.0.23
### 운영 지표 API 추가
통합 대시보드에서 서비스 상태를 확인할 수 있도록 `GET /api/stats`를 추가했습니다.
회원 수, 신규 회원 수, 덱 수, 신규 덱 수, 카드 시리즈 수, 등록 카드 수 같은 집계 정보를 확인할 수 있습니다. 개인정보나 상세 회원 목록은 포함하지 않습니다.
## v4.0.22
### 아이돌마스터 신데렐라 걸즈 추가

View File

@@ -32,6 +32,7 @@ WEB_PORT=44082
APP_BASE_URL=http://localhost:44082
RESEND_API_KEY=Resend_API_Key
RESEND_FROM_EMAIL=UNIARE <인증된_발신주소>
STATS_API_TOKEN=대시보드용_토큰_또는_빈값
```
랜덤 문자열은 `openssl rand -hex 32`로 만들 수 있다.
@@ -65,6 +66,7 @@ CORS_ORIGINS=https://uniare.sori.studio
APP_BASE_URL=https://uniare.sori.studio
RESEND_API_KEY=Resend_API_Key
RESEND_FROM_EMAIL=UNIARE <account@인증된_발신도메인>
STATS_API_TOKEN=대시보드용_긴_랜덤_문자열
```
Resend에서 소유한 도메인 또는 발신용 하위 도메인을 먼저 추가하고 DNS 인증을 완료해야 한다. API Key에는 메일 발송 권한이 필요하며 `.env` 외에는 기록하지 않는다.
@@ -75,6 +77,8 @@ Docker 실행: `docker compose -f docker-compose.prod.yml up -d --build`
API 확인: `curl -fsS http://localhost:44082/api/v1/health`
운영 지표 확인: `curl -fsS http://localhost:44082/api/stats`
정상이면 `{"ok":true,"version":"4.0.16"}`이 표시된다.
이메일 기능 확인:

View File

@@ -1,5 +1,10 @@
# 의사결정 이력
## 2026-08-12 v4.0.23 — 운영 지표는 집계 API로만 공개
💡 통합 대시보드에서 변화를 감지하되 개인 정보와 상세 덱 목록을 외부로 내보내지 않기 위함.
🔧 `/api/stats`와 `/api/v1/stats`에 회원·덱·카드 집계값을 제공하고, `STATS_API_TOKEN` 설정 시 토큰 인증을 적용.
## 2026-07-03 v4.0.21 — 인증 rate limit은 IP 기준 + 프록시 신뢰 1홉
💡 API가 nginx 뒤에만 노출되므로 `trust proxy=1`로 X-Forwarded-For를 신뢰해야 컨테이너 IP가 아닌 실제 클라이언트 IP로 제한이 걸림.

View File

@@ -119,6 +119,10 @@ style/output.css
서버 진입·헬스 체크
api/src/index.js
외부 통계 API
api/src/routes/stats.js
api/src/services/statsService.js
SQLite 스키마·관리자 시드
api/src/db.js

View File

@@ -3,7 +3,7 @@
## 프로젝트 개요
- 서비스명: `UNIARE - Union Arena Deck Builder`
- 현재 버전: `v4.0.22`
- 현재 버전: `v4.0.23`
- 프론트: 정적 HTML, CSS, JavaScript
- 백엔드: Express, SQLite(`better-sqlite3`)
- 운영: Docker Compose 기반 Nginx + API
@@ -208,6 +208,49 @@
| Method | Path | 권한 | 기능 |
|---|---|---|---|
| GET | `/api/v1/health` | 공개 | API 상태와 버전 |
| GET | `/api/stats` | 공개 또는 토큰 | 외부 대시보드용 운영 지표 |
| GET | `/api/v1/stats` | 공개 또는 토큰 | 외부 대시보드용 운영 지표 |
`/api/stats`와 `/api/v1/stats`는 같은 응답을 반환한다. `.env`의 `STATS_API_TOKEN`이 비어 있으면 공개 집계 API로 동작하고, 값이 있으면 `Authorization: Bearer <token>` 또는 `X-Stats-Token: <token>` 헤더가 필요하다. 응답에는 개인정보 없이 집계값만 포함한다.
```json
{
"status": "online",
"ok": true,
"version": "4.0.23",
"lastUpdated": "2026-08-12T00:00:00.000Z",
"members": {
"total": 0,
"active": 0,
"inactive": 0,
"verified": 0,
"unverified": 0,
"created24h": 0,
"latestCreatedAt": null,
"latestLoginAt": null
},
"decks": {
"total": 0,
"userTotal": 0,
"presetTotal": 0,
"publicTotal": 0,
"privateTotal": 0,
"anonymousTotal": 0,
"created24h": 0,
"updated24h": 0,
"totalViews": 0,
"latestCreatedAt": null,
"latestUpdatedAt": null
},
"cards": {
"seriesTotal": 0,
"cardTypesTotal": 0,
"cardPrintsTotal": 0,
"parallelPrintsTotal": 0,
"bySeries": []
}
}
```
### 인증
@@ -274,6 +317,6 @@
- `cardList.html`, `result.html`의 인라인 스크립트가 커서 변경 영향 범위가 넓다.
- `admin.html`은 3개 언어 번역 적용이 완료되지 않았다.
- Homepage 전용 `GET /api/homepage` 엔드포인트는 아직 구현되지 않았다.
- 외부 통계 API는 집계값만 제공하며, 상세 사용자·덱 정보는 포함하지 않는다.
- 현재 Compose의 컨테이너명(`uniare-api`, `uniare-web`)과 데이터 볼륨명(`uniare-data`)은 고정값이며 환경 변수화되지 않았다.
- Resend 발송은 운영 `.env`의 API 키·발신 주소와 Resend에서 인증된 발신 도메인이 필요하다.

View File

@@ -14,7 +14,6 @@
- `admin.html`의 고정 한국어 문구를 `ko`, `ja`, `en` 번역 체계에 연결한다.
- 옆 프로젝트에 `integrations/uadeck-deck-client.js`를 적용하고 실제 공유 덱 조회를 검증한다.
- Homepage 연동이 필요해지면 `GET /api/homepage`와 운영 지표 응답을 구현한다.
## 유지보수

View File

@@ -1,5 +1,17 @@
# 업데이트 이력
## 2026-08-12 / v4.0.23 — 운영 지표 API 추가
### 수행 작업
- 외부 대시보드용 `GET /api/stats`, `GET /api/v1/stats` 추가
- 회원·덱 집계와 카드 시리즈·고유 카드 번호·패러렐 포함 카드 수 집계 추가
- `.env`의 `STATS_API_TOKEN` 설정 시 Bearer 또는 `X-Stats-Token` 인증 적용
- 외부 대시보드 위젯 문서와 API 명세 갱신
### 검증
- 통계 API 라우트 테스트 추가
- API 테스트 전체 실행 예정
## 2026-08-09 / v4.0.22 — UA55 카드 시리즈 추가
### 수행 작업
@@ -223,7 +235,7 @@
- `deploy.md`를 최초 설치·실행·업데이트·백업·롤백 순서의 운영 가이드로 전면 재작성
- `deploy.md`에서 로컬 개발과 NAS 운영을 분리하고 이미지·`datas/`·API 변경별 반영 명령을 구분
- `AGENTS.md` 재검수 결과를 반영해 SQLite WAL 안전 백업·복구 절차와 Compose 고정 이름 제약을 문서화
- Homepage Custom API YAML을 공식 문서 기준으로 재확인하고 참고 URL 추가
- Custom API YAML을 공식 문서 기준으로 재확인하고 참고 URL 추가
- `.cursorrules`의 잘못된 `.AGENTS.md` 참조를 `AGENTS.md`로 수정하고 배포 문서의 개인 로컬 절대 경로를 제거
- `deploy.md`의 중복 설명을 제거하고 초심자가 상황별 절차를 바로 선택할 수 있도록 간소화
- `deploy.md`의 Markdown 표를 제거하고 불필요한 줄바꿈을 줄여 명령 중심으로 재정리

View File

@@ -4,8 +4,9 @@
- 운영 URL: `https://uniare.sori.studio`
- API 상태: `https://uniare.sori.studio/api/v1/health`
- 운영 지표: `https://uniare.sori.studio/api/stats`
- 공유 덱: `https://uniare.sori.studio/api/v1/decks/<shareCode>`
- Homepage 전용 `GET /api/homepage`는 아직 구현되지 않았다.
- `STATS_API_TOKEN`이 설정된 경우 운영 지표 API는 Bearer 토큰 또는 `X-Stats-Token` 헤더가 필요하다.
## 상태 확인
@@ -16,7 +17,7 @@ curl -fsS https://uniare.sori.studio/api/v1/health
```json
{
"ok": true,
"version": "4.0.0"
"version": "4.0.23"
}
```
@@ -26,11 +27,11 @@ curl -fsS https://uniare.sori.studio/api/v1/health
curl -fsS http://localhost:44082/api/v1/health
```
## Homepage 위젯
## 대시보드 위젯
현재 구현된 헬스 API를 사용하는 예시다.
운영 지표 API를 사용하는 예시다.
Homepage Custom API 공식 문서:
Custom API 공식 문서:
```text
https://gethomepage.dev/widgets/services/customapi/
@@ -43,18 +44,92 @@ https://gethomepage.dev/widgets/services/customapi/
description: Union Arena Deck Builder
widget:
type: customapi
url: https://uniare.sori.studio/api/v1/health
url: https://uniare.sori.studio/api/stats
refreshInterval: 30000
mappings:
- field: ok
- field: status
label: 상태
format: text
- field: version
label: 버전
format: text
- field: members.total
label: 회원
format: number
- field: members.created24h
label: 신규 회원 24h
format: number
- field: decks.total
label: 덱
format: number
- field: decks.created24h
label: 신규 덱 24h
format: number
- field: cards.seriesTotal
label: 시리즈
format: number
- field: cards.cardTypesTotal
label: 카드 종류
format: number
```
Docker 내부의 Homepage 컨테이너에서 같은 Compose 네트워크를 사용할 경우 공개 도메인 대신 `http://uniare-web/api/v1/health`를 사용할 수 있다. 서로 다른 Compose 프로젝트라면 공통 외부 네트워크 연결이 필요하다.
Docker 내부의 대시보드 컨테이너에서 같은 Compose 네트워크를 사용할 경우 공개 도메인 대신 `http://uniare-web/api/stats`를 사용할 수 있다. 서로 다른 Compose 프로젝트라면 공통 외부 네트워크 연결이 필요하다.
토큰을 설정한 경우 curl 예시는 다음과 같다.
```bash
curl -fsS \
-H "Authorization: Bearer $STATS_API_TOKEN" \
https://uniare.sori.studio/api/stats
```
응답 예시:
```json
{
"status": "online",
"ok": true,
"version": "4.0.23",
"lastUpdated": "2026-08-12T00:00:00.000Z",
"members": {
"total": 12,
"active": 12,
"inactive": 0,
"verified": 10,
"unverified": 2,
"created24h": 1,
"latestCreatedAt": "2026-08-12 09:00:00",
"latestLoginAt": "2026-08-12T10:00:00.000Z"
},
"decks": {
"total": 34,
"userTotal": 34,
"presetTotal": 0,
"publicTotal": 20,
"privateTotal": 14,
"anonymousTotal": 0,
"created24h": 3,
"updated24h": 5,
"totalViews": 120,
"latestCreatedAt": "2026-08-12 09:30:00",
"latestUpdatedAt": "2026-08-12T10:10:00.000Z"
},
"cards": {
"seriesTotal": 56,
"cardTypesTotal": 5400,
"cardPrintsTotal": 6200,
"parallelPrintsTotal": 800,
"bySeries": [
{
"series": "ua01",
"cardTypes": 90,
"cardPrints": 110,
"parallelPrints": 20
}
]
}
}
```
## 공유 덱 조회
@@ -64,15 +139,13 @@ curl -fsS https://uniare.sori.studio/api/v1/decks/x7Kp9m2Q
브라우저와 Node.js 연동은 `integrations/uadeck-deck-client.js` 또는 `docs/api-integration.md`를 사용한다.
## 운영 지표 제안
## 운영 지표 범위
`GET /api/homepage`를 구현할 때 다음 지표를 우선 제공한다.
현재 운영 지표 API는 다음 집계값을 제공한다.
- API 상태와 현재 버전
- 전체 회원 수
- 전체 덱 수와 공개 덱 수
- 최근 24시간 생성 덱 수
- DB 백업 시각과 성공 여부
- 미리보기·아바타 저장 공간 사용량
- 전체·활성·인증 회원 수, 최근 24시간 신규 회원 수, 최근 가입·접속 시각
- 전체·공개·비공개·익명 덱 수, 최근 24시간 생성·수정 덱 수, 전체 조회 수
- 등록 카드 시리즈 수, 고유 카드 번호 수, 패러렐 포함 카드 수, 시리즈별 카드 수
회원 수나 덱 수처럼 운영 정보가 포함된 엔드포인트는 공개 범위를 검토하고, 필요하면 내부 네트워크 또는 별도 토큰으로 제한한다.
DB 백업 시각과 미리보기·아바타 저장 공간 사용량은 아직 포함하지 않는다.