개발일지 2026-08-07
음악학원 플랫폼 개발일지 (2026-08-07)
개요
전날(08-05) 학생 앱에 만들어둔 "학원 변경 신청"의 관리자 승인 플로우를 완성한 날이다. (1) 학생 본인 신청 내역 조회 API, (2) 관리자 승인 API + 승인 화면, (3) 노출 토글 즉시 저장용 전용 PATCH /expose 분리, (4) 브랜드 학원찾기/학원상세의 "수강생 모집중" 라벨·UI 다듬기를 진행했다.
수정/생성 파일 목록
백엔드 (piano-backend)
.../admin/AcademyChangeRequestAdminController.java(신규) — 관리자 승인/반려.../student/academychange/AcademyChangeRequest.java/...Mapper.java/...Service.java(수정) — 승인 상태 전이.../student/academychange/StudentAcademyChangeController.java(수정) — 학생 본인 신청 내역 조회mapper/AcademyChangeRequestMapper.xml(수정),migration-20260807-academy-change-request-menu.sql(신규).../academy/AcademyMapper.java/AcademyService.java/admin/AcademyAdminController.java(수정) — 노출 토글 전용 PATCH/admin/academies/{id}/exposedata.sql(수정) — 승인 메뉴 시드
프론트
admin/src/pages/AcademyChangeRequests.tsx(신규),admin/src/api/academyChangeRequests.ts(신규),admin/src/App.tsx(수정) — 관리자 승인 화면/라우트student/src/pages/AcademyChangeRequestPage.tsx(수정),student/src/api/academyChangeRequest.ts(수정) — 내 신청 내역·상태 표시admin/src/api/academies.ts(수정),admin/src/pages/AcademyDetail.tsx(수정) — 노출 토글을 전용 PATCH 로 전환brand/src/pages/Locations.tsx(수정),admin/src/pages/AcademyDetail.tsx(수정) — 수강생 모집중 라벨 위치/노출admin/src/components/Layout.tsx(수정) — 헤더 배경 불투명+하단 보더
파일별 상세
1. 학원 변경 신청 — 관리자 승인 플로우 완성
학생이 넣은 학원 변경 신청을 관리자가 승인/반려한다. 승인 시 상태를 전이시키고(대기→승인), 학생 앱에서는 자기 신청의 현재 상태를 조회해 표시한다. 관리자 화면(AcademyChangeRequests.tsx)은 신청 목록 + 승인/반려 액션으로 구성했다.
// admin/api/academyChangeRequests.ts
export const listChangeRequests = async () => {
const { data } = await client.get<ApiResult<ChangeRequest[]>>('/admin/academy-change-requests');
return data.data ?? [];
};
export const approveChangeRequest = (id: number) =>
client.post(`/admin/academy-change-requests/${id}/approve`);
// student — 내 신청 내역/상태
export const myChangeRequests = async () => {
const { data } = await client.get<ApiResult<MyChangeRequest[]>>('/student/academy-change-requests/me');
return data.data ?? [];
};
이 승인 로직은 이틀 뒤(08-09) "승인 시 담당강사 초기화 + 새 학원 원장 문자 알림"으로 한 번 더 확장된다.
2. 노출 토글 즉시 저장 — 전용 PATCH /expose 분리
08-06 에는 브랜드 노출 토글이 학원 기본정보 폼 전체 저장에 얹혀 있었다. 토글은 "그때그때 즉시 반영"이 자연스러운 UX 라, 전용 엔드포인트 PATCH /admin/academies/{id}/expose 를 새로 파서 토글만 단독 저장하도록 바꿨다. 폼 저장 후에도 편집 모드가 유지되도록, 노출 토글은 편집 모드에서만 변경 가능하도록 정리했다.
// AcademyAdminController — 노출 플래그만 부분 갱신
@PatchMapping("/{id}/expose")
public ApiResponse<Void> updateExpose(@PathVariable Long id, @RequestBody ExposeRequest req) {
academyService.updateExposeFlags(id, req.getExposeFind(), req.getExposeRecruiting());
return ApiResponse.ok();
}
3. 브랜드 UI 다듬기
- 학원찾기(
Locations.tsx)에서 "수강생 모집중" 라벨을 지도(이미지) 영역 좌상단으로 이동. - 관리자 학원 상세에서도 모집 토글 ON 이면 동일한 라벨을 이미지 좌상단에 노출해 브랜드와 미리보기를 맞췄다.
- admin 상단 헤더를 반투명+블러 대신 불투명 배경 + 하단 보더로 바꿔 콘텐츠에 딱 붙어 보이게 했다.
결론 / 배운 점
- 신청→승인 같은 양쪽(학생/관리자) 워크플로우는 상태 전이를 서버가 소유하고, 각 앱은 그 상태를 조회해 표시만 하도록 두면 정합성이 유지된다.
- 토글처럼 즉시성이 중요한 컨트롤은 큰 폼 저장과 분리된 전용 PATCH 로 두는 게 낫다. 저장 실패 범위도 좁아진다.
댓글 0
- 첫 번째 댓글을 남겨보세요.