개발일지 2026-07-12
피아노 학원 플랫폼 개발일지 (2026-07-12)
개요
악보 관리 시스템의 그룹(곡) 관리 + 변형(PDF) 추가 기능을 완성하고, 학생/공개 악보 탐색 사이트의 상세 페이지 UI를 와이어프레임에 맞춰 대폭 개선했다. 미리보기 설정·프린트 제한 등 운영 설정 화면도 DB 연동으로 전환하고, 아티스트 상세 페이지를 신규 구현했다.
수정/생성 파일 목록
백엔드 (piano-backend)
AdminSheetItemRow.java(수정) — pdfFilename 필드 추가AdminSheetSong.java(수정) — categoryIds, titleMainEn, artistMainEn 필드 추가AdminSheetSongController.java(수정) — 변형 추가 엔드포인트POST /sheet-songs/{id}/itemsAdminSheetSongService.java(수정) — addItem(), categoryNames 직접 수정, pdf_filename 최대값+1 채번AdminSheetSongMapper.java(수정) — updateCategoryNames, findByArtistPaged, countByArtist 추가AdminSheetSongMapper.xml(수정) — itemRowMap에 pdf_filename 매핑, 검색조건에 pdf_filename 추가, song_code 숫자정렬, categoryNames/categoryIds 상세 반환SheetSongUpdateRequest.java(수정) — categoryNames 필드 추가SheetItemCreateRequest.java(신규) — 변형 추가 요청 DTOStudentSheetSongMapper.xml(수정) — category_names 컬럼 반환, 아티스트별 조회 쿼리PublicSheetSongController.java(수정) —GET /by-artist엔드포인트 추가PublicSheetSongService.java(수정) — listByArtist(), registrationInfo 매핑PublicSongRow.java(수정) — categoryNamesText 필드 추가SheetSong.java(수정) — registrationInfo 필드 추가PrintLimitController.java(신규) — 프린트 제한 CRUD APIPrintLimit.java(신규) — 프린트 제한 엔티티PrintLimitMapper.java(신규) — 프린트 제한 매퍼PrintLimitMapper.xml(신규) — 프린트 제한 SQLSheetPreviewController.java(신규) — 미리보기 설정 조회/수정 APISheetPreviewSettings.java(신규) — 미리보기 설정 엔티티SheetPreviewMapper.java(신규) — 미리보기 설정 매퍼SheetPreviewMapper.xml(신규) — 미리보기 설정 SQLmigration-20260712c-print-limits.sql(신규) — print_limits 테이블migration-20260712d-print-limit-codes.sql(신규) — 공통코드(printMonthlyLimit, printExceedPolicy)migration-20260712e-sheet-preview-settings.sql(신규) — sheet_preview_settings 테이블 + 공통코드(watermarkType, watermarkPosition, watermarkOpacity)
프론트 — 관리자 (admin)
SheetGroups.tsx(신규) — 악보 그룹관리 목록. 서버 페이징, 체크박스 선택 삭제, 그룹코드 링크SheetGroupDetail.tsx(신규) — 악보 그룹 상세. sheet_songs 직접 편집, category_names 드래그 정렬SheetSongs.tsx(수정) — 곡코드 링크, 체크박스 삭제, 서버 페이징, 엑셀 다운로드SheetCategories.tsx(수정) — 체크박스 선택 삭제, 제목 클릭 수정, 행별 버튼 제거SheetPreview.tsx(수정) — DB 연동 + 공통코드 + 워터마크 시뮬레이션PrintLimits.tsx(수정) — DB 연동 + 공통코드SheetItemAdd.tsx(신규) — 변형 추가 팝업 (PDF 업로드 + 난이도/편성/KOMCA)sheetSongs.ts(수정) — addSheetItem, SheetItemCreateForm 등 API 추가sheetPreview.ts(신규) — 미리보기 설정 APIprintLimits.ts(신규) — 프린트 제한 APIDataTable.tsx(수정) — 서버 페이징 props, 헤더 무조건 중앙정렬Sidebar.tsx(수정) — 메뉴 클릭 시 resetSearch state 전달usePersistedSearch.ts(수정) — resetSearch 감지해 검색 조건 초기화AuthContext.tsx(수정) — 로그인 시 sessionStorage/localStorage 초기화pageRegistry.ts(수정) — sheet-groups 등록popup/registry.ts(수정) — SheetItemAdd 등록
프론트 — 악보 사이트 (sheets)
SongCard.tsx(수정) — 와이어프레임 스타일 카드 (썸네일 + 편성/난이도 태그 + 아티스트 링크)songs/page.tsx(수정) — 상세 히어로 영역 (커버 + 정보카드 + 분류정보), 편성별 그룹 섹션artist/page.tsx(신규) — 아티스트 상세 페이지 (헤더 + 관련곡 그리드)sheetSongs.ts(수정) — registrationInfo, getSheetSongsByArtist API 추가globals.css(수정) — 카드 썸네일, 태그, 히어로, 섹션 테이블, 아티스트 페이지 스타일.env.local(신규) — 로컬 개발 시 localhost:8080으로 API 연결
주요 작업 상세
1. 악보 그룹관리 (sheet_songs 단위)
기존 악보목록은 변형(sheet_items) 단위로만 보여줬는데, 곡(sheet_songs) 단위로 관리하는 그룹관리 화면을 추가했다.
- 목록: 그룹코드(songCode) 링크 클릭 → 상세 이동, 서버 페이징(DataTable 서버 페이징 props 신규), 체크박스 선택 삭제
- 상세: sheet_songs 컬럼을 직접 편집하는 폼.
category_names는 Chip 태그로 추가/삭제/드래그 정렬 가능
// 드래그로 등록정보 순서 변경
<Chip draggable onDragStart={() => setDragIdx(i)}
onDrop={() => {
const next = [...prev];
const [moved] = next.splice(dragIdx, 1);
next.splice(i, 0, moved);
return next;
}} />
2. 변형(PDF) 추가 기능
기존에는 곡+변형을 동시에 등록하는 것만 가능했는데, 기존 곡에 변형만 추가하는 API + 팝업을 만들었다.
POST /admin/sheet-songs/{id}/items— pdf_filename은 같은 곡의 기존 변형 중 최대 순번+1로 자동 채번- 팝업에서 PDF 드래그 업로드, 난이도/편성/KOMCA 입력 후 추가
// pdf_filename 자동 채번: 기존 최대값 + 1
for (AdminSheetItem ex : existing) {
int n = Integer.parseInt(ex.getPdfFilename().substring(prefix.length()));
if (n > maxSeq) maxSeq = n;
}
String pdfFilename = prefix + String.format("%04d", maxSeq + 1);
3. DataTable 서버 페이징
DataTable 공통 컴포넌트에 serverTotal, serverPage, onServerPageChange props를 추가해서, 페이지 번호/크기 변경 시 서버 API를 호출하도록 했다.
<DataTable serverTotal={total} serverPage={page - 1}
onServerPageChange={(p, size) => { setPage(p + 1); setPageSize(size); }} />
4. 미리보기 설정 + 프린트 제한 — DB 연동
두 화면 모두 목업에서 실제 DB 테이블 + API로 전환했다.
sheet_preview_settings테이블: 공개 페이지 범위, 워터마크 설정print_limits테이블: 월 허용 횟수, 초과 정책- 셀렉트박스 옵션은 공통코드(
watermarkType,printMonthlyLimit등)에서 로드
5. 악보 사이트 — 와이어프레임 UI 적용
곡 카드: 썸네일(베이지 배경 + 곡명/아티스트) + 편성/난이도 태그를 와이어프레임과 동일하게 구현
곡 상세 히어로: 좌측 커버아트 + 우측 정보카드(아티스트/작곡가 pill 클릭 → 아티스트 페이지) + 분류정보 태그
편성별 그룹 섹션: 변형 목록을 formMinor(멜로디/2단/3단/포핸즈)별로 그룹핑. 각 섹션에 난이도/Key/가사/페이지/설명/미리보기·출력 버튼
6. 아티스트 상세 페이지
아티스트/작곡가 이름 클릭 시 /artist?name=Yiruma 형태로 이동. 해당 인물의 관련 곡/등록 악보/카테고리 수를 보여주고, 곡 카드 그리드로 목록 표시.
- 백엔드:
GET /public/sheet-songs/by-artist?artist=...— artist 또는 composer 일치 조회
트러블슈팅
배포 경로 오류 발견 및 수정
nginx root가 /var/www/piano이고 location이 /admin이므로 실제 서빙 경로는 /var/www/piano/admin/인데, deploy-prod 스킬이 /var/www/piano/piano-admin/에 배포하고 있었다. 배포해도 반영이 안 되는 원인이었고, 스킬 설정을 올바른 경로로 수정했다.
백엔드 포트 충돌 (systemd restart loop)
systemd Restart=on-failure 설정으로 인해 이전 프로세스가 죽지 않은 채로 새 프로세스가 계속 기동 시도 → 포트 8080 충돌 반복. systemctl stop → reset-failed → kill -9 → 포트 확인 → start 순서로 해결.
결론
악보 관리의 곡 그룹/변형 체계가 완성되었고, 공개 악보 사이트의 UI가 와이어프레임 수준으로 올라왔다. 미리보기·프린트 제한 같은 운영 설정도 DB 기반으로 전환되어 관리자가 직접 조정할 수 있게 되었다. 아티스트 상세 페이지까지 추가되어 악보 탐색 UX가 한층 풍부해졌다.
댓글 0
- 첫 번째 댓글을 남겨보세요.