Skip to content

[FEAT] 시스템 관리자 기능 구현 #20

@Uechann

Description

@Uechann

[FEAT] 시스템 관리자 기능 구현

📋 이슈 개요

플랫폼 운영을 위한 관리자 기능을 구현합니다. 기관 승인, 리뷰 신고 검토, 회원 관리, 통계 대시보드 등을 제공합니다.

🎯 핵심 구현 목표

✅ 반드시 구현해야 할 기능

  1. 관리자 계정 관리 - 관리자 로그인, 계정 생성/수정/삭제
  2. 기관 승인 관리 - PENDING 기관 검토 및 승인/거부
  3. 리뷰 신고 관리 - 신고된 리뷰 검토 및 처리
  4. 회원 관리 - 회원 조회, 정지, 활성화
  5. 통계 대시보드 - 플랫폼 전체 통계
  6. 관리자 활동 로그 - 모든 관리 작업 기록

📋 전체 API 엔드포인트 목록

Part 1: 관리자 계정 관리

Method Endpoint 설명 권한 상태
POST /api/v1/admin/auth/login 관리자 로그인 공개 ❌ 구현 필요
POST /api/v1/admin/auth/logout 관리자 로그아웃 ADMIN ❌ 구현 필요
POST /api/v1/admin/accounts 관리자 계정 생성 SUPER_ADMIN ❌ 구현 필요
GET /api/v1/admin/accounts 관리자 계정 목록 SUPER_ADMIN ❌ 구현 필요
GET /api/v1/admin/accounts/{adminId} 관리자 계정 조회 SUPER_ADMIN ❌ 구현 필요
PUT /api/v1/admin/accounts/{adminId} 관리자 계정 수정 SUPER_ADMIN ❌ 구현 필요
PATCH /api/v1/admin/accounts/{adminId}/status 활성화 상태 변경 SUPER_ADMIN ❌ 구현 필요
DELETE /api/v1/admin/accounts/{adminId} 관리자 계정 삭제 SUPER_ADMIN ❌ 구현 필요

Part 2: 기관 승인 관리

Method Endpoint 설명 권한 상태
GET /api/v1/admin/institutions/pending 승인 대기 기관 목록 ADMIN ❌ 구현 필요
GET /api/v1/admin/institutions 전체 기관 목록 (필터링) ADMIN ❌ 구현 필요
GET /api/v1/admin/institutions/{institutionId} 기관 상세 조회 (관리자용) ADMIN ❌ 구현 필요
PATCH /api/v1/admin/institutions/{institutionId}/approve 기관 승인 ADMIN ❌ 구현 필요
PATCH /api/v1/admin/institutions/{institutionId}/reject 기관 거부 ADMIN ❌ 구현 필요
DELETE /api/v1/admin/institutions/{institutionId} 기관 강제 삭제 SUPER_ADMIN ❌ 구현 필요

Part 3: 리뷰 신고 관리

Method Endpoint 설명 권한 상태
GET /api/v1/admin/review-reports 리뷰 신고 목록 ADMIN ❌ 구현 필요
GET /api/v1/admin/review-reports/{reportId} 리뷰 신고 상세 ADMIN ❌ 구현 필요
PATCH /api/v1/admin/review-reports/{reportId}/approve 신고 승인 (리뷰 숨김) ADMIN ❌ 구현 필요
PATCH /api/v1/admin/review-reports/{reportId}/reject 신고 거부 (정상 리뷰) ADMIN ❌ 구현 필요
DELETE /api/v1/admin/reviews/{reviewId} 리뷰 강제 삭제 ADMIN ❌ 구현 필요

Part 4: 회원 관리

Method Endpoint 설명 권한 상태
GET /api/v1/admin/members 회원 목록 조회 ADMIN ❌ 구현 필요
GET /api/v1/admin/members/{memberId} 회원 상세 조회 ADMIN ❌ 구현 필요
PATCH /api/v1/admin/members/{memberId}/suspend 회원 정지 ADMIN ❌ 구현 필요
PATCH /api/v1/admin/members/{memberId}/activate 회원 활성화 ADMIN ❌ 구현 필요
DELETE /api/v1/admin/members/{memberId} 회원 강제 탈퇴 SUPER_ADMIN ❌ 구현 필요

Part 5: 통계 대시보드

Method Endpoint 설명 권한 상태
GET /api/v1/admin/dashboard 전체 통계 ADMIN ❌ 구현 필요
GET /api/v1/admin/statistics/institutions 기관 통계 ADMIN ❌ 구현 필요
GET /api/v1/admin/statistics/members 회원 통계 ADMIN ❌ 구현 필요
GET /api/v1/admin/statistics/reservations 예약 통계 ADMIN ❌ 구현 필요

Part 6: 관리자 활동 로그

Method Endpoint 설명 권한 상태
GET /api/v1/admin/action-logs 활동 로그 조회 SUPER_ADMIN ❌ 구현 필요
GET /api/v1/admin/action-logs/admin/{adminId} 특정 관리자 활동 조회 SUPER_ADMIN ❌ 구현 필요

📊 통계

총 API 개수: 30개
✅ 완료: 0개
❌ 구현 필요: 30개

Part별 개수:
- Part 1 (관리자 계정): 8개 (전체 필요)
- Part 2 (기관 승인): 6개 (전체 필요)
- Part 3 (리뷰 신고): 5개 (전체 필요)
- Part 4 (회원 관리): 5개 (전체 필요)
- Part 5 (통계 대시보드): 4개 (전체 필요)
- Part 6 (활동 로그): 2개 (전체 필요)

✅ API 우선순위

1순위 (핵심 기능)

  1. POST /api/v1/admin/auth/login - 관리자 로그인
  2. GET /api/v1/admin/institutions/pending - 승인 대기 기관 목록
  3. PATCH /api/v1/admin/institutions/{institutionId}/approve - 기관 승인
  4. PATCH /api/v1/admin/institutions/{institutionId}/reject - 기관 거부
  5. GET /api/v1/admin/dashboard - 전체 통계

2순위 (관리 기능)

  1. GET /api/v1/admin/review-reports - 리뷰 신고 목록
  2. PATCH /api/v1/admin/review-reports/{reportId}/approve - 신고 승인
  3. GET /api/v1/admin/members - 회원 목록
  4. PATCH /api/v1/admin/members/{memberId}/suspend - 회원 정지

3순위 (부가 기능)

  1. 관리자 계정 CRUD
  2. 활동 로그
  3. 상세 통계

🔐 Part 1: 관리자 계정 관리

구현 필요 (❌)

1. 관리자 로그인

POST /api/v1/admin/auth/login
권한: 공개
입력: accountId, password
응답: JWT 토큰 (accessToken, refreshToken)
검증: ADMIN, SUPER_ADMIN 권한 확인

2. 관리자 계정 생성

POST /api/v1/admin/accounts
권한: SUPER_ADMIN
입력: accountId, password, name, email, phoneNumber, role
검증: accountId, email 중복 체크

3. 관리자 목록 조회

GET /api/v1/admin/accounts
권한: SUPER_ADMIN
필터: role, isActive
페이징: page, size

4. 관리자 계정 수정

PUT /api/v1/admin/accounts/{adminId}
권한: SUPER_ADMIN
수정 가능: name, email, phoneNumber, role

5. 활성화 상태 변경

PATCH /api/v1/admin/accounts/{adminId}/status?isActive=false
권한: SUPER_ADMIN

6. 관리자 계정 삭제

DELETE /api/v1/admin/accounts/{adminId}
권한: SUPER_ADMIN
동작: Soft Delete (isActive = false)

🏥 Part 2: 기관 승인 관리

구현 필요 (❌)

1. 승인 대기 기관 목록

GET /api/v1/admin/institutions/pending
권한: ADMIN
필터: approvalStatus = PENDING
정렬: 신청일시 기준
페이징: page, size
응답: 기관 ID, 기관명, 유형, 소유자 정보, 신청일시

2. 전체 기관 목록 (필터링)

GET /api/v1/admin/institutions
권한: ADMIN
필터: approvalStatus, institutionType, city
검색: name (기관명)
페이징: page, size

3. 기관 상세 조회 (관리자용)

GET /api/v1/admin/institutions/{institutionId}
권한: ADMIN
응답: 기관 모든 정보 + 소유자 정보 + 승인 이력

4. 기관 승인

PATCH /api/v1/admin/institutions/{institutionId}/approve
권한: ADMIN
입력: approvalNote (승인 사유, 선택)
동작:
  - Institution.approvalStatus = APPROVED
  - AdminActionLog 기록
  - 기관 소유자에게 알림 (TODO)

5. 기관 거부

PATCH /api/v1/admin/institutions/{institutionId}/reject
권한: ADMIN
입력: approvalNote (거부 사유, 필수)
동작:
  - Institution.approvalStatus = REJECTED
  - AdminActionLog 기록
  - 기관 소유자에게 알림 (TODO)

6. 기관 강제 삭제

DELETE /api/v1/admin/institutions/{institutionId}
권한: SUPER_ADMIN
동작: Hard Delete 또는 Soft Delete

⭐ Part 3: 리뷰 신고 관리

구현 필요 (❌)

1. 리뷰 신고 목록

GET /api/v1/admin/review-reports
권한: ADMIN
필터: status (PENDING, REVIEWING, APPROVED, REJECTED)
정렬: 신고일시 기준
페이징: page, size
응답:
  - 신고 ID, 리뷰 내용, 별점
  - 신고 사유, 신고자 정보
  - 리뷰 작성자 정보
  - 기관 정보

2. 리뷰 신고 상세 조회

GET /api/v1/admin/review-reports/{reportId}
권한: ADMIN
응답: 신고 정보 + 리뷰 전체 내용 + 신고자/작성자 상세 정보

3. 리뷰 신고 승인 (리뷰 숨김)

PATCH /api/v1/admin/review-reports/{reportId}/approve
권한: ADMIN
입력: reviewNote (검토 의견, 필수)
동작:
  - ReviewReport.status = APPROVED
  - Review.isReported = true, 리뷰 숨김 처리
  - AdminActionLog 기록
  - 리뷰 작성자에게 알림 (TODO)

4. 리뷰 신고 거부 (정상 리뷰)

PATCH /api/v1/admin/review-reports/{reportId}/reject
권한: ADMIN
입력: reviewNote (검토 의견, 필수)
동작:
  - ReviewReport.status = REJECTED
  - Review.isReported = false (정상화)
  - AdminActionLog 기록

5. 리뷰 강제 삭제

DELETE /api/v1/admin/reviews/{reviewId}
권한: ADMIN
동작: Soft Delete

👥 Part 4: 회원 관리

구현 필요 (❌)

1. 회원 목록 조회

GET /api/v1/admin/members
권한: ADMIN
필터: status (ACTIVE, SUSPENDED, DELETED)
검색: name, phoneNumber, email
정렬: 가입일시 기준
페이징: page, size
응답:
  - 회원 ID, 이름, 전화번호, 이메일
  - 성별, 생년월일
  - 상태, 가입일, 마지막 로그인
  - 예약 수, 리뷰 수, 어르신 프로필 수

2. 회원 상세 조회

GET /api/v1/admin/members/{memberId}
권한: ADMIN
응답: 회원 모든 정보 + 어르신 프로필 목록 + 예약/리뷰 통계

3. 회원 정지

PATCH /api/v1/admin/members/{memberId}/suspend
권한: ADMIN
입력:
  - reason (정지 사유, 필수)
  - suspendDays (정지 기간, 1~365일)
동작:
  - Member.status = SUSPENDED
  - Member.suspendUntil = 현재 + suspendDays
  - AdminActionLog 기록
  - 회원에게 알림 (TODO)

4. 회원 활성화 (정지 해제)

PATCH /api/v1/admin/members/{memberId}/activate
권한: ADMIN
동작:
  - Member.status = ACTIVE
  - Member.suspendUntil = null
  - AdminActionLog 기록

5. 회원 강제 탈퇴

DELETE /api/v1/admin/members/{memberId}
권한: SUPER_ADMIN
동작: Soft Delete, 개인정보 마스킹

📊 Part 5: 통계 대시보드

구현 필요 (❌)

1. 대시보드 전체 통계

GET /api/v1/admin/dashboard
권한: ADMIN
응답:
  - 전체 현황
    - 총 기관 수, 활성 기관 수, 승인 대기 기관 수
    - 총 회원 수, 활성 회원 수
    - 총 예약 수, 총 리뷰 수
  
  - 기관 통계
    - 승인 상태별 개수 (PENDING, APPROVED, REJECTED)
    - 기관 유형별 개수
  
  - 회원 통계
    - 상태별 개수 (ACTIVE, SUSPENDED, DELETED)
    - 이번 달 신규 가입자 수
  
  - 예약 통계
    - 상태별 개수 (PENDING, CONFIRMED, COMPLETED, CANCELLED, NO_SHOW)
    - 오늘 예약 건수
  
  - 리뷰 통계
    - 총 리뷰 수, 신고된 리뷰 수
    - 평균 별점

2. 기관 통계

GET /api/v1/admin/statistics/institutions
권한: ADMIN
응답: 기관 관련 상세 통계 (월별, 유형별)

3. 회원 통계

GET /api/v1/admin/statistics/members
권한: ADMIN
응답: 회원 가입 추이 (월별, 일별)

4. 예약 통계

GET /api/v1/admin/statistics/reservations
권한: ADMIN
응답: 예약 추이, 기관별 예약 순위

📝 Part 6: 관리자 활동 로그

구현 필요 (❌)

1. 활동 로그 조회

GET /api/v1/admin/action-logs
권한: SUPER_ADMIN
필터: actionType, targetType, adminId
기간: startDate, endDate
페이징: page, size
응답:
  - 로그 ID, 관리자 이름
  - 작업 유형, 작업 설명
  - 대상 유형, 대상 ID
  - 작업 일시

2. 특정 관리자 활동 조회

GET /api/v1/admin/action-logs/admin/{adminId}
권한: SUPER_ADMIN
응답: 특정 관리자가 수행한 모든 작업 이력

🏗️ 엔티티 구조

SystemAdmin (시스템 관리자)

❌ 신규 생성 필요
- id, accountId, passwordHash
- name, email, phoneNumber
- role (SUPER_ADMIN, ADMIN, VIEWER)
- isActive, lastLoginAt

AdminActionLog (관리자 활동 로그)

❌ 신규 생성 필요
- id, admin (SystemAdmin)
- actionType (Enum)
- targetId, targetType
- actionDescription, details
- createdAt

AdminActionType (Enum)

❌ 신규 생성 필요
- INSTITUTION_APPROVE, INSTITUTION_REJECT
- MEMBER_SUSPEND, MEMBER_ACTIVATE
- REVIEW_REPORT_APPROVE, REVIEW_REPORT_REJECT
- ADMIN_CREATE, ADMIN_UPDATE, ADMIN_DELETE

Member 수정 필요

✅ 이미 존재
추가 필요:
- status (Enum: ACTIVE, SUSPENDED, DELETED)
- suspendUntil (LocalDateTime)

📋 구현 순서

Step 1: Entity 생성 (2일)

  • SystemAdmin Entity 생성
  • SystemAdminRole Enum (SUPER_ADMIN, ADMIN, VIEWER)
  • SystemAdminRepository 구현
  • AdminActionLog Entity 생성
  • AdminActionType Enum 생성
  • AdminActionLogRepository 구현
  • Member Entity에 status, suspendUntil 추가

Step 2: 관리자 Auth (1일)

  • AdminAuthService 구현 (로그인, JWT 발급)
  • AdminAuthController 구현
  • SecurityConfig에 /api/v1/admin/** 경로 설정

Step 3: 관리자 계정 관리 (1일)

  • AdminAccountService 구현
  • AdminAccountController 구현 (6개 API)
  • @PreAuthorize("hasRole('SUPER_ADMIN')") 적용

Step 4: 기관 승인 관리 (2일)

  • InstitutionAdminService 구현
  • InstitutionAdminController 구현 (6개 API)
  • Institution.approve(), reject() 메서드 추가
  • 승인 상태 변경 로직
  • AdminActionLog 기록

Step 5: 리뷰 신고 관리 (2일)

  • ReviewReportAdminService 구현
  • ReviewReportAdminController 구현 (5개 API)
  • Review 숨김/복원 메서드 추가
  • AdminActionLog 기록

Step 6: 회원 관리 (1.5일)

  • MemberAdminService 구현
  • MemberAdminController 구현 (5개 API)
  • Member 정지/활성화 메서드 추가
  • AdminActionLog 기록

Step 7: 통계 대시보드 (2일)

  • 통계 쿼리 작성 (QueryDSL 또는 Native Query)
  • AdminDashboardService 구현
  • AdminDashboardController 구현 (4개 API)
  • Redis 캐싱 적용 (선택)

Step 8: 활동 로그 (1일)

  • AdminActionLogService 구현 (로그 기록/조회)
  • AdminActionLogController 구현 (2개 API)
  • 각 Service에 로그 기록 추가

Step 9: 테스트 및 문서화 (1.5일)

  • Swagger 전체 시나리오 테스트
  • 권한 체크 검증
  • API 문서 정리

예상 기간: 14일 (약 3주)


🚨 핵심 주의사항

  1. 보안

    • 관리자 API는 별도 URL (/api/v1/admin/**)
    • 강력한 비밀번호 정책 적용
    • IP 화이트리스트 검토 (선택)
  2. 권한

    • SUPER_ADMIN: 모든 권한
    • ADMIN: 승인, 신고 검토, 회원 관리
    • VIEWER: 조회만 가능 (선택적 구현)
  3. 로그

    • 모든 중요 작업은 AdminActionLog 기록 필수
    • 삭제/정지 등 중요 작업은 사유 필수
    • 로그는 최소 1년 보관
  4. 성능

    • 통계 대시보드는 Redis 캐싱 고려 (TTL 5분)
    • 대용량 로그는 페이징 처리
  5. 알림

    • 승인/거부/정지 시 대상자에게 알림 (TODO - 알림 기능 구현 후)

📚 참고 파일

생성 필요한 파일

❌ /domain/admin/entity/SystemAdmin.java
❌ /domain/admin/entity/SystemAdminRole.java (Enum)
❌ /domain/admin/entity/AdminActionLog.java
❌ /domain/admin/entity/AdminActionType.java (Enum)
❌ /domain/admin/repository/SystemAdminRepository.java
❌ /domain/admin/repository/AdminActionLogRepository.java
❌ /domain/admin/service/AdminAuthService.java
❌ /domain/admin/service/AdminAccountService.java
❌ /domain/admin/service/InstitutionAdminService.java
❌ /domain/admin/service/ReviewReportAdminService.java
❌ /domain/admin/service/MemberAdminService.java
❌ /domain/admin/service/AdminDashboardService.java
❌ /domain/admin/service/AdminActionLogService.java
❌ /api/admin/controller/AdminAuthController.java
❌ /api/admin/controller/AdminAccountController.java
❌ /api/admin/controller/InstitutionAdminController.java
❌ /api/admin/controller/ReviewReportAdminController.java
❌ /api/admin/controller/MemberAdminController.java
❌ /api/admin/controller/AdminDashboardController.java
❌ /api/admin/controller/AdminActionLogController.java

수정 필요한 파일

🔧 /domain/user/guardian/entity/Member.java (status, suspendUntil 추가)
🔧 /global/security/SecurityConfig.java (admin 경로 추가)

💡 구현 팁

1. 권한 체크

@PreAuthorize("hasRole('ADMIN')")
@PatchMapping("/institutions/{institutionId}/approve")
public ResponseEntity<Void> approveInstitution(...) {}

2. 활동 로그 기록

private void logAdminAction(
    Long adminId,
    AdminActionType actionType,
    String description,
    Long targetId,
    String targetType
) {
    AdminActionLog log = AdminActionLog.builder()
        .admin(systemAdminRepository.getReferenceById(adminId))
        .actionType(actionType)
        .actionDescription(description)
        .targetId(targetId)
        .targetType(targetType)
        .build();
    
    adminActionLogRepository.save(log);
}

3. 통계 쿼리 (QueryDSL)

public DashboardDto getDashboardStats() {
    QInstitution institution = QInstitution.institution;
    QMember member = QMember.member;
    
    // 기관 통계
    Long totalInstitutions = queryFactory
        .select(institution.count())
        .from(institution)
        .where(institution.deleted.eq(false))
        .fetchOne();
    
    Long pendingInstitutions = queryFactory
        .select(institution.count())
        .from(institution)
        .where(
            institution.deleted.eq(false),
            institution.approvalStatus.eq(ApprovalStatus.PENDING)
        )
        .fetchOne();
    
    // ...
}

4. 회원 정지

public void suspendMember(Long adminId, Long memberId, SuspendRequestDto dto) {
    Member member = findById(memberId);
    
    member.suspend(dto.reason(), dto.suspendDays());
    
    logAdminAction(
        adminId,
        AdminActionType.MEMBER_SUSPEND,
        "회원 정지: " + member.getName(),
        memberId,
        "MEMBER"
    );
}

🎯 완료 기준

  • 모든 API가 Swagger에서 정상 동작
  • 권한 체크가 모든 API에 적용됨
  • 기관 승인/거부가 정상 동작함
  • 리뷰 신고 처리가 정상 동작함
  • 회원 정지/활성화가 정상 동작함
  • 통계 대시보드가 정확하게 표시됨
  • 모든 중요 작업에 로그가 남음
  • 로그가 정상적으로 조회됨

📝 담당자

@SongTaeKwon

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions