배경
관리자/교직원/개발자 대시보드 화면(Figma node 942:21779/942:20791/942:21970)이 PR #81로 이미 구현되어 있으나, KPI 카드·표·알림 데이터가 전부 하드코딩된 Mock이다 — 실제 API 연동이 전혀 시도되지 않았다.
Client 근거
GETI-Client-V1(develop, 078388a) src/views/admin-dashboard/model/mock.ts — DASHBOARD_CONTENT 전체가 정적 상수(관리자/교직원/개발자 3종).
src/views/admin-dashboard/ui/AdminDashboardPage.tsx — content: DashboardContent를 Props로만 받아 그대로 렌더링할 뿐, 어떤 Query Hook도 호출하지 않는다.
Widget별 필요 Metric (Client Mock 기준, 추측 아님)
관리자: 가입 승인 대기(교직원) 건수 · 전체 지원(서) 건수 · 공고 상세(모집/마감/비공개) 건수 · 프로그램 상태(진행/예정/종료) 건수 · 미답변 문의 건수 · 전체 지원 처리 현황 표(제출완료/검토중/수정요청 건수·비율) · 최근 운영 상태(공고·프로그램·미답변 문의 요약).
교직원: 신규 지원자 건수 · 수정요청 지원서 건수 · 기업 전달 대기 건수 · 진행 중 프로그램 건수 · 포트폴리오 미제출(기한 경과) 건수 · 담당 공고 현황 표(공고별 지원자·처리대기·상태) · 최근 알림 3종.
개발자: 정상 시스템 건수 · Discord 전송 실패 건수 · 정기 작업 실패 건수 · 외부 공고 수집 실패 건수 · 미처리 오류 문의 건수 · 최근 실패 내역 표 · 최근 운영 알림.
확정 계약
기준 시각/기간을 아래와 같이 확정한다(Client Mock의 "최근 7일" 표기는 아래 값으로 대체한다 — CLIENT_CONTRACT_ALIGNMENT_REQUIRED: 화면 문구를 실제 값에 맞게 정리해야 한다).
| Metric |
기준 |
상태 |
| 신규 지원자 |
최근 3일(JobApplication 생성 시각 기준) |
CONFIRMED |
| Discord 전송 실패 |
최근 24시간 |
REUSE_EXISTING_API — GET /api/v1/admin/discord-deliveries?status=FAILED(Issue #206/PR #213, Merge 완료)의 totalElements에 기간 Filter만 추가하면 된다 |
| 정기 작업 실패 |
최근 24시간 |
BLOCKED — #227(Scheduler 통합 조회 계약)이 먼저 확정/구현되어야 한다 |
| 외부 공고 수집 실패 |
최근 24시간 |
REUSE_EXISTING_API — 기존 Collector 실행 이력 조회 재사용(Issue #227과 조회 계층을 공유할 수 있는지 구현 시 확인) |
| 가입 승인 대기 |
현재 값 |
REUSE_EXISTING_API — GET /api/v1/admin/members/search?status=PENDING&role=TEACHER의 totalElements(Issue #183/PR #216) |
| 공고/프로그램/문의 상태별 건수 |
현재 값 |
REUSE_EXISTING_API — 각 목록 Endpoint의 상태별 totalElements 반복 조회 |
| 지원 처리 현황(상태별) |
현재 값 |
REUSE_EXISTING_API — JobApplicationAdminServiceImpl.list의 기존 status Filter |
| 기업 전달 대기 |
- |
EXCLUDE — docs/application/application-domain-plan.md(§1.1)가 "기업 전달·전달완료 상태 구현 안 함"이라 명시했고 JobApplicationStatus.FORWARDED는 죽은 값으로 남아 있다. 실제 Lifecycle이 구현되기 전까지 이 Metric은 Dashboard에서 제외한다 |
| 포트폴리오 미제출(기한 경과) |
- |
BLOCKED — Portfolio Phase 2 Scope ①(학생 제출, PR #212)은 Merge됐지만 Issue #204가 다루는 관리자 제출 현황/일괄 다운로드(Scope ②)는 아직 OPEN이다. Phase 2가 완료되기 전에는 실제 Metric으로 구현하지 않는다 |
| 정상 시스템 |
실제 Health/Operation 상태 기준 |
BLOCKED — #227이 먼저 확정되어야 "정상"의 판정 기준(각 Task 상태 조합)이 생긴다 |
기존 API totalElements 조합으로 충분히 계산 가능한 Metric은 신규 Aggregate API를 만들지 않는다. 새 Aggregate가 필요한 항목(BLOCKED로 표시된 것들)만 해당 선행 Issue가 완료된 뒤 범위를 좁혀 후속 Issue로 구현한다.
요구사항
제외 범위
Architecture
Cross-Domain(Member/Job/Program/Inquiry/Application/Notification/Discord/Scheduler/Collector) 성격이라 특정 Domain 하나에 두지 않는다. REUSE_EXISTING_API 항목은 기존 Endpoint를 Client가 여러 번 호출하는 방식으로 충분하므로 이 Issue에서 신규 Aggregate Query Port를 도입하지 않는다.
Performance
REUSE_EXISTING_API 항목은 Client가 필요한 만큼만 개별 호출하면 되므로 서버 Aggregate가 필요하지 않다. BLOCKED 항목이 실제 구현될 때 호출 수가 문제가 되면 그 시점에 Aggregate 필요성을 재검토한다.
Security
Role별(관리자/교직원/개발자) 대시보드가 서로 다른 Metric을 요구하므로, 각 REUSE_EXISTING_API 호출도 기존 Endpoint의 Role 정책을 그대로 따른다(별도 확대 없음).
Test
이 Issue 자체는 신규 Backend 코드를 추가하지 않으므로 별도 Test가 없다. BLOCKED 항목이 후속 Issue로 구현될 때 해당 Issue에서 Test를 추가한다.
완료 조건
Related
Owner 후보
- Cross-Domain이라 단일 기능 구현자가 없다.
- Candidate(MEDIUM):
Fresh-Banana — Application/Export/Member Admin 등 최근 가장 넓은 범위를 구현한 이력
- Confidence: MEDIUM (자동 Assign 금지, Assignee 비워둠)
배경
관리자/교직원/개발자 대시보드 화면(Figma node 942:21779/942:20791/942:21970)이 PR #81로 이미 구현되어 있으나, KPI 카드·표·알림 데이터가 전부 하드코딩된 Mock이다 — 실제 API 연동이 전혀 시도되지 않았다.
Client 근거
GETI-Client-V1(develop,078388a)src/views/admin-dashboard/model/mock.ts—DASHBOARD_CONTENT전체가 정적 상수(관리자/교직원/개발자 3종).src/views/admin-dashboard/ui/AdminDashboardPage.tsx—content: DashboardContent를 Props로만 받아 그대로 렌더링할 뿐, 어떤 Query Hook도 호출하지 않는다.Widget별 필요 Metric (Client Mock 기준, 추측 아님)
관리자: 가입 승인 대기(교직원) 건수 · 전체 지원(서) 건수 · 공고 상세(모집/마감/비공개) 건수 · 프로그램 상태(진행/예정/종료) 건수 · 미답변 문의 건수 · 전체 지원 처리 현황 표(제출완료/검토중/수정요청 건수·비율) · 최근 운영 상태(공고·프로그램·미답변 문의 요약).
교직원: 신규 지원자 건수 · 수정요청 지원서 건수 · 기업 전달 대기 건수 · 진행 중 프로그램 건수 · 포트폴리오 미제출(기한 경과) 건수 · 담당 공고 현황 표(공고별 지원자·처리대기·상태) · 최근 알림 3종.
개발자: 정상 시스템 건수 · Discord 전송 실패 건수 · 정기 작업 실패 건수 · 외부 공고 수집 실패 건수 · 미처리 오류 문의 건수 · 최근 실패 내역 표 · 최근 운영 알림.
확정 계약
기준 시각/기간을 아래와 같이 확정한다(Client Mock의 "최근 7일" 표기는 아래 값으로 대체한다 — CLIENT_CONTRACT_ALIGNMENT_REQUIRED: 화면 문구를 실제 값에 맞게 정리해야 한다).
JobApplication생성 시각 기준)GET /api/v1/admin/discord-deliveries?status=FAILED(Issue #206/PR #213, Merge 완료)의totalElements에 기간 Filter만 추가하면 된다GET /api/v1/admin/members/search?status=PENDING&role=TEACHER의totalElements(Issue #183/PR #216)totalElements반복 조회JobApplicationAdminServiceImpl.list의 기존 status Filterdocs/application/application-domain-plan.md(§1.1)가 "기업 전달·전달완료 상태 구현 안 함"이라 명시했고JobApplicationStatus.FORWARDED는 죽은 값으로 남아 있다. 실제 Lifecycle이 구현되기 전까지 이 Metric은 Dashboard에서 제외한다기존 API
totalElements조합으로 충분히 계산 가능한 Metric은 신규 Aggregate API를 만들지 않는다. 새 Aggregate가 필요한 항목(BLOCKED로 표시된 것들)만 해당 선행 Issue가 완료된 뒤 범위를 좁혀 후속 Issue로 구현한다.요구사항
제외 범위
Architecture
Cross-Domain(Member/Job/Program/Inquiry/Application/Notification/Discord/Scheduler/Collector) 성격이라 특정 Domain 하나에 두지 않는다. REUSE_EXISTING_API 항목은 기존 Endpoint를 Client가 여러 번 호출하는 방식으로 충분하므로 이 Issue에서 신규 Aggregate Query Port를 도입하지 않는다.
Performance
REUSE_EXISTING_API 항목은 Client가 필요한 만큼만 개별 호출하면 되므로 서버 Aggregate가 필요하지 않다. BLOCKED 항목이 실제 구현될 때 호출 수가 문제가 되면 그 시점에 Aggregate 필요성을 재검토한다.
Security
Role별(관리자/교직원/개발자) 대시보드가 서로 다른 Metric을 요구하므로, 각 REUSE_EXISTING_API 호출도 기존 Endpoint의 Role 정책을 그대로 따른다(별도 확대 없음).
Test
이 Issue 자체는 신규 Backend 코드를 추가하지 않으므로 별도 Test가 없다. BLOCKED 항목이 후속 Issue로 구현될 때 해당 Issue에서 Test를 추가한다.
완료 조건
Related
Owner 후보
Fresh-Banana— Application/Export/Member Admin 등 최근 가장 넓은 범위를 구현한 이력