# ITOSM 피아노 학습실 - Bach to Basics 설치 및 운영 ## 운영 정보 | 항목 | 값 | |---|---| | 설치 위치 | `/home/syskiller/piano/bach-to-basics` | | Gitea 저장소 | `syskiller/ITOSMPiano-BachToBasics` | | 프론트엔드 컨테이너 | `piano-bach-frontend` | | 백엔드 컨테이너 | `piano-bach-backend` | | 호스트 포트 | `127.0.0.1:18102` | | 백엔드 내부 포트 | `8000` | | 기본 주소 | `https://learn.itosm.co.kr` | | 별칭 주소 | `https://learn.itosm.com` | | MusicXML 보관 폴더 | `/home/syskiller/piano/music/musicxml` | | 회원 DB와 MIDI 보관 | `/home/syskiller/piano/bach-to-basics/data` | 백엔드는 호스트 포트를 열지 않는다. 프론트엔드 nginx만 Docker 내부 네트워크에서 백엔드에 접근한다. 외부 요청은 aaPanel nginx와 프론트엔드 nginx를 차례로 거친다. aaPanel의 프록시 프로젝트에는 `learn.itosm.co.kr`을 등록했다. 공용 `*.itosm.co.kr` 인증서를 적용했으며 HTTP 요청은 HTTPS로 강제 전환한다. 2026-10-03 공개 주소에서 HTTPS 200 응답과 인증서의 대상 도메인을 확인했다. `learn.itosm.com`은 기본 주소로 이동한다. ## 실행과 관리 ```bash cd /home/syskiller/piano/bach-to-basics docker compose up -d --build docker compose ps docker compose logs -f --tail=200 docker compose restart docker compose down ``` 프론트엔드 내부 확인은 `curl http://127.0.0.1:18102/`로 한다. 백엔드 확인은 프론트엔드 프록시를 통해 `curl http://127.0.0.1:18102/api/openapi.json`을 사용한다. ## 비밀 파일과 환경 변수 백엔드 API 키는 `secrets/backend_api_key`에 저장한다. 파일 권한은 600을 유지하고 Git에 넣지 않는다. Compose는 다음 값을 사용한다. - `BACKEND_API_KEY_FILE=/run/secrets/backend_api_key` - `REQUIRE_AUTH=1` - `ALLOWED_ORIGINS=https://learn.itosm.co.kr,https://learn.itosm.com` - `RATE_LIMIT_PER_MIN=60` 프론트엔드 컨테이너가 비밀 파일을 읽어 백엔드로 보내는 내부 요청에만 인증 헤더를 추가한다. 회원용 비밀번호 원문은 저장하지 않는다. 초기 관리자 비밀번호만 `secrets/library_admin_password`에 두고 파일 권한을 600으로 유지한다. 회원 DB와 업로드 MIDI는 `data`에 보관하며 Git에서 제외한다. 상세 권한과 백업 방법은 `docs/LIBRARY-AUTH-KO.md`에 기록했다. ## 업데이트 1. `git status --short --branch`로 로컬 변경을 확인한다. 2. 공식 `origin`의 변경을 가져온다. 3. 한국어판과 운영 보안 커밋의 충돌 여부를 확인한다. 4. `docker compose build`를 실행한다. 5. `docker compose up -d`로 두 전용 컨테이너만 교체한다. 6. MIDI와 MusicXML 가져오기 및 악보와 내려오는 음표 화면을 다시 검사한다. ## 한국어판 변경 파일 - `frontend/src/i18n/ko.ts` - `frontend/src/main.tsx` - `frontend/index.html` - `frontend/vite.config.ts` - `frontend/src/index.css` - `frontend/src/views/PracticeView.tsx` - `frontend/src/components/Transport/TransportControls.tsx` - `backend/main.py` - `backend/routers/transcribe.py` - `frontend/nginx.conf` - `frontend/docker-entrypoint.d/20-backend-api-key.sh` - `frontend/Dockerfile` - `docker-compose.yml` 한국어 번역 리소스와 모바일 화면 보완 및 서버 내부 API 키 처리를 추가했다. 공식 CI와 같은 pnpm 9를 사용하도록 고정해 잠금 파일 기반 빌드를 유지한다. MIDI와 MusicXML 및 악보와 내려오는 음표와 따라치기 기능은 원본 구조를 유지한다. 표준 `.musicxml` 확장자도 파일 선택과 백엔드 변환에서 지원한다. ## 데이터와 한글 파일명 MIDI와 MusicXML은 브라우저 파일 선택이나 끌어 놓기로 불러온다. 공용 보관 폴더는 `/home/syskiller/piano/music/midi`와 `/home/syskiller/piano/music/musicxml`이다. 프론트엔드는 파일명을 유니코드 문자열로 처리하며 백엔드 전송 제목에는 UTF-8 URL 인코딩을 사용한다. ## 원본으로 되돌리기 공식 원본 커밋을 별도 작업 트리에 복원해 빌드한다. 현재 운영 폴더의 기록은 강제로 다시 쓰지 않는다. `/home/syskiller/piano/backup`에 보관한 Git 번들과 설치 백업을 사용해 별도 복제본에서 먼저 검증한다. 백엔드 키를 복원할 때는 비밀 백업을 일반 소스와 분리하고 권한 600을 유지한다. ## 선택 기능과 제한 사항 - 초기 운영에서는 Audiveris PDF OMR과 Basic Pitch 오디오 변환을 별도로 구성하지 않는다. - MusicXML과 MIDI 및 기본 악보 변환 기능은 설치되어 있다. - 실제 USB MIDI 입력과 따라치기 동작은 안드로이드 Chrome과 실제 전자피아노에서 최종 확인해야 한다. - iPhone과 iPad의 Safari는 Web MIDI를 지원하지 않는다. - 회원 가입과 로그인 및 등급별 곡 보관함을 제공한다. 회원은 MIDI를 올리고 전체 공개와 회원 공개 및 지정 공유와 나만 보기 중 하나를 선택할 수 있다. - 회원은 현재 비밀번호를 확인한 뒤 비밀번호를 변경하거나 탈퇴할 수 있다.