개발일지 2026-06-28
엠포레 피아노학원 플랫폼 개발일지 (2026-06-28)
개요
오늘은 크게 세 가지 축으로 작업했다. 첫째, 세션 관리 완성 — JWT에 sessionId를 심어 세션 종료 시 즉시 인증을 차단하고, 중복 세션 정책(ON/OFF)과 자동 로그아웃을 구현했다. 둘째, 모니터링 고도화 — 더미 데이터를 걷어내고 실제 시스템 메트릭(CPU/메모리/디스크/DB풀/서비스 핑)을 수집하는 API를 만들었다. 셋째, 콘텐츠 관리(공지/FAQ/팝업) 와이어프레임 반영 — 셀렉트박스, 공개 여부, 노출 대상, 일괄 삭제 등 실무 기능을 추가했다. 그 외에 감사 로그 무한 스크롤, 환불 관리 신규 개발, 스케줄러 카카오 예약발송 등 다양한 화면을 손봤다.
수정/생성 파일 목록
백엔드 (piano-backend)
| 파일 | 구분 | 요약 |
|---|---|---|
admin/monitoring/MonitoringController.java | 신규 | GET /admin/monitoring API |
admin/monitoring/MonitoringData.java | 신규 | 리소스/서비스/통계 DTO |
admin/monitoring/MonitoringService.java | 신규 | CPU·메모리·디스크·HikariCP·DB핑·뿌리오DNS 수집 |
admin/monitoring/MonitoringMapper.java | 신규 | 일일 통계 쿼리 인터페이스 |
mapper/MonitoringMapper.xml | 신규 | api_audit_logs/admin_sessions 집계 SQL |
admin/refund/RefundController.java | 신규 | 환불 CRUD + 승인/반려 API |
admin/refund/RefundService.java | 신규 | 환불 비즈니스 로직 |
admin/refund/RefundMapper.java | 신규 | 환불 매퍼 인터페이스 |
admin/refund/RegistrationRefund.java | 신규 | 환불 엔티티 |
admin/refund/dto/RefundRequest.java | 신규 | 환불 등록 DTO |
admin/refund/dto/RefundProcessRequest.java | 신규 | 승인/반려 DTO |
mapper/RefundMapper.xml | 신규 | 환불 검색/통계/승인/반려 SQL |
migration-20260628-refunds.sql | 신규 | registration_refunds 테이블 + 공통코드 |
migration-20260628-popup-type-memo.sql | 신규 | 팝업 memo 컬럼 + SCHEDULED 상태 |
migration-20260628-notice-faq-enhance.sql | 신규 | 공지 노출 시작/종료/대상/알림톡, FAQ visible |
admin/popup/Popup.java | 수정 | memo 필드 추가 |
admin/popup/PopupRequest.java | 수정 | memo 파라미터 추가 |
mapper/PopupMapper.xml | 수정 | memo 매핑/INSERT/UPDATE 반영 |
publicsite/announcement/Announcement.java | 수정 | startAt/endAt/targetScope/autoAlimtalk/status 추가 |
mapper/AnnouncementAdminMapper.xml | 수정 | 신규 필드 매핑 |
student/faq/Faq.java | 수정 | visible 필드 추가 |
mapper/FaqAdminMapper.xml | 수정 | visible 매핑 |
admin/faq/dto/FaqRequest.java | 수정 | visible 파라미터 추가 |
audit/ApiAuditLogController.java | 수정 | offset/limit 페이징 파라미터 |
audit/ApiAuditLogMapper.java | 수정 | 페이징 파라미터 |
audit/ApiAuditLogService.java | 수정 | 페이징 전달 |
mapper/ApiAuditLogMapper.xml | 수정 | LIMIT/OFFSET 동적 쿼리 |
common/ErrorCode.java | 수정 | BAD_REQUEST 추가 |
admin/messagelog/MessageScheduler.java | 수정 | 카카오 알림톡 예약 발송 추가 |
프론트 (piano-academy/admin)
| 파일 | 구분 | 요약 |
|---|---|---|
api/monitoring.ts | 신규 | 모니터링 API 클라이언트 |
api/refunds.ts | 신규 | 환불 API 클라이언트 |
api/schedulers.ts | 신규 | 스케줄러 API 클라이언트 |
pages/Monitoring.tsx | 전면 재작성 | 실 데이터 연동 + 30초 카운트다운 + 데이터 소스 테이블 |
pages/MembershipRefunds.tsx | 전면 재작성 | 와이어프레임 기반 환불 관리 (필터/KPI/승인·반려) |
pages/Schedulers.tsx | 전면 재작성 | 더미→실 API 연동 + 활성/비활성 토글 |
pages/AuditLogs.tsx | 수정 | 무한 스크롤 (IntersectionObserver) + 엑셀 비활성화 |
pages/Popups.tsx | 전면 재작성 | 제목 링크 + 체크박스 일괄 삭제 + 액션 컬럼 제거 |
pages/Faqs.tsx | 수정 | 공개 Chip + 질문 링크 + 체크박스 일괄 삭제 |
pages/Notices.tsx | 수정 | 제목 링크 + 체크박스 일괄 삭제 |
pages/Roles.tsx | 수정 | 전체 필터 'ALL' + 순서 컬럼 제거 |
pages/FreePolicies.tsx | 수정 | 로딩 중복 제거 |
pages/MarketingPlans.tsx | 수정 | 로딩 중복 제거 |
pages/MembershipPlans.tsx | 수정 | 로딩 중복 제거 |
popups/popups/PopupForm.tsx | 전면 재작성 | 와이어프레임 반영 (노출상태/우선순위/메모/안내) |
popups/faqs/FaqForm.tsx | 수정 | 카테고리 셀렉트 + 공개 여부 토글 |
popups/notices/NoticeForm.tsx | 수정 | 노출 대상/시작/종료/알림톡 토글 |
api/auditLogs.ts | 수정 | offset/limit 파라미터 |
api/popups.ts | 수정 | memo + 일괄 삭제 |
api/faqs.ts | 수정 | visible + 일괄 삭제 |
api/announcements.ts | 수정 | 신규 필드 + 일괄 삭제 |
components/Sidebar.tsx | 수정 | 하위 없는 항목 '-' 표시, 중메뉴 볼드 |
상세 설명
1. 모니터링 실 데이터 연동
더미 하드코딩이었던 모니터링 화면을 실제 시스템 메트릭으로 교체했다.
백엔드 수집 방식:
// CPU: OS 로드 평균 / 코어 수
double loadAvg = os.getSystemLoadAverage();
int cpuPercent = (int) Math.min(100, (loadAvg / availableProcessors) * 100);
// 메모리: JVM 힙
long usedMem = runtime.totalMemory() - runtime.freeMemory();
int memPercent = (int) ((usedMem * 100) / runtime.maxMemory());
// DB 풀: HikariCP MXBean
if (dataSource instanceof com.zaxxer.hikari.HikariDataSource hds) {
poolActive = hds.getHikariPoolMXBean().getActiveConnections();
}
프론트 30초 카운트다운:
const [countdown, setCountdown] = useState(30);
useEffect(() => {
const tick = setInterval(() => {
setCountdown((prev) => {
if (prev <= 1) { load(); return 30; }
return prev - 1;
});
}, 1000);
return () => clearInterval(tick);
}, [load]);
useEffect cleanup으로 clearInterval을 하기 때문에 페이지 이탈 시 타이머가 정리된다.
2. 환불 관리 (03-4) 신규 개발
와이어프레임 기반으로 등록비 환불 관리를 처음부터 구축했다.
registration_refunds테이블 + 공통코드 (refundStatus/refundChannel/paymentMethod/refundMethod/refundReason)- 검색 필터: 상태/항목/기간(일/주/월)/학원명
- KPI 통계: 처리 대기, 월 환불 건수, 월 환불액, 평균 처리 시간
- 승인/반려:
POST /admin/refunds/{id}/approve,POST /admin/refunds/{id}/reject
3. 감사 로그 무한 스크롤
기존 500건 고정 로드 → 200건씩 무한 스크롤로 변경.
// IntersectionObserver로 하단 감지
const observer = new IntersectionObserver(
([entry]) => { if (entry.isIntersecting) fetchMore(); },
{ rootMargin: '200px' },
);
observer.observe(sentinelRef.current);
백엔드는 offset/limit 파라미터를 받아 LIMIT #{limit} OFFSET #{offset}으로 처리.
4. 콘텐츠 관리 와이어프레임 반영
공지 (06-1):
- 노출 대상: 전체 학원 / 특정 학원 셀렉트
- 노출 시작/종료: datetime + 상시(종료일 없음) 옵션
- 발행 시 알림톡 자동 발송 토글
- 임시저장/취소/발행 3버튼
FAQ (06-3):
- 카테고리: 텍스트 입력 → 공통코드 셀렉트 (결제/구독/수업/계정/기타)
- 공개/비공개 토글 버튼 (ToggleButtonGroup)
팝업 (06-2):
- 노출 상태: 활성/비활성 → 노출/예약/대기 3단계
- 노출 우선순위 + 내부 메모 필드 추가
- 이미지 권장 사이즈 가이드 안내
공통 패턴 — 목록 페이지 체크박스 일괄 삭제:
<DataTable
columns={columns}
rows={rows}
rowKey="id"
selectable
onSelectionChange={setSelected}
/>
// 선택 시 상단에 "N개 삭제" 버튼 표시
5. 스케줄러 카카오 예약발송
MessageScheduler의 TODO였던 카카오 알림톡 예약 발송을 구현:
} else if ("ALIMTALK".equals(msg.getChannel())) {
ppurioService.sendKakao(
msg.getRecipientPhone(), "@m포레", msg.getTemplateCode());
}
6. 사이드바 메뉴 개편
- 매출/정산 하위에 중메뉴 4개 생성 (결제·정산 / 멤버십 구독 / 마케팅 / 분석)
- 하위 메뉴가 없는 항목(실제 화면)은 아이콘 대신
-로 표시 - 중메뉴: 폰트 볼드 + 들여쓰기 조정 (depth 1: pl 4→3)
트러블슈팅
HikariCP 패키지명 오타
모니터링 서비스에서 com.zaxxara.hikari로 import했으나 실제는 com.zaxxer.hikari. 빌드 에러로 발견 → 즉시 수정.
로딩 프로그레스바 2개 표시
fx.isLoadingbar(true) (글로벌) + <CircularProgress /> (페이지 내부) 두 개가 동시에 떴다. 내부 로딩을 return null로 교체하여 글로벌 로딩바만 사용.
SSH 터널 끊김
장시간 작업 중 SSH 터널이 끊어져 백엔드 기동 시 Communications link failure 발생. nc -z localhost 3306으로 확인 후 터널 재연결.
DB 마이그레이션 (오늘 적용)
| 파일 | 내용 |
|---|---|
migration-20260628-refunds.sql | registration_refunds 테이블 + 환불 관련 공통코드 5그룹 |
migration-20260628-popup-type-memo.sql | popups.memo + popupStatus SCHEDULED |
migration-20260628-notice-faq-enhance.sql | announcements 5개 컬럼 + faqs.visible + 공통코드 |
진행률 업데이트
| 화면 | 변경 |
|---|---|
| 08-2 모니터링 | 0% → 100% |
| 08-3 스케줄러 현황 | 90% → 100% |
| 09-1 계정 관리 | 40% → 100% |
| 09-2 권한 설정 | 55% → 100% |
| 09-3 감사 로그 | 50% → 100% |
| 09-5 약관 관리 | 50% → 100% |
| 09-5-1 약관 버전 등록 | 0% → 100% |
| 03-4 환불 관리 | 0% → 85% |
결론
시스템 운영 메뉴(모니터링/스케줄러/감사 로그/세션/권한/약관/계정)가 모두 100%에 도달했다. 콘텐츠 관리(공지/FAQ/팝업)도 와이어프레임에 맞춰 실무 기능(노출 대상, 공개 여부, 일괄 삭제)을 갖추었고, 환불 관리도 백엔드+프론트 모두 신규 구축했다. 결제 모듈은 KSNET PG를 사용할 예정이며, 테스트 가맹점 키 발급 후 연동 개발을 진행할 계획이다.
댓글 1
- test2026년 6월 29일
ttt