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

곡을 담지 않고 조건만 담기로 했다

매장에 트는 재생목록을 그때까지는 곡을 하나씩 골라 담아 만들었다. 곡이 수백 개가 되니 이 방식이 버텼다가 무너졌다. 새 곡이 들어와도 사람이 다시 담아 주기 전까지는 어느 재생목록에도 들어가지 않는다. 곡을 늘리는 일과 재생목록을 신선하게 두는 일이 따로 노는 셈이다.

그래서 곡 대신 조건을 담기로 했다. 「무보컬·잔잔함·재즈·사철」 같은 조건을 재생목록에 저장해 두면, 그 조건에 맞는 새 곡은 승인되는 순간 저절로 그 재생목록에 들어온다.

대신 통제를 잃는다. 조건에 맞기만 하면 내가 한 번도 안 들어 본 곡이 매장에 나간다. 그래서 두 가지를 같이 뒀다. 조건대로 알아서 채우는 재생목록과, 조건으로 후보만 좁혀 놓고 최종 확정은 사람이 하는 재생목록이다. 매장 분위기를 책임지는 간판 재생목록은 뒤엣것으로 두고, 「새로 들어온 잔잔한 곡」처럼 신선도가 값인 것은 앞엣것으로 뒀다.

자동으로 채우는 쪽을 고를 때 묻는 건 「자동이 정확한가」가 아니라 「틀렸을 때 누가 얼마나 다치나」다. 틀린 곡 하나가 매장에 나가는 비용이 크면 사람이 확정하고, 그 비용이 작으면 자동이 낫다.


사철 트는 재생목록에 캐럴이 섞여 나왔다

조건으로 굴리기 시작하자마자 문제가 나왔다. 여름에 트는 재생목록에서 크리스마스 곡이 나온 것이다. 그 곡도 조건(잔잔함·피아노)에는 맞았다.

고치는 방법이 둘이었다. 크리스마스 곡을 하나씩 빼거나, 「계절이 붙은 곡은 사철 재생목록에서 전부 뺀다」는 규칙을 하나 두거나.

뒤엣것을 골랐다. 앞엣것은 곡이 들어올 때마다 다시 손봐야 하지만, 뒤엣것은 한 번 정하면 앞으로 들어올 계절 곡에도 그대로 듣는다. 조건으로 굴리기로 한 이상, 예외도 곡 단위가 아니라 조건 단위로 두는 게 앞뒤가 맞았다.

빼는 규칙을 만들 때는 그게 「이 곡」을 빼는 규칙인지 「이런 곡」을 빼는 규칙인지를 먼저 가린다. 앞엣것은 목록이 되고 뒤엣것은 규칙이 되는데, 목록은 늘어나고 규칙은 늘어나지 않는다.


시간표대로 바꾸되 곡은 끊지 않기로 했다

재생목록을 시간대별로 걸 수 있게 만들면서 정할 게 하나 더 나왔다. 9시가 되는 그 순간 바꿀 것인가, 지금 곡이 끝난 뒤에 바꿀 것인가.

곡을 중간에 끊으면 매장에서 바로 티가 난다. 그래서 전환은 곡이 끝나는 자리에서만 하기로 했다. 시각이 지나도 지금 곡은 끝까지 가고, 다음 곡을 고르는 순간에 「지금은 어느 시간대인가」를 다시 본다.

블록마다 끝 시각을 따로 두지 않은 것도 같은 결이다. 다음 블록이 시작하기 전까지가 앞 블록의 시간이라, 끝을 적게 하면 두 값이 어긋날 자리만 생긴다. 시간표는 「언제부터」만 적게 하고 나머지는 계산으로 두었다.

사람이 채워야 할 값이 둘인데 그중 하나가 다른 하나에서 나온다면, 그건 묻지 말고 계산하는 게 맞다. 물어 두면 언젠가 둘이 어긋난다.


놓치는 곡이 많았는데 원인은 도구가 아니라 사전이었다

곡을 올릴 때 프롬프트의 단어를 보고 분위기를 자동으로 붙인다. 그런데 분명히 활기찬 곡인데 「활기」가 안 붙는 일이 자주 있었다. 자동 분류가 약한 거라고 생각하기 쉬운 자리다.

실제로는 「활기」에 등록된 단어가 몇 개 안 됐던 것이다. 앞선 TIL 2에서 한 단어가 두 칸에 걸리지 않게 사전을 정리했는데, 이번엔 반대로 단어가 모자란 쪽이었다. lively·vibrant·dynamic 같은 말을 더 넣자 놓치던 곡들이 그대로 걸리기 시작했다. 도구를 바꾼 게 아니라 도구가 보는 목록을 늘린 것뿐이다.

자동 분류가 약해 보이면 방법을 갈아엎기 전에 그게 무엇을 보고 판단하는지부터 본다. 대개는 판단하는 힘이 아니라 아는 말의 수가 모자란다.


분류 이름이 누구 기준인지 걸렸다

분위기 하나가 「이국적」이었다. 계속 눈에 걸려서 「휴양」으로 바꿨다.

이유는 기능이 아니라 시선이다. 「이국적」은 보는 사람 기준의 말이다. 그 곡들은 동남아·라틴 계열인데, 정작 그쪽 사람에게는 이국적일 리가 없다. 곡이 주는 느낌 자체를 가리키는 「휴양」은 누가 보든 같은 것을 가리킨다.

바꾸면서 하나 안심한 게 있다. 이미 그 분위기가 붙어 있던 곡 96편은 손댈 필요가 없었다. 앞선 TIL 2에서 칸을 옮길 때 확인한 것과 같은 이유다. 이름을 바꿀 때마다 붙은 것이 다 떨어진다면 애초에 이름을 못 고친다.

분류 이름은 만드는 쪽의 시선이 아니라 대상 자체를 가리켜야 오래 간다. 그리고 이름을 고치는 일이 싸야 이런 판단을 미루지 않게 된다.


애매한 곡을 막아 두면 확인이 밀린다

룸톤 곡은 가사가 없는 게 기본이다. 그래서 올리기 전에 목소리가 섞였는지 자동으로 검사한다. 그런데 이 검사는 허밍이나 스캣도 목소리로 잡고, 색소폰 같은 악기까지 목소리 쪽으로 샌다. 앞선 TIL 4에서 확인한 대로 도구가 틀린 게 아니라 묻는 질문이 다른 것인데, 결과만 보면 오탐이 잦다.

그때까지는 의심 곡을 따로 격리 폴더로 뺐다. 막아 두는 쪽이 안전해 보이지만, 실제로는 「나중에 들어 봐야 하는 폴더」가 쌓이기만 했다. 확인이 밀리면 그 곡들은 없는 곡이 된다.

그래서 격리를 그만두고, 의심 표시만 달아 그대로 들여보내기로 했다. 나중에 앱에서 「보컬」 필터로 모아 들으면 되고, 그때까지는 적어도 카탈로그 안에 있다.

오탐이 잦은 자동 판정에는 「확실해질 때까지 막아 두기」보다 「들여보내고 표시해서 나중에 거르기」가 맞다. 앞엣것은 사람이 손대야 풀리는 대기열을 만들고, 뒤엣것은 손대지 않아도 시간이 지나면 걸러진다.


한 달에 뽑을 수 있는 곡 수가 정해져 있었다

곡은 생성 도구로 만드는데, 요금제에 따라 한 달에 내려받을 수 있는 수가 정해져 있다(상위 요금제 60곡, 낮추면 20곡). 무한정 뽑는 게 아니라 예산이 정해진 자원이다.

이걸 알고 나면 「부족한 분위기를 채우자」가 계획이 된다. 어떤 분위기가 몇 곡인지 세어 보고, 빈 쪽부터 그달의 몫을 쓴다.

도구의 한도는 기능 설계가 아니라 운영 계획으로 넘어온다. 무료·유료 한도를 볼 때 「되나 안 되나」만 보면, 그게 한 달에 무엇을 할 수 있는지를 정한다는 걸 놓친다.


요약

  • 곡 대신 조건을 담으면 새 곡이 저절로 들어온다. 자동으로 채울지는 「자동이 정확한가」가 아니라 「틀렸을 때 누가 다치나」로 정한다.
  • 예외를 둘 때는 「이 곡」인지 「이런 곡」인지 가린다. 앞엣것은 목록이 되고 뒤엣것은 규칙이 된다.
  • 시간표 전환은 곡이 끝나는 자리에서만 한다. 한 값에서 나오는 다른 값은 묻지 말고 계산한다.
  • 자동 분류가 약해 보이면 방법보다 그것이 아는 말의 수를 먼저 본다.
  • 분류 이름은 만드는 쪽의 시선이 아니라 대상 자체를 가리켜야 오래 간다. 이름을 고치는 일이 싸야 그 판단을 미루지 않는다.
  • 오탐이 잦은 판정은 막아 두기보다 표시해서 나중에 거른다. 막아 두면 사람이 손대야 풀리는 대기열이 쌓인다.
  • 도구의 한도는 기능이 아니라 운영 계획으로 넘어온다.

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