이 글은 Today I Learn 시리즈의 98번째 기록입니다. (총 230개)

파는 물건이 파일이라 보호가 먼저였다

룸톤이 파는 것은 곡 파일이다. 매장이 돈을 내고 듣는 것도, 남이 공짜로 가져갈 수 있는 것도 같은 파일이다. 그래서 첫날 정할 것은 어떻게 재생하느냐가 아니라 어떻게 아무나 못 받아가게 하느냐였다.

정리하면 층이 셋이었다.

  • 저장소를 열어 두고 주소만 알면 받게 두기. 가장 싸지만 주소 하나가 새면 끝이다.
  • 저장소는 잠가 두고 우리 서버를 거쳐서만 내보내기. 곡을 틀 때마다 잠깐만 살아 있는 주소를 새로 만들어 준다.
  • 파일 자체를 암호로 잠가서 앱만 풀 수 있게 하기. 가장 단단하지만 만드는 일도 많다.

가운데를 먼저 골랐다. 주소가 새어도 금방 죽고, 곡 하나씩 발급하니 한 번에 카탈로그 전체가 털리지도 않는다. 파일 자체를 잠그는 일은 외부 고객을 받기 전에 하기로 미뤘다.

여기서 확실히 해 둔 게 하나 있다. 스피커로 나온 소리를 녹음하는 건 어떤 방법으로도 못 막는다. 그러니 목표는 「못 가져가게 한다」가 아니라 「그냥 파일을 복사해 가는 것보다 번거롭게 만든다」다. 막을 수 없는 것을 목표로 잡으면 아무리 만들어도 부족해 보인다.


보호를 택하면 편의를 잃는다

곡 주소가 몇 분이면 죽게 해 두니 바로 대가가 나왔다. 재생 라이브러리에는 곡 여러 개를 미리 담아 두고 알아서 이어 트는 기능이 있는데, 그걸 쓸 수 없다. 뒤쪽 곡의 주소가 실제로 재생될 때쯤엔 이미 죽어 있기 때문이다.

그래서 곡이 끝나는 것을 지켜보다가 그때 다음 곡의 주소를 새로 받아 잇는 방식으로 만들었다. 기성 기능 하나를 못 쓰고 직접 이어 붙인 셈이다.

보호를 한 단계 올리면 기성품이 맞물리지 않는 자리가 생긴다. 그 비용을 미리 세어 두면 「이만큼 막기 위해 이만큼 직접 만든다」는 교환이 되고, 안 세어 두면 나중에 왜 이게 이렇게 복잡한지 모르게 된다.


매장은 화면을 켜 두지 않는다

앱을 만들면서 확인해야 할 게 있었다. 매장 기기는 화면을 끈 채로 하루 종일 음악만 트는 상태가 정상이다.

그런데 요즘 휴대기기 운영체제는 화면이 꺼지면 앱을 재운다. 계속 소리를 내려면 시스템에 「지금 음악을 틀고 있다」고 신고하고 알림을 띄워 둬야 한다. 그 대가로 시스템이 앱을 함부로 끄지 않는다.

이건 기능이 아니라 사용 환경에서 나온 요구였다. 만들기 전에 「이 앱이 실제로 놓이는 상태는 무엇인가」를 물었기 때문에 첫날 걸렸다. 나중에 이 장치가 슬쩍 풀려 재생이 끊기는 일이 다시 생기는데, 그때 원인을 빨리 찾은 것도 여기서 한 번 짚어 뒀기 때문이다.


음량을 어디서 맞출지 정했다

생성 도구로 뽑은 곡은 음량이 제각각이라 이어 틀면 소리가 튄다. 맞출 자리가 둘이었다.

재생할 때 앱이 곡마다 볼륨을 조절하거나, 올릴 때 파일 자체를 같은 음량으로 구워 두거나. 앞엣것은 원본을 안 건드려서 깔끔해 보이지만, 재생하는 쪽마다 같은 계산을 넣어야 하고 기기에 따라 소리를 키우는 쪽이 막히기도 한다.

올릴 때 굽는 쪽으로 정했다. 재생하는 쪽을 여러 개 만들 생각이라면, 공통으로 거치는 앞단에서 한 번 해결하는 게 전체가 단순해진다.

같은 자리에서 하나 더 정했다. 음량을 맞추는 폭에 위아래 한계를 두는 것이다. 측정이 잘못된 곡 하나가 크게 보정돼 매장에서 갑자기 커지면, 그 사고 한 번이 서비스 전체의 인상을 정한다. 자동으로 손보는 장치에는 「최악의 경우 얼마나 어긋날 수 있나」를 먼저 묶어 둔다.


재생 한 번을 어디서 셀지 정했다

인기 곡 순서를 만들려면 재생을 세야 하는데 기준이 애매했다. 끝까지 들은 것만 셀지, 튼 순간을 셀지.

끝까지 들은 것만 세면 정확하지만 건너뛴 곡은 안 세어지고, 그걸 알아내려면 장치가 하나 더 필요하다. 곡을 틀려면 반드시 주소를 받아 가야 하니, 그 지점에서 세기로 했다. 이건 「재생을 시작했다」이지 「끝까지 들었다」가 아니다.

편성에 참고하려는 숫자니까 이 정도면 충분하다고 봤다. 완청률이 필요해지는 날이 오면 그때 따로 만들면 된다.

지금 필요한 정확도가 어디까지인지 먼저 정하면, 그보다 정확한 것을 만드느라 쓰는 시간을 아낄 수 있다. 다만 이 정의가 나중에 다른 일의 조건이 된다는 것도 같이 알아 두는 게 좋다.


자동 분류의 한계는 도구가 아니라 입력에 있었다

프롬프트에서 장르를 자동으로 뽑아 태그 초안을 채우게 했다. 트로피컬 하우스 곡에 「기타」가 장르로 붙었다. 프롬프트에 기타가 쓰여 있으니 걸린 것인데, 거기서 기타는 여러 악기 중 하나지 장르가 아니다. 정작 첫머리에 적힌 진짜 장르는 사전에 없어서 놓쳤다.

단어가 있는지만 보고 그 단어가 문장에서 무슨 역할인지는 못 보는 게 이 방식의 한계다. 더 똑똑한 방법으로 갈 수도 있었지만, 반대편을 보니 답이 달랐다. 「집 편안」 두 단어짜리 프롬프트에서는 어떤 방법을 써도 장르를 뽑을 수 없다.

그래서 도구를 정교하게 만들기 전에 프롬프트를 충실히 쓰는 쪽을 먼저 하기로 했다. 자동 분류의 성능은 분류기보다 입력의 질에 더 크게 걸려 있다.


요약

  • 막을 수 없는 것(스피커 녹음)을 목표로 잡지 않는다. 목표는 「그냥 복사하는 것보다 번거롭게」다.
  • 보호를 올리면 기성품이 안 맞물리는 자리가 생긴다. 그 비용을 미리 세어 두면 교환이 되고, 안 세면 복잡함만 남는다.
  • 만들기 전에 「이 물건이 실제로 놓이는 상태」를 묻는다. 매장 기기는 화면이 꺼진 채 하루 종일 돈다.
  • 여러 재생기가 생길 일이면 공통으로 거치는 앞단에서 한 번 해결한다. 자동 보정에는 최악의 어긋남을 묶어 둔다.
  • 지금 필요한 정확도를 먼저 정한다. 다만 그 정의가 나중 일의 조건이 된다.
  • 자동 분류의 성능은 분류기보다 입력의 질에 더 걸려 있다.

Series: Today I Learn

1 C++ 자료형(Data Type) 2 MD5 vs pHash 3 C++에서 함수의 선언과 정의 4 Tkinter padx, pady 5 메모리와 포인터 변수 6 Call by Value, Call by Reference, Call by Pointer 비교 7 const 8 Gemfile — Jekyll 프로젝트의 의존성 파일 9 kramdown-parser-gfm — Jekyll의 GFM 파서 10 파서(Parser) 11 AHU vs OHU 12 I might try it vs I'll try it 뉘앙스 차이 13 SESSION_EXPIRE_AT_BROWSER_CLOSE=True 14 configuration key 15 Git stash vs discard 16 subprocess.Popen으로 Windows 탐색기에 명령어를 전달 17 Post 잔디 분석하기 18 Google Sheets Sync 최적화 19 DSL (Domain Specific Language)과 GPL (General Purpose Language) 20 마크다운 표 그리는 방법 21 쿼리 파라미터(Query Parameter). 기존 QR코드 재활용 22 Django 보안 취약점 점검 및 수정 23 OOP Object-Oriented Programming 객체 지향 프로그래밍 24 Fernet 대칭 암호화 25 Jekyll 코드블록 안의 Liquid 태그 26 습관만들기 Pawbit TIL 1 27 insertOnConflictUpdate vs DoUpdate(target) 28 세션 필터 29 아코디언(Accordiaon) UI를 펼친상태로 만들기 30 input의 step 31 습관만들기 Pawbit TIL 2 32 습관만들기 Pawbit TIL 3 33 Word Cloud 34 Google Sheets를 데이터 버스로(with AppSheet) 35 Django 모델 텍스트 필드 자동 수집 패턴 36 localStorage로 섹션 토글 상태 유지 37 순차 ID 생성(`select_for_update()` + `max()` 조합) 38 역참조 검색과 distinct() 39 xlsx 다운로드와 로딩 오버레이 충돌 40 Android 파일 공유 MIME 타입 41 AssetManifest — Flutter 빌드 타임 asset 목록 런타임 조회 42 크레센도 Phaser + TypeScript TIL 1 43 크레센도 Phaser + TypeScript TIL 2 44 크레센도 Phaser + TypeScript TIL 3 45 크레센도 Phaser + TypeScript TIL 4 46 크레센도 Phaser + TypeScript TIL 5 47 여둘까 Office Layout TIL 1 48 습관만들기 Pawbit TIL 4 49 여둘까 Office Layout TIL 2 50 여둘까 Office Layout TIL 3 51 크레센도 Phaser + TypeScript TIL 6 52 UTF-8 BOM과 PowerShell 파일 쓰기 53 소리꽃 KeyBloom TIL 1 54 습관만들기 Pawbit TIL 5 55 여둘까 Office Layout TIL 4 56 소리꽃 KeyBloom TIL 2 57 소리꽃 KeyBloom TIL 3 58 메트로놈 Simple Metronome TIL 1 59 소리꽃 KeyBloom TIL 4 60 메트로놈 Simple Metronome TIL 2 61 소리꽃 KeyBloom TIL 5 62 습관만들기 Pawbit TIL 6 63 크레센도 Phaser + TypeScript TIL 7 64 메트로놈 Simple Metronome TIL 3 65 소설 타임라인 관리 도구 Lumior TIL 1 66 습관만들기 Pawbit TIL 7 67 정적 블로그 SEO 정비와 Pagefind 검색 도입 68 크레센도 Phaser + TypeScript TIL 8 69 메트로놈 Simple Metronome TIL 4 70 습관만들기 Pawbit TIL 8 71 안드로이드 AudioTrack 연속 재생, 실측 피커 정렬, 카메라 토치 플래시 72 메트로놈 Simple Metronome TIL 5 73 모래게임 Sandrop TIL 1 74 습관만들기 Pawbit TIL 9 75 메트로놈 Simple Metronome TIL 6 76 모래게임 Sandrop TIL 2 77 모래게임 Sandrop TIL 3 78 습관만들기 Pawbit TIL 11 79 습관만들기 Pawbit TIL 10 80 메트로놈 Simple Metronome TIL 7 81 모래게임 Sandrop TIL 4 82 모래게임 Sandrop TIL 5 83 습관만들기 Pawbit TIL 12 84 모래게임 Sandrop TIL 6 85 소리꽃 KeyBloom TIL 6 86 모래게임 Sandrop TIL 7 87 모래게임 Sandrop TIL 8 88 소리꽃 KeyBloom TIL 7 89 모래게임 Sandrop TIL 9 90 소리꽃 KeyBloom TIL 8 91 모래게임 Sandrop TIL 10 92 소리꽃 KeyBloom TIL 9 93 콘티온 ContiOn TIL 1 94 소리꽃 KeyBloom TIL 10 95 콘티온 ContiOn TIL 2 96 습관만들기 Pawbit TIL 13 97 콘티온 ContiOn TIL 3 98 룸톤 Roomtone TIL 1 읽는 중 99 모래게임 Sandrop TIL 11 100 소리꽃 KeyBloom TIL 11 101 여둘까 Office Layout TIL 5 102 모래게임 Sandrop TIL 12 103 모래게임 Sandrop TIL 13 104 콘티온 ContiOn TIL 4 105 모래게임 Sandrop TIL 14 106 소리꽃 KeyBloom TIL 12 107 습관만들기 Pawbit TIL 14 108 모래게임 Sandrop TIL 15 109 모래게임 Sandrop TIL 16 110 소리꽃 KeyBloom TIL 13 111 온실 GreenHouse TIL 1 112 콘티온 ContiOn TIL 5 113 모래게임 Sandrop TIL 17 114 소리꽃 KeyBloom TIL 14 115 온실 GreenHouse TIL 2 116 콘티온 ContiOn TIL 6 117 모래게임 Sandrop TIL 18 118 콘티온 ContiOn TIL 7 119 모래게임 Sandrop TIL 19 120 소리꽃 KeyBloom TIL 15 121 룸톤 Roomtone TIL 2 122 모래게임 Sandrop TIL 20 123 모래게임 Sandrop TIL 21 124 소리꽃 KeyBloom TIL 16 125 소리꽃 KeyBloom TIL 17 126 소리꽃 KeyBloom TIL 18 127 여둘까 Office Layout TIL 6 128 소리꽃 KeyBloom TIL 19 129 소리꽃 KeyBloom TIL 20 130 콘티온 ContiOn TIL 8 131 콘티온 ContiOn TIL 9 132 로그스톤 상표 셀프 출원 TIL 1 133 소리꽃 KeyBloom TIL 21 134 로그스톤 샵 LogStone Shop TIL 1 135 소리꽃 KeyBloom TIL 22 136 로그스톤 샵 LogStone Shop TIL 2 137 룸톤 Roomtone TIL 3 138 소리꽃 KeyBloom TIL 23 139 모래게임 Sandrop TIL 22 140 모래게임 Sandrop TIL 23 141 소리꽃 KeyBloom TIL 24 142 로그스톤 샵 LogStone Shop TIL 3 143 모래게임 Sandrop TIL 24 144 소리꽃 KeyBloom TIL 25 145 모래게임 Sandrop TIL 25 146 MiniMacro TIL 1 147 룸톤 Roomtone TIL 4 148 모래게임 Sandrop TIL 26 149 콘티온 ContiOn TIL 10 150 Astro가 무엇인지, 왜 옮기는지 151 룸톤 Roomtone TIL 5 152 룸톤 Roomtone TIL 6 153 모래게임 Sandrop TIL 27 154 소리꽃 KeyBloom TIL 26 155 MiniMacro TIL 2 156 로그스톤 샵 LogStone Shop TIL 4 157 메트로놈 Simple Metronome TIL 8 158 모래게임 Sandrop TIL 28 159 여둘까 Office Layout TIL 7 160 룸톤 Roomtone TIL 7 161 메트로놈 Simple Metronome TIL 9 162 블로그 Astro 이관 TIL 163 여둘까 Office Layout TIL 8 164 로그스톤 샵 LogStone Shop TIL 5 165 모래게임 Sandrop TIL 29 166 오픈데이 Openday TIL 1 167 로그스톤 샵 LogStone Shop TIL 6 168 모래게임 Sandrop TIL 30 169 오픈데이 Openday TIL 2 170 모래게임 Sandrop TIL 31 171 Unreal Engine MCP TIL 1 172 모래게임 Sandrop TIL 32 173 소리꽃 KeyBloom TIL 27 174 콘티온 ContiOn TIL 11 175 오픈데이 Openday TIL 3 176 로그스톤 샵 LogStone Shop TIL 7 177 모래게임 Sandrop TIL 33 178 소리꽃 KeyBloom TIL 28 179 오픈데이 Openday TIL 4 180 여둘까 Office Layout TIL 9 181 오픈데이 Openday TIL 5 182 ScorePlayer TIL 1 183 모래게임 Sandrop TIL 34 184 BuildingHub TIL 1 185 ScorePlayer TIL 2 186 여둘까 Office Layout TIL 10 187 BuildingHub TIL 2 188 ScorePlayer TIL 3 189 Unreal Engine MCP TIL 2 190 궁 미로 PalaceMaze TIL 1 191 메트로놈 Simple Metronome TIL 10 192 메트로놈 Simple Metronome TIL 11 193 오픈데이 Openday TIL 6 194 BuildingHub TIL 3 195 Obsidian vault에서 코드만 빼기 — directory junction 196 ScorePlayer TIL 4 197 여둘까 Office Layout TIL 11 198 오픈데이 Openday TIL 7 199 URL은 바뀔 수 있는 것에 묶지 않는다 200 돌이키기 힘든 변경은 작게 먼저 확인한다 201 도구는 기능이 아니라 내 일에 맞는지로 고른다 202 궁 미로 PalaceMaze TIL 2 203 궁 미로 PalaceMaze TIL 3 204 소리꽃 KeyBloom TIL 29 205 오픈데이 Openday TIL 8 206 룸톤 Roomtone TIL 8 207 BuildingHub TIL 4 208 ScorePlayer TIL 5 209 로그스톤 샵 LogStone Shop TIL 8 210 여둘까 Office Layout TIL 12 211 오픈데이 Openday TIL 9 212 BuildingHub TIL 5 213 MiniMacro TIL 3 214 룸톤 Roomtone TIL 10 215 룸톤 Roomtone TIL 9 216 소리꽃 KeyBloom TIL 30 217 오픈데이 Openday TIL 10 218 여둘까 Office Layout TIL 13 219 룸톤 Roomtone TIL 11 220 소리꽃 KeyBloom TIL 31 221 궁 미로 PalaceMaze TIL 4 222 룸톤 Roomtone TIL 12 223 로그스톤 샵 LogStone Shop TIL 9 224 룸톤 Roomtone TIL 13 225 로그스톤 샵 LogStone Shop TIL 10 226 룸톤 Roomtone TIL 14 227 소리꽃 KeyBloom TIL 32 228 룸톤 Roomtone TIL 15 229 룸톤 Roomtone TIL 16 230 룸톤 Roomtone TIL 17