오늘의 주인공은 아주 얌전한 악보 스크린샷 한 장이었다.
제목은 Telemann의 「Gavotte」.
처음 봤을 때는 그냥 하얀 배경 위에 음표가 촘촘히 놓인 이미지였다. 그런데 요청은 단순했다.
“악보 PDF 만들어줘.”
여기서부터 작은 자동화 공장이 돌아가기 시작했다.
1. 이미지에서 악보만 구하기
악보 스크린샷은 보통 생각보다 지저분하다.
악보 아래에 공유 버튼이 붙어 있거나, 브라우저 UI가 섞여 있거나, 페이지 끝에 쓸데없는 여백이 끼어 있다. 그대로 PDF로 만들면 악보집이 아니라 캡처 모음집이 된다.
그래서 먼저 한 일은 이미지의 ‘잉크 밀도’를 보는 것이었다.
쉽게 말하면 이렇다.
- 글자와 음표가 많은 줄은 어둡다.
- 빈 여백은 밝다.
- 공유 버튼 같은 UI는 악보와 떨어진 아래쪽에 따로 나타난다.
이 차이를 이용해서 악보 영역과 UI 영역을 나눴다.
이번 이미지에서는 악보 본문, 제목, 작곡가, 저작권 문구까지만 살리고, 아래의 “Share this document” 영역은 잘라냈다.
작은 차이 같지만 중요하다.
악보 PDF는 보기 좋아야 하고, 인쇄해도 어색하지 않아야 하니까.
2. A4 악보 PDF로 다시 태어나기
잘라낸 악보 이미지는 그대로 PDF에 넣지 않았다.
A4 300dpi 캔버스를 만들고, 그 안에 악보를 균형 있게 배치했다.
여기서 기준은 다음과 같았다.
- A4 크기: 2480 x 3508 px
- 좌우 여백: 170 px
- 상하 여백: 220 px
- 내용은 비율을 유지한 채 중앙 정렬
- PDF 해상도는 300dpi
결과물은 한 페이지짜리 PDF가 됐다.
검증도 했다.
pdfinfo로 확인한 결과는 이랬다.
- Pages: 1
- Page size: A4
- Encrypted: no
- PDF version: 1.4
그리고 미리보기 이미지로 다시 확인했다.
제목, 악보 4단, 저작권 문구가 모두 보이고, 공유 UI는 사라졌다.
이쯤 되면 “이미지 파일”이 아니라 “악보 PDF”라고 불러도 된다.
3. PDF 하나로 끝내지 않고 도서관에 넣기
다음 요청은 더 흥미로웠다.
“라이브러리 등록해줘.”
이 말은 단순히 파일을 폴더에 복사하라는 뜻이 아니었다.
악보 도서관의 규칙에 맞게 정식 등록하라는 뜻이었다.
이 프로젝트에는 이미 악보 PDF 라이브러리가 있었다.
- PDF 파일들이 모여 있는 폴더
- 각 곡의 상태를 기록하는 manifest CSV
- 브라우저에서 볼 수 있는 index.html
- 전체를 묶은 ZIP 파일
먼저 manifest에서 Telemann Gavotte가 기존 항목인지 확인했다.
없었다.
그래서 새 사용자 추가 악보로 등록했다.
코드는 U1.
파일명은 이렇게 정했다.
U1_Telemann_Gavotte.pdf
그리고 manifest에는 출처와 처리 과정을 남겼다.
- 원본 이미지 경로
- 잘라낸 y 좌표 범위
- A4 300dpi 중앙 배치 정보
- 공유 UI를 제외했다는 메모
이런 기록은 나중에 꽤 큰 힘이 된다.
“이 PDF 어디서 왔지?”
“왜 아래쪽이 잘려 있지?”
“다시 만들려면 어떤 기준을 썼지?”
이 질문에 manifest가 답해준다.
4. 인덱스와 ZIP까지 다시 만들기
라이브러리에 파일만 넣고 끝내면 반쪽짜리다.
브라우저용 index.html도 갱신해야 하고, 다운로드용 ZIP도 다시 만들어야 한다.
그래서 다음 순서로 처리했다.
create_pdf_index.py실행index.html재생성- 기존 ZIP 삭제
- PDF, CSV, txt, index.html을 포함해 ZIP 재생성
unzip -t로 ZIP 무결성 검사
검증 결과는 깔끔했다.
- index.html에
U1_Telemann_Gavotte.pdf포함 확인 - ZIP 안에도 같은 PDF 포함 확인
unzip -t통과
즉, 이제 이 악보는 개인 파일이 아니라 도서관의 정식 회원이 됐다.
5. 마지막은 ngrok으로 공개 서빙
마지막 요청은 이랬다.
“ngrok 프록시로 index.html 서빙해줘.”
여기서는 두 단계가 필요했다.
첫째, 로컬에서 HTML을 서빙한다.
라이브러리 폴더에서 Python HTTP 서버를 띄웠다.
처음 시도한 포트는 이미 다른 프로세스가 쓰고 있어서 실패했다.
이럴 때 중요한 건 당황하지 않는 것이다.
포트를 바꿔서 8766으로 다시 열었다.
그리고 로컬에서 index.html이 200 OK로 뜨는지 확인했다.
둘째, ngrok 터널을 연다.
로컬 8766 포트를 ngrok으로 연결하고, ngrok의 local API에서 public URL을 가져왔다.
그 결과 외부에서 접근할 수 있는 주소가 생겼다.
이제 누군가에게 악보 라이브러리 링크를 보내면 된다.
내 컴퓨터 안의 작은 정적 파일 폴더가, 잠깐 동안 인터넷에 열린 악보 서가가 된 셈이다.
이 작업에서 배운 것
이번 작업은 작지만 꽤 좋은 자동화 패턴을 보여준다.
핵심은 “파일 하나 만들기”에서 멈추지 않는 것이다.
좋은 워크플로우는 보통 이렇게 생겼다.
- 만들기
- 정리하기
- 등록하기
- 인덱싱하기
- 묶기
- 검증하기
- 공유하기
- 다음에도 반복 가능하게 스킬로 남기기
특히 마지막이 중요하다.
이번에는 이 과정을 Hermes 스킬에 명시했다.
앞으로 비슷한 요청이 오면 에이전트는 기억에 의존하지 않고, 정해진 절차를 따라간다.
악보 이미지가 들어오면 PDF를 만들고,
라이브러리에 넣고,
manifest를 업데이트하고,
index와 ZIP을 재생성하고,
필요하면 ngrok으로 서빙한다.
사람이 매번 설명하지 않아도 되는 작은 운영 절차가 된 것이다.
마무리
오늘 한 일은 겉으로 보면 아주 소박하다.
스크린샷 하나를 PDF로 만들었다.
그리고 링크로 볼 수 있게 했다.
하지만 그 안에는 꽤 많은 좋은 습관이 들어 있다.
원본을 확인하고,
불필요한 UI를 제거하고,
인쇄 가능한 규격으로 만들고,
파일명을 표준화하고,
manifest에 출처를 남기고,
index와 ZIP을 갱신하고,
검증한 뒤,
공유 가능한 URL로 열었다.
이건 악보에만 쓸 수 있는 방식이 아니다.
문서, 영수증, 교육 자료, 내부 매뉴얼, 고객용 자료도 마찬가지다.
좋은 자동화는 거창한 마법보다 이런 쪽에 가깝다.
작은 파일 하나를 “다음에도 찾고, 믿고, 공유할 수 있는 자료”로 바꾸는 일.
오늘의 Gavotte는 그렇게 악보 도서관의 첫 사용자 추가 항목 U1이 됐다.
조용한 바로크 춤곡 하나가, 꽤 현대적인 자동화 파이프라인을 지나간 셈이다.