Skip to content

Develop#469

Merged
minij02 merged 18 commits into
mainfrom
develop
May 16, 2026
Merged

Develop#469
minij02 merged 18 commits into
mainfrom
develop

Conversation

@minij02
Copy link
Copy Markdown
Collaborator

@minij02 minij02 commented May 16, 2026

📌 기능 설명

📌 구현 내용

📌 구현 결과

📌 논의하고 싶은 점

minij02 and others added 18 commits May 16, 2026 23:40
- 관리자가 PENDING 상태의 사업자 판매자 등록 신청을 조회/승인/반려할 수 있도록 4개 엔드포인트 추가
  - GET /api/admin/sellers/pending (페이지네이션 지원)
  - GET /api/admin/sellers/pending/:userId
  - PATCH /api/admin/sellers/pending/:userId/approve
  - DELETE /api/admin/sellers/pending/:userId (status=REJECTED 소프트 삭제)
- authenticateJwt + isAdmin 미들웨어로 관리자 권한 강제
- .gitignore에 .omc/ 추가

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: 사업자 판매자 승인 대기 관리 API 구현
- 승인 완료(APPROVED) 상태 판매자를 개인/사업자 별로 분리 조회
  - GET /api/admin/sellers/individual (실명·이메일·정산계좌 + 페이지네이션)
  - GET /api/admin/sellers/business (프로필·닉네임·실명·이메일·정산계좌 + 페이지네이션)
- search 쿼리 파라미터: 실명/이메일/닉네임 부분 일치 검색
- 정렬: created_at DESC (가입 최신순)
- authenticateJwt + isAdmin 미들웨어 적용

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: 관리자 판매자 목록 조회 및 검색 API 구현
- 승인 완료(APPROVED) 판매자의 등록 폼 상세 정보 조회
  - GET /api/admin/sellers/individual/:userId
    (프로필·닉네임·실명·이메일·정산계좌·등록유형)
  - GET /api/admin/sellers/business/:userId
    (위 + 사업자등록번호·대표자명·상호명·사업자등록증 URL)
- 개인/사업자 분리 응답 DTO로 타입 안전성 확보
- authenticateJwt + isAdmin 미들웨어 적용

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: 관리자 판매자 상세 조회 API 구현
- DELETE /api/admin/sellers/:userId
  - 승인 완료(APPROVED) 상태 판매자(개인/사업자) 공통 처리
  - 트랜잭션으로 두 작업 수행:
    1) 사용자의 활성 프롬프트 일괄 비활성화 (inactive_date=now())
    2) SettlementAccount 하드 삭제
  - 기존 구매/정산 이력은 영향 없음
  - 응답에 비활성화된 프롬프트 개수 반환
- authenticateJwt + isAdmin 미들웨어 적용

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: 관리자 판매자 등록 취소 API 구현
- GET /api/admin/stats/members
  - 총 회원수 (userstatus=deleted 제외)
  - 가입 경로별 분포: email(NONE) / google / kakao / naver
  - 채널별 count와 ratio(0~1, 소수 4자리) 반환
- 신규 모듈 src/stats/ 구성 (controllers/services/repositories/dtos/routes)
- /api/admin/stats 경로에 라우터 마운트
- authenticateJwt + isAdmin 미들웨어 적용

방문자/활성 사용자 지표는 추적 인프라 부재로 별도 이슈 #461, #462로 분리.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: 관리자 회원 가입 현황 통계 API 구현
- GET /api/admin/stats/prompts/new
  - daily_count: 최근 24시간(롤링) 업로드 수
  - weekly_count: 최근 7일 KST 캘린더 기준 합계
  - daily_uploads: 7일치 일자별 업로드 수 (막대 그래프용)
  - 비활성(inactive_date IS NOT NULL) 프롬프트 제외
- GET /api/admin/stats/prompts/top-sales
  - 최근 30일 Purchase.amount 합계 기준 Top 5
  - is_free=false 만 집계
  - 삭제·비활성 프롬프트도 매출 집계 포함 (title 없으면 null)
- authenticateJwt + isAdmin 미들웨어 적용

인기 프롬프트(최근 7일 조회+다운수)는 누적 카운터 한계로 별도 이슈 #464로 분리.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: 관리자 신규/매출 상위 프롬프트 통계 API 구현
- User.last_active_at 컬럼 추가 (Prisma migration 포함)
- src/utils/user-activity.ts: Redis 5분 throttle로 last_active_at 갱신
  - SET NX EX 300 으로 throttle 키 원자적 획득, 성공 시에만 DB UPDATE
  - 실패 시 로깅 후 silent fail (인증 흐름 방해 금지)
- passport JWT verify 콜백에서 fire-and-forget으로 활동 기록
- GET /api/admin/stats/active-users
  - window_days: 30 (롤링)
  - current_count: now-30d ~ now
  - previous_count: now-60d ~ now-30d
  - change_rate: 소수 4자리, 이전 구간 0이면 null
  - userstatus=deleted 제외
- authenticateJwt + isAdmin 미들웨어 적용

배포 시 `pnpm prisma migrate deploy` 필요.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: 활성 사용자 추적 인프라 및 통계 API 구현
- 인프라
  - src/utils/visitor-tracking.ts
    - Redis HyperLogLog 일별 키(visitors:hll:YYYY-MM-DD, KST)
    - PFADD로 visitor_id 누적, 400일 TTL
    - 봇 UA 필터 (정규식 매칭)
    - 로그인 시 user_id, 비로그인 시 SHA-256(IP + VISITOR_HASH_SALT) 24글자 해시
  - src/middlewares/visitorTracker.ts
    - 모든 /api 요청에 mount, /health /api-docs /uploads /sse 제외
    - OPTIONS/HEAD 제외, 봇 UA 제외
    - res.on(finish) 훅으로 인증 후 visitor_id 확정 후 기록
    - 4xx/5xx 응답은 카운트 제외

- API
  - GET /api/admin/stats/visitors
    - daily_count: 오늘 KST 고유 방문자
    - current_count: 최근 30일 롤링 합집합
    - previous_count: 그 이전 30일 (now-60d ~ now-30d)
    - change_rate: 소수 4자리, previous=0이면 null
    - ?month=YYYY-MM 지정 시 month_total + month_daily 추가 반환
  - authenticateJwt + isAdmin 적용
  - YYYY-MM 형식 검증 (잘못된 형식 시 400)

배포 환경에 VISITOR_HASH_SALT 환경변수 추가 권장 (없어도 동작하나 보안 강화 목적).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: 방문자 추적 인프라 및 통계 API 구현
- 신규 테이블 PromptStatDaily (prompt_id, snapshot_date, views, downloads)
  - 유니크 (prompt_id, snapshot_date), index (snapshot_date)
  - Prisma migration 포함
- 일일 스냅샷 cron (node-cron, Asia/Seoul 00:00)
  - 매일 모든 프롬프트의 누적 views/downloads를 snapshot
  - 90일 초과 데이터 자동 cleanup
  - 서버 부팅 시 오늘 스냅샷 없으면 즉시 1회 실행 (ensureTodaySnapshot)
- GET /api/admin/stats/prompts/popular
  - 7일 전 KST 스냅샷과 현재값의 차분으로 score 계산
  - score = views_delta + downloads_delta, 상위 5개
  - 활성 프롬프트(inactive_date IS NULL)만 포함
  - 7일 전 스냅샷 없는 신규 프롬프트는 baseline=0으로 산정
- node-cron + @types/node-cron 의존성 추가
- authenticateJwt + isAdmin 미들웨어 적용

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat: 프롬프트 일일 스냅샷 인프라 및 인기 프롬프트 API 구현
@minij02 minij02 self-assigned this May 16, 2026
@minij02 minij02 merged commit 03fa2d0 into main May 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant