- DB 테이블: activity_logs → logs - 문서: activity-logs.md → logs.md - 컴포넌트: ActivityLogs.jsx → Logs.jsx - 라우트 import 업데이트 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
197 lines
7.1 KiB
Markdown
197 lines
7.1 KiB
Markdown
# 활동 로그 시스템
|
|
|
|
## 개요
|
|
|
|
관리자 페이지에서 모든 행동(관리자 수동 작업 + 봇 자동 작업)에 대한 로그를 조회할 수 있는 시스템.
|
|
앨범 CRUD, 멤버 수정, 일정 추가/수정/삭제, 봇 동기화 등 모든 활동을 DB에 기록하고 관리자 페이지에서 필터링/페이지네이션으로 조회.
|
|
|
|
---
|
|
|
|
## DB 테이블
|
|
|
|
### `activity_logs`
|
|
|
|
```sql
|
|
CREATE TABLE activity_logs (
|
|
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
actor VARCHAR(50) NOT NULL, -- "admin" 또는 봇 ID ("youtube-3", "x-1" 등)
|
|
action VARCHAR(50) NOT NULL, -- create, update, delete, start, stop, sync_complete, error 등
|
|
category VARCHAR(30) NOT NULL, -- album, schedule, member, bot, category, dict, concert, sync
|
|
target_type VARCHAR(50) DEFAULT NULL, -- youtube_schedule, x_schedule, album, photo, member 등
|
|
target_id INT UNSIGNED DEFAULT NULL,
|
|
summary VARCHAR(500) NOT NULL, -- 사람이 읽을 수 있는 한 줄 요약
|
|
details JSON DEFAULT NULL, -- 추가 상세 정보
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
INDEX idx_created_at (created_at),
|
|
INDEX idx_category (category),
|
|
INDEX idx_actor (actor)
|
|
);
|
|
```
|
|
|
|
### 컬럼 설명
|
|
|
|
| 컬럼 | 설명 | 예시 |
|
|
|------|------|------|
|
|
| `actor` | 행위자 | `"admin"`, `"youtube-3"`, `"x-1"`, `"meilisearch"` |
|
|
| `action` | 행동 유형 | `create`, `update`, `delete`, `upload`, `start`, `stop`, `sync_complete`, `error`, `reorder` |
|
|
| `category` | 대분류 | `album`, `schedule`, `member`, `bot`, `category`, `dict`, `concert`, `sync` |
|
|
| `target_type` | 대상 타입 | `youtube_schedule`, `x_schedule`, `album`, `photo`, `teaser`, `member`, `youtube_bot`, `x_bot`, `category`, `concert` |
|
|
| `target_id` | 대상 DB ID | 해당 레코드의 PK |
|
|
| `summary` | 한 줄 요약 | `"YouTube 일정 생성: fromis_9 영상 제목"` |
|
|
| `details` | 추가 정보 (JSON) | `{ "videoId": "abc123", "channelName": "채널명" }` |
|
|
|
|
---
|
|
|
|
## 백엔드 구현
|
|
|
|
### 로그 유틸리티
|
|
|
|
**파일:** `backend/src/utils/activityLog.js`
|
|
|
|
```javascript
|
|
logActivity(db, { actor, action, category, targetType, targetId, summary, details })
|
|
```
|
|
|
|
- fire-and-forget: 로그 실패가 비즈니스 로직에 영향 주지 않도록 try/catch 감싸기
|
|
- 트랜잭션 외부에서 호출 (로그 실패가 롤백 유발하지 않도록)
|
|
|
|
### API 엔드포인트
|
|
|
|
**GET /api/admin/activity-logs** — 로그 목록 조회 (인증 필수)
|
|
|
|
| 파라미터 | 타입 | 기본값 | 설명 |
|
|
|----------|------|--------|------|
|
|
| `page` | integer | 1 | 페이지 번호 |
|
|
| `limit` | integer | 50 | 페이지당 개수 (최대 100) |
|
|
| `category` | string | - | 카테고리 필터 (콤마 구분) |
|
|
| `actor` | string | - | 행위자 필터 (`"admin"` 또는 `"bot"`) |
|
|
| `search` | string | - | summary 검색 |
|
|
| `from` | string | - | 시작 날짜 (YYYY-MM-DD) |
|
|
| `to` | string | - | 종료 날짜 (YYYY-MM-DD) |
|
|
|
|
**응답:**
|
|
```json
|
|
{
|
|
"logs": [
|
|
{
|
|
"id": 1,
|
|
"actor": "admin",
|
|
"action": "create",
|
|
"category": "schedule",
|
|
"target_type": "youtube_schedule",
|
|
"target_id": 456,
|
|
"summary": "YouTube 일정 생성: fromis_9 영상 제목",
|
|
"details": { "videoId": "abc123", "channelName": "채널명" },
|
|
"created_at": "2026-03-01T14:30:00"
|
|
}
|
|
],
|
|
"total": 1234,
|
|
"page": 1,
|
|
"limit": 50,
|
|
"totalPages": 25
|
|
}
|
|
```
|
|
|
|
### 로그 삽입 대상
|
|
|
|
#### 관리자 수동 작업
|
|
|
|
| 파일 | 로그 대상 |
|
|
|------|----------|
|
|
| `routes/admin/youtube.js` | YouTube 일정 생성/수정 |
|
|
| `routes/admin/x.js` | X 일정 생성 |
|
|
| `routes/admin/concert.js` | 콘서트 일정 생성 |
|
|
| `routes/admin/youtube-bots.js` | YouTube 봇 생성/수정/삭제 |
|
|
| `routes/admin/x-bots.js` | X 봇 생성/수정/삭제 |
|
|
| `routes/admin/bots.js` | 봇 시작/정지/전체동기화 |
|
|
| `routes/albums/index.js` | 앨범 생성/수정/삭제 |
|
|
| `routes/albums/photos.js` | 사진 업로드/삭제 |
|
|
| `routes/albums/teasers.js` | 티저 삭제 |
|
|
| `routes/members/index.js` | 멤버 수정 |
|
|
| `routes/schedules/index.js` | 일정 삭제, 카테고리 CRUD, 순서변경 |
|
|
| `routes/schedules/suggestions.js` | 사전 저장 |
|
|
|
|
#### 봇 자동 작업
|
|
|
|
| 파일 | 로그 대상 |
|
|
|------|----------|
|
|
| `plugins/scheduler.js` | 동기화 완료 (addedCount > 0일 때만), 에러 |
|
|
| `services/youtube/index.js` | 영상 추가 성공 |
|
|
| `services/x/index.js` | 트윗 추가 성공 |
|
|
|
|
> **봇 로그 전략:** 변화 없는 동기화는 로그 안 남김. `addedCount > 0`이거나 에러인 경우만 기록.
|
|
|
|
---
|
|
|
|
## 프론트엔드 구현
|
|
|
|
### 로그 페이지
|
|
|
|
**경로:** `/admin/logs`
|
|
|
|
**UI 구성:**
|
|
- 필터 바: 카테고리 칩, 행위자 드롭다운, 기간 선택, 텍스트 검색
|
|
- 로그 테이블: 시간, 행위자(아이콘), 액션 뱃지(색상별), summary
|
|
- 페이지네이션
|
|
|
|
**액션 뱃지 색상:**
|
|
| 액션 | 색상 |
|
|
|------|------|
|
|
| create / upload | 초록 |
|
|
| update / reorder | 파랑 |
|
|
| delete | 빨강 |
|
|
| sync_complete | 보라 |
|
|
| error | 빨강 |
|
|
| start / stop | 노랑 |
|
|
|
|
### 대시보드 메뉴
|
|
|
|
대시보드 menuItems에 활동 로그 항목 추가 (ScrollText 아이콘)
|
|
|
|
---
|
|
|
|
## 수정 파일 목록
|
|
|
|
### 신규 생성 (4개)
|
|
|
|
| 파일 | 내용 |
|
|
|------|------|
|
|
| `backend/src/utils/activityLog.js` | logActivity 유틸리티 함수 |
|
|
| `backend/src/routes/admin/activity-logs.js` | API 엔드포인트 |
|
|
| `frontend/src/api/admin/activityLogs.js` | API 클라이언트 |
|
|
| `frontend/src/pages/pc/admin/logs/ActivityLogs.jsx` | 로그 페이지 컴포넌트 |
|
|
|
|
### 수정 (백엔드 15개 + 프론트엔드 3개)
|
|
|
|
| 파일 | 변경 |
|
|
|------|------|
|
|
| `backend/src/routes/index.js` | 라우트 등록 |
|
|
| `backend/src/routes/admin/youtube.js` | logActivity 호출 |
|
|
| `backend/src/routes/admin/x.js` | logActivity 호출 |
|
|
| `backend/src/routes/admin/concert.js` | logActivity 호출 |
|
|
| `backend/src/routes/admin/youtube-bots.js` | logActivity 호출 |
|
|
| `backend/src/routes/admin/x-bots.js` | logActivity 호출 |
|
|
| `backend/src/routes/admin/bots.js` | logActivity 호출 |
|
|
| `backend/src/routes/albums/index.js` | logActivity 호출 |
|
|
| `backend/src/routes/albums/photos.js` | logActivity 호출 |
|
|
| `backend/src/routes/albums/teasers.js` | logActivity 호출 |
|
|
| `backend/src/routes/members/index.js` | logActivity 호출 |
|
|
| `backend/src/routes/schedules/index.js` | logActivity 호출 |
|
|
| `backend/src/routes/schedules/suggestions.js` | logActivity 호출 |
|
|
| `backend/src/plugins/scheduler.js` | 동기화 로그 |
|
|
| `backend/src/services/youtube/index.js` | 영상 추가 로그 |
|
|
| `backend/src/services/x/index.js` | 트윗 추가 로그 |
|
|
| `frontend/src/api/admin/index.js` | export 추가 |
|
|
| `frontend/src/routes/pc/admin/index.jsx` | 라우트 등록 |
|
|
| `frontend/src/pages/pc/admin/dashboard/Dashboard.jsx` | 메뉴 추가 |
|
|
|
|
---
|
|
|
|
## 구현 순서
|
|
|
|
1. DB 테이블 생성
|
|
2. 백엔드: logActivity 유틸리티 + API 엔드포인트 + 라우트 등록
|
|
3. 백엔드: 각 라우트/서비스에 logActivity 호출 추가
|
|
4. 프론트엔드: API 클라이언트 + 로그 페이지 + 라우트/대시보드 연결
|
|
5. 서버 재빌드 + 테스트
|
|
6. 문서 업데이트
|