사이트픽 블로그
← 목록으로

개발일지 2026-08-06

음악학원 플랫폼 개발일지 (2026-08-06)

개요

이날은 관리자(admin)의 학원 상세 화면 대개편이 핵심이었다. 와이어프레임 시안대로 학원 상세를 여러 탭으로 확장하고, (1) 계약 상태 관리(상태 변경 + 이력 + SMS 통지), (2) 본사 수동 구독 연장(다음 결제일 연장), (3) 계약 종료일(contract_end)을 다음 결제일과 동기화, (4) 학원 기본정보에 업태/업종·운영시간 필드 추가와 로고 저장, (5) 브랜드사이트 노출 토글(학원찾기/수강생모집) 영속화, (6) 대리점(Agency)에 미배정 학원 일괄 배정 및 소속 해제까지 붙였다.

수정/생성 파일 목록

백엔드 (piano-backend)

  • .../academy/AcademyStatusService.java / AcademyStatusHistory.java / AcademyStatusHistoryMapper.java (신규) — 계약상태 변경 + 이력 + SMS
  • mapper/AcademyStatusHistoryMapper.xml, migration-20260806-academy-status-history.sql (신규)
  • .../academy/subscription/AcademySubscriptionService.java (수정), dto/SubscriptionExtendRequest.java (신규) — 수동 구독 연장
  • .../admin/AcademyAdminController.java (수정) — 상태변경/연장/노출/대리점배정 엔드포인트
  • Academy.java / AcademyService.java / dto/AcademyRequest.java (수정) — 업태(biz_type)/업종/노출플래그/로고
  • migration-20260806b-academy-biz-type-category.sql, ...c-drop-biz-category.sql, ...d-academy-expose-flags.sql (신규)
  • .../agency/AgencyService.java (수정) — 미배정 학원 일괄 배정 / 소속 해제(unassign)
  • .../file/FileService.java (수정) — SUPER_ADMIN 로고 업로드 실패 수정
  • mapper/AcademyMapper.xml, mapper/LocationMapper.xml (수정)

프론트 (admin 중심)

  • admin/src/pages/AcademyDetail.tsx (대폭 개편, 여러 커밋에 걸쳐 9탭 확장·상태관리 연동·구독연장·기본정보 재배치)
  • admin/src/api/academies.ts (수정) — 상태변경/연장/노출 PATCH/대리점 API
  • admin/src/popups/agencies/AgencyAcademyManager.tsx (신규), AssignAcademies.tsx (신규), admin/src/pages/Agencies.tsx (수정) — 대리점 학원 관리 분할 화면
  • brand/src/pages/Locations.tsx (수정) — 노출 토글 반영, 수강생 모집중 라벨 위치
  • admin/src/components/Layout.tsx (수정) — 헤더 스타일

파일별 상세

1. 학원 계약 상태 관리 (상태 변경 + 이력 + SMS)

학원의 계약상태(ACTIVE/EXPIRED/TERMINATED 등)를 관리자가 바꿀 수 있게 하고, 바뀔 때마다 이력을 남기고 원장에게 SMS를 보내도록 했다. 이력 테이블(academy_status_history)을 새로 만들고, 상태 전환 로직을 AcademyStatusService 로 캡슐화했다.

// AcademyStatusService — 상태 변경 → 이력 적재 → SMS
academyMapper.updateContractStatus(academyId, newStatus);
historyMapper.insert(new AcademyStatusHistory(academyId, oldStatus, newStatus, reason));
smsSendService.sendStatusChanged(academy, newStatus);  // 원장 통지

admin AcademyDetail.tsx 의 "상태 관리" 탭이 이 API 와 실연동되어, 상태 드롭다운 변경 + 사유 입력 + 이력 리스트를 보여준다.

2. 본사 수동 구독 연장 + 계약 종료일 동기화

결제 실패/특수 케이스를 대비해 본사가 수동으로 다음 결제일을 연장할 수 있게 했다(SubscriptionExtendRequest). 또한 신규 가입 시 contract_end 를 다음 결제일과 맞춰 동기화(5303381)해서, 계약 만료와 결제 주기가 어긋나지 않게 했다. (이 contract_end 가 08-10 대시보드의 "만료 임박 학원" 위젯의 기준이 된다.)

3. 학원 기본정보 개편 (업태/업종·운영시간·로고)

사업자 정보에 맞춰 학원 기본정보에 업태(biz_type)/업종(biz_category) 을 추가했다. 처음엔 두 컬럼으로 넣었다가(a07f671), 이후 단일 컬럼 통합 + 로고 저장 지원으로 정리(cd7eee7)했다. admin 상세 폼은 캡처(시안) 순서대로 필드를 재배치하고, 브랜드 노출용 운영시간(hours) 한 줄 필드를 추가했다.

4. 브랜드사이트 노출 토글 영속화

학원을 브랜드(공개) 사이트의 "학원찾기(expose_find)" / "수강생 모집중(expose_recruiting)" 에 노출할지를 토글로 저장한다. 관리자에서 저장하면 즉시 brand 지점찾기에 반영되도록 플래그를 영속화했다. 이날은 저장 방식이 아직 폼 전체 저장에 얹혀 있었고, 다음 날(08-07) 전용 PATCH /expose 로 분리해 "그때그때 즉시 저장"으로 개선한다.

5. 대리점(Agency) 학원 관리

대리점에 미배정 학원을 일괄 배정하고, 반대로 소속을 해제(unassign) 하는 기능을 백엔드/관리자 양쪽에 붙였다. admin 은 AgencyAcademyManager(3분할: 대리점 소속 / 미배정 / 검색)와 AssignAcademies 팝업으로 관리한다.

트러블슈팅 메모

  • SUPER_ADMIN 로고 업로드 실패: 본사 관리자 계정에는 academyId 가 없어 로고 저장 경로 계산에서 NPE 성 실패가 났다. FileService 에서 학원 컨텍스트가 없을 때의 분기를 보정해 해결(65002db).
  • 업태/업종 컬럼 설계 번복: 두 컬럼 → 단일 컬럼 통합으로 바꾸며 drop-biz-category migration 을 추가. 초기 스키마를 확정 전에 너무 세분화하지 말자는 교훈.

결론 / 배운 점

  • 상태 변경처럼 "되돌아보기가 필요한" 도메인은 이력 테이블 + 통지를 처음부터 함께 설계하면 CS 대응이 쉬워진다.
  • 결제 주기와 계약 만료일을 동기화해두면 후속 기능(만료 임박 알림/대시보드)이 그 값 하나로 깔끔하게 파생된다.
  • 즉시 반영이 필요한 토글은 폼 전체 저장에 얹지 말고 전용 PATCH 로 분리하는 게 UX·정합성 모두 낫다(다음 날 반영).

댓글 0

  • 첫 번째 댓글을 남겨보세요.