2026년 10월 11일 일요일

물건은 남는데 정보는 먼저 사라진다

이 글은 GitHub에 추가한 SyX2ool 프로젝트의 Background and Modification(BACKGROUND.md)을 국문으로 옮긴 것이다.

ChatGPT 자동 생성 이미지.

Korg X2와 SyX2ool을 만들게 된 이야기

Korg X2와 X3가 출시된 1990년대에는 3.5인치 플로피 디스크가 신시사이저와 컴퓨터 사이에서 데이터를 주고받는 평범한 수단이었다. 특히 내장 시퀀서를 갖춘 워크스테이션급 신시사이저에서 플로피 디스크 드라이브는 단순한 부가 기능이 아니었다. 곡과 시퀀스, 음색을 비롯한 사용자 데이터를 저장하고 다시 불러오는 중요한 장치였다.

30여 년이 지난 지금은 상황이 달라졌다. 신시사이저 본체는 여전히 멀쩡하게 작동하는데 플로피 디스크 드라이브가 먼저 고장 나는 일이 생긴다. 드라이브가 살아 있다고 해도 요즘 컴퓨터에서 플로피 디스크를 사용하는 것 자체가 매우 번거롭다.

한 가지 해결 방법은 원래의 플로피 디스크 드라이브를 Gotek 같은 플로피 에뮬레이터로 교체하는 것이다. 과거의 디스크 기반 작업 방식을 그대로 유지하려면 아마 이것이 가장 간단한 방법일 것이다. 그러나 나는 플로피 디스크 드라이브를 교체하지 않고 어디까지 할 수 있는지가 궁금했다.

플로피 디스크라는 통로를 제외하면 X2/X3와 현대의 컴퓨터를 이어 주는 가장 중요한 통로는 MIDI 포트가 된다. 일반 MIDI 메시지로 연주 정보를 주고받을 수 있고, System Exclusive(SysEx) 메시지를 이용하면 해당 신시사이저에 고유한 데이터까지 주고받을 수 있다.

이 과정에서 오래전에 만들어진 Java 프로그램인 X3File2Sysex가 큰 도움이 되었다. 다행히 예전에 보관해 둔 Korg 디스크 파일도 있었다. X3File2Sysex를 이용하면 디스크의 데이터를 SysEx 형태로 바꾸어 MIDI를 통해 신시사이저로 전송할 수 있었다.

이것이 특히 중요했던 것은 X2의 내장 백업 배터리를 교체했을 때였다. 배터리를 교체한 뒤 X2를 다시 제대로 사용할 수 있는 상태로 만들려면 Preload Data 디스크의 데이터를 다시 올려야 했다. 그런데 플로피 디스크 드라이브가 고장 난 상태에서는 원래의 복구 방법을 사용할 수 없었다. X3File2Sysex와 MIDI 연결을 이용하니 필요한 디스크 데이터를 SysEx로 바꾸어 X2에 전송하는 방법으로 이 문제를 해결할 수 있었다.

이 경험을 통해 고장 난 플로피 디스크 드라이브를 우회하는 통로로 SysEx를 충분히 활용할 수 있다는 것을 알게 되었다. 그러나 기존 도구에는 한계도 있었다. 이미 준비된 데이터를 복원하는 것은 가능했지만, X2에서 덤프한 시퀀서 데이터를 자유롭게 들여다보고 수정하거나 다른 형식으로 바꾸어 다시 이용하는 것은 또 다른 문제였다.

오래전에 받아 둔 파일이 다시 귀중한 자료가 되다

지금 생각하면 정말 운이 좋았다. 아주 오래전에 어느 웹사이트에서 Korg X2/X3용 디스크 파일을 모아 놓은 ZIP 파일을 발견하여 받아 두었기 때문이다. 지금은 그 자료가 있던 웹사이트의 흔적조차 찾기가 쉽지 않다.

당시에는 그 파일을 보관해 둔 것이 특별히 중요하다고 생각하지 않았다. 그러나 수십 년이 지난 뒤 그것은 매우 귀중한 시험 자료가 되었다.

그 안에는 실제 Song과 User Pattern, Program, Drum 데이터 등 X2/X3에서 사용하던 여러 종류의 데이터가 들어 있었다. 이 파일들을 실제 X2에서 덤프한 SysEx 데이터와 비교하면서 막연한 추측이 아니라 실제 데이터를 바탕으로 내부 구조를 조사할 수 있었다.

또 하나 결정적으로 중요했던 자료는 Korg X2/X3 Reference Guide였다.

신시사이저를 단순히 연주하는 데에는 별로 눈에 띄지 않는 내용이 이 매뉴얼에는 상당히 자세하게 기록되어 있다. SysEx 명령, 시퀀서 파라미터, 이벤트의 종류, Pattern 관련 기능, MIDI 동작 등 내부 데이터 구조를 이해하는 데 필요한 기술적인 정보가 들어 있다.

물론 Reference Guide만 읽는다고 해서 시퀀서 덤프의 모든 바이트가 저절로 해석되는 것은 아니었다. 하지만 실제 SysEx 파일에서 발견되는 데이터를 이해하는 데 필요한 용어와 구조적인 단서를 제공했다.

결국 Reference Guide, 오래전에 보관해 둔 디스크 파일, X3File2Sysex, 그리고 실제 X2에서 얻은 덤프 데이터를 서로 비교하는 것이 X2/X3 시퀀서 형식을 분석하는 기반이 되었다.

그래서 SyX2ool을 만들기 시작했다

X2에서 시퀀서 데이터를 덤프하고, 기존 SysEx 데이터를 다시 X2로 보내는 것까지는 가능했다. 하지만 나는 덤프 파일을 정체를 알 수 없는 하나의 거대한 바이트 덩어리로 취급하는 데서 그치고 싶지 않았다.

그 안에 무엇이 들어 있는지를 알고 싶었다.

10개의 Song은 어디에 저장되어 있는가? 100개의 User Pattern은 어떤 구조로 들어 있는가? 각 Track과 Event는 어떻게 표현되는가? 그리고 X2/X3의 시퀀서 데이터와 오늘날에도 널리 사용하는 Standard MIDI File(SMF)을 서로 변환할 수는 없을까?

무엇보다도 플로피 디스크 드라이브에 의존하지 않고 현대의 컴퓨터에서 X2/X3의 내장 시퀀서에 좀 더 자유롭게 접근하고 싶었다.

그것이 SyX2ool을 만들게 된 동기였다.

SyX2ool이라는 이름은 SysEx + X2 + Tool을 합쳐 만든 것이다. 처음에는 X2/X3의 ALL SEQUENCE DATA 덤프를 해석해 보는 작은 실험으로 시작했다. 그러나 작업을 계속하면서 Song을 가져오고 내보내고, User Pattern을 추출하고, SysEx 데이터를 분석하고, MIDI와 Pattern 데이터를 실시간으로 신시사이저에서 연주하는 기능까지 갖춘 명령행 도구로 조금씩 발전하게 되었다.

그런 의미에서 SyX2ool은 X2/X3를 대신하기 위해 만든 프로그램이 아니다. 오히려 그 반대다.

오래된 X2/X3에서 원래 가지고 있던 기능을 오늘날에도 조금 더 자유롭게 사용할 수 있게 만드는 것이 목적이다.

하드웨어만 보존한다고 끝나는 것이 아니다

이번 작업을 하면서 또 하나 느낀 점이 있다.

오래된 신시사이저는 그것을 둘러싸고 있던 정보와 소프트웨어 생태계보다 오히려 더 오래 살아남을 수 있다는 것이다.

개인이 운영하던 웹사이트는 사라진다. 다운로드 링크는 끊어진다. 한때 유용했던 작은 프로그램은 더 이상 구하기 어려워진다. 사용자들 사이에서 공유되던 사용법과 기술적인 지식도 조금씩 사라진다.

내 컴퓨터 한구석에 별 생각 없이 보관해 두었던 오래된 파일들이 수십 년이 지난 뒤 X2/X3를 이해하는 데 매우 귀중한 자료가 되었다.

물건은 남는데, 정보는 먼저 사라진다.

SyX2ool을 만드는 일에는 그 정보의 일부라도 다시 기록하여 남겨 두려는 의미도 있다.


덧붙임: 이 글을 쓰면서 X3File2Sysex를 지금도 인터넷에서 구할 수 있는지 찾아보았다. 한참 찾다 보니 뜻밖에도 내 오래된 홈페이지(My old synth and MIDI)에 x3file2sysex.zip을 올려 둔 흔적이 검색되었다. 올려 놓은 나 자신도 까맣게 잊고 있었다. 물건뿐 아니라 정보도, 때로는 어디에 보관했는지조차 잊은 채 살아남는다. 😄 이 '덧붙임' 단락은 GitHub의 문서에는 포함되지 않았다.


덧붙임.2: 한 시대를 풍미했던 MIDI 관련 MIDI-OX가 최신 Windows 컴퓨터에서 제대로 전송하지 못하는 SysEx를 놓고 얼마나 고민을 하였던가? 그러나 바이브 코딩으로 만든 Syx2ool 파이썬 스크립트는 구렁이 담 넘어가듯 잘만 전송하였다. 웹 서핑을 하다가 우연히 MIDI-OX의 개발자인 Jamie O'Connell의 자기 소개 정보를 접하였다(링크). 8년 동안 배고프고 힘든 밴드 생활을 하다가 소프트웨어 엔지니어가 되었다는 진솔한 이야기가 실려 있다. 이 웹사이트는 마지막 갱신일이 2003년 7월이다. 그의 GitHub 프로젝트 사이트에도 약간의 활동 내역이 있지만, 시간이 흐를수록 이런 역사적 자료는 점점 사라질 것이다.

2026년 10월 10일 토요일

X2 Piano는 살리고 X3DRUMS(시퀀스 및 패턴)는 제대로 올리기 — SysEx 파일을 AI로 고쳐 쓰다

Korg X2는 90년대의 Pop & Rock의 표준적인 음색과 나쁘지 않은 이펙터를 내장하고 있다. 내가 특별히 관심을 두고 있는 것은 내장 시퀀서와 드럼 패턴이다. 인터넷에서 구한 XSD-15 Power Disk라는 프리셋 디스크의 내용물 중에 X3DRUMS.SNG에는 음악 제작이나 라이브에서 재사용 가능한 패턴 100개가 장르별로 10개의 곡에 채워져서 제공된다. 실제 소리가 궁금하다면 내가 1년 전에 올린 다음 영상을 확인하면 된다.



하지만 X2 기본 설정 상태에서 이 SNG 데이터만 로드하면 제 소리가 나지 않는다. 실제로는 플로피 디스크 드라이브가 망가진 상태라서 SNG 파일을 직접 로드할 수는 없고, 이를 SysEx로 전환한 것을 사용하고 있다. 제 소리를 내려면 Song/Pattern 데이터뿐 아니라 X3DRUMS에 맞는 Program과 Drum Kit 데이터도 함께 로드해야 한다. 내가 사용하는 SysEx 파일로 말하면 X3DRUMS_Prog.syx와 X3DRUMS_Drums.syx가 그것이다. 이렇게 하였을 때 가장 큰 불편함은 X2의 최대 장점인 Program A01 "X2 Piano"가 사라진다는 것이다. 매뉴얼을 참고하여 A01을 X2의 것으로 고쳐 놓으면 되지만 여간 불편한 것이 아니다. Multisound를 340번 피아노로 맞추는 것 외에도 이펙터를 비롯한 여러 설정을 손봐야 하니 여간 번거로운 일이 아니다. 이러한 불편함은 인공지능 덕분에 크게 줄어들게 되었다. 매뉴얼과 샘플 파일을 밀어 넣고 원하는 사항을 지시하면 되기 때문이다.

  • X2: A01 = X2 Piano, B01 = Piano 16' 
  • X3: A01 = Piano 8', B02 = ExpressoPF

X2/X3에는 편집 가능한 4개의 드럼킷(A1/A2/B1/B2)과 8개의 ROM 드럼킷이 있다. 이 4개의 드럼킷에서 각 키(건반)에 어떤 Drum Sound를 배치하고 어떻게 소리 나게 할 것인지는 Drums.syx에 저장된다. 반면 각 Drum Program이 이들 가운데 어느 Drum Kit을 사용할 것인지는 Prog.syx에 저장된다. 따라서 X3DRUMS의 song 및 사용자 패턴을 제작자가 의도한 음색으로 재생하려면 X3DRUMS_Prog.syx와 X3DRUMS_Drums.syx를 모두 로드해야 한다. 

놀랍게도 X2/X3의 기본 설정에서 B1은 프로그램에 할당되어 있지 않다. 

  • Program A09 (Total Kit) => A1 (Total Kit)
  • Program A69 (ProdcrKit) => A2 (Producer Kit)
  • Program B09 (Rave Kit) => B2 (Rave Kit)
  • Program B69 (VeloGated) => B2 (Rave Kit)

처음에는 이 결과가 잘 이해되지 않았다. 혹시 설정이 변형된 장비에서 덤프한 SysEx 파일을 표준 데이터처럼 사용하고 있는 것은 아닐까 하는 의심도 들었다. 그러나 X2에 Preload 데이터를 다시 로드한 뒤 실제 Program Edit 화면에서 확인해도 B09와 B69는 모두 B2를 사용하고 있었고, 별도로 살펴본 X3 Preload의 Program 데이터에서도 같은 관계가 확인되었다. 따라서 B1이 기본 Drum Program에서 사용되지 않는 것은 단순한 덤프 오류라기보다는 원래 그렇게 설계된 것으로 보인다.

그러나 X3DRUMS의 Program 데이터를 그대로 로드하면 X2의 Piano인 Program A01도 X3DRUMS의 A01로 덮어써진다. X2 Piano를 계속 사용하고 싶었기 때문에, X3DRUMS의 Program 데이터는 그대로 유지하면서 A01만 X2 Preload의 Piano 설정으로 교체하도록 ChatGPT에 지시하였다. 이렇게 만든 수정 SysEx를 사용하면 X3DRUMS에 필요한 Drum Program 설정을 유지하면서 X2의 A01 Piano도 함께 사용할 수 있다.

X3DRUMS User Pattern 목록
Song 제목 Pattern 길이 프리뷰용 Program / Drum Kit
S6 Rock&Roll! P00–P19 모두 2 bar A09 Total Kit / A1
S0 16 Beat P20–P29 모두 2 bar A09 Total Kit / A1
S9 Waltz1,2,3 P30–P35 모두 2 bar A09 Total Kit / A1
S7 Shuffels P36–P43 모두 2 bar A09 Total Kit / A1
S3* Latin&Perc P44–P59 모두 1 bar B69 Percussion / B1
S1* CntryPolka P60–P69 모두 1 bar B69 Percussion / B1
S2* Dance !!! P70–P79 모두 1 bar B09 Rave Kit / B2
S5* Rap!!! P80–P89 P80–85: 2 bar / P86–89: 1 bar B09 Rave Kit / B2
S4* Rap Filler P90–P94 모두 1 bar B09 Rave Kit / B2
S8 Slow Jams P95–P99 모두 1 bar A09 Total Kit / A1

* X2/X3 Preload 상태에서 X3DRUMS의 Song/Pattern 데이터만 로드하면 원래 의도한 음색으로 재생되지 않는 곡.

X3DRUMS에서 확인한 중요한 변경은 다음과 같다.

  • 기본 Preload에서는 사용되지 않던 B1 (Percussion Kit)을 Program B69가 사용하도록 변경하였다. B1 자체의 내용은 Preload와 동일하며, B69의 이름은 VeloGated에서 Percussion으로 바뀌었다.
  • B2 (Rave Kit)는 X3DRUMS에서 Drum Kit 자체의 내용이 대폭 변경되었다.

결론적으로 X2의 장점인 X2 Piano를 유지하면서 X3DRUMS의 드럼 패턴과 시퀀스를 원래 의도된 소리로 사용하는 방법은 다음과 같다.

  1. X2 Preload를 기본 상태로 삼는다.
  2. X3DRUMS_Drums.syx와 X3DRUMS의 Song/Pattern 데이터를 전송한다.
  3. X3DRUMS_Prog.syx에서 Program A01만 X2 Preload의 X2 Piano로 치환한 수정 SysEx를 전송한다. 이 파일은 두 Program dump를 ChatGPT에 주고 A01 데이터만 교체하도록 지시하여 만들었다.

X3DRUMS의 시퀀스 덤프에서 패턴 데이터를 풀어낸다고 해서 곧바로 표준 MIDI처럼 사용할 수 있는 것은 아니다. PC에서 MIDI 케이블을 통해 X2로 드럼 연주 정보를 보내려면 패턴 내부의 이벤트와 시간 정보가 실제 MIDI 메시지로 어떻게 대응되는지를 더 알아내야 한다. 특히 라이브 드럼머신처럼 PC에서 다음 패턴을 즉석에서 예약하고, 현재 패턴이 끝나는 다음 bar부터 정확히 전환하여 연주하려면 PC 쪽에서 패턴의 재생과 타이밍을 직접 관리해야 한다. X2에 저장된 User Pattern을 외부 MIDI에서 이런 방식으로 선택하고 전환하는 기능은 매뉴얼에서는 확인되지 않기 때문이다.

어휴, 차라리 이런 물건 갖고 노는 것이 정신 건강에 더 이롭지 않을까?


정신 건강에는 이런 물건이 낫고, 지적 유희에는 X2가 낫다. Ardule 드럼 패턴학 생태계까지 X2를 이어 보려는 것이 나의 장기적 목표이다.

신시사이저 역사에서 Korg X2/X3가 갖는 의미

Korg X2/X3는 신시사이저 역사에서 M1이나 Trinity, Triton처럼 새로운 시대를 연 기종은 아니다. 그러나 1980년대 말부터 1990년대 중반까지 이어진 Korg 워크스테이션의 발전 과정을 이해하기에는 꽤 흥미로운 악기이다.

요즘 두 기기의 '케미'가 아주 좋다. USB 케이블 형태의 MIDI 인터페이스는 '대용량' SysEx 전송에서 동작 불안정으로 인해 서랍 속으로 들어가 버렸다.

1988년에 등장한 M1은 PCM 기반 음원, 디지털 이펙트, 드럼과 시퀀서를 한 악기에 통합하면서 이른바 ‘뮤직 워크스테이션’이라는 악기 유형을 대중화했다. Korg 역시 M1이 워크스테이션이라는 새로운 악기 범주를 정의한 제품이라고 평가한다. 이후 T 시리즈를 거쳐 1991년에는 AI² 음원과 waveshaping을 채택한 01/W 시리즈가 등장했다.

X3는 1993년에 출시되었다. 내가 보유한 X2는 그 이듬해 등장한 76건반 모델(피아노 음색이 강화됨)이며, 2004년 3월에 천안 백석대학교 근처까지 가서 중고품을 구입하였다. 이들은 앞선 Korg 워크스테이션에서 발전해 온 AI² 계열의 PCM 음원 기술을 계승했다. X3의 경우 340개의 PCM multisound, 32음 동시발음, 두 개의 디지털 multi-effect processor, 16트랙 시퀀서와 32,000 event의 기록 용량을 갖추었다. 시퀀서에는 10개의 Song과 100개의 Pattern을 저장할 수 있었으며, 3.5인치 플로피디스크와 Standard MIDI File(SMF), General MIDI도 지원했다.

그러나 X2/X3가 기술적으로 새로운 시대를 연 것은 아니었다. 오히려 이미 상당히 성숙한 Korg의 PCM 워크스테이션 기술을 보다 실용적인 형태로 정리한 제품에 가까웠다. 01/W에 있었던 waveshaping도 X3에서는 사라졌다. 당시의 평가에서도 X3는 획기적인 신기술을 선보인 악기라기보다 기존 AI² 기술을 이용하여 가격과 기능의 균형을 맞춘 워크스테이션으로 받아들여졌다.

이 점은 전후의 Korg 제품을 함께 보면 더욱 분명해진다. X3보다 5년 앞선 1988년에는 역사적인 M1이 있었고, 1990년에는 독특한 Wave Sequencing과 Vector Synthesis를 내세운 Wavestation이 등장했다. 그리고 X2가 나온 바로 다음 해인 1995년에는 Trinity가 등장했다. Trinity는 터치스크린 기반의 TouchView 인터페이스와 당시로서는 고품질·대용량인 PCM, 다양한 확장 기능을 갖춘 새로운 세대의 플래그십 워크스테이션이었다. 1999년에는 그 계보를 이어 Triton이 등장했다.

따라서 Korg 워크스테이션의 역사를 아주 단순화한다면 다음과 같은 두 시대를 생각해 볼 수 있다.

M1 → T series → 01/W → X2/X3
      ↓
Trinity → Triton → 이후 세대

물론 이것은 엄밀한 제품 계보도가 아니라 기술과 제품 성격의 변화를 이해하기 위한 단순화이다. X2/X3 이후에도 AI² 계열 제품은 계속 출시되었다.

그렇다면 X2/X3의 역사적 가치는 무엇일까?

이 악기에는 1990년대 초반의 ‘워크스테이션’이라는 개념이 매우 전형적인 형태로 남아 있다. 컴퓨터를 사용하지 않고도 한 대의 건반악기에서 음색을 고르고 Combination을 만들고, 드럼 Pattern을 구성하고, 16트랙 Sequencer에 곡을 녹음한 뒤 플로피디스크에 저장한다. MIDI와 SysEx를 이용해 외부 기기와 데이터를 주고받고, GM/SMF를 통해 다른 환경에서 만들어진 곡을 재생할 수도 있다.

오늘날의 DAW 중심 작업 환경에서 보면 번거로운 방식이다. 하지만 바로 그렇기 때문에 X2/X3를 직접 사용해 보는 것은 1990년대 초반의 전자악기가 지향했던 ‘컴퓨터 없이 한 대에서 곡 전체를 만드는 작업 환경’을 경험하는 일이기도 하다.

X2/X3는 Korg 역사에서 가장 유명하거나 가장 혁신적인 신시사이저는 아니다. 오히려 M1에서 시작된 초기 PCM 워크스테이션 시대가 충분히 성숙한 시점에 등장한 실용적인 제품이라고 보는 편이 적절하다. 그리고 바로 다음 해 Trinity가 등장하면서 Korg의 워크스테이션은 새로운 세대로 넘어가기 시작했다.

그런 의미에서 X2는 ‘명기’라는 하기 어렵다. 그러나 한 시대의 기술과 음악 제작 방식을 잘 보존하고 있는 흥미로운 악기라고 부르는 편이 더 어울린다.

그러면 나는 2026년에 이르러 왜 이렇게 낡은 신시사이저인 X2에 집착하는가? 가장 큰 출발점은 아마도 일종의 ‘죄책감’이었을 것이다. 22년 전 결코 적지 않은 돈을 주고 중고로 구입했으면서도 제대로 활용하지 못한 채 오랫동안 방치해 두었다. 그동안 피아노 대용의 연습 악기로라도 꾸준히 사용했다면 지금쯤 내 연주 실력이 훨씬 나아졌으리라는 것은 자명하다.

두 번째 이유는 X2가 나의 DIY적 호기심을 자극하기 때문이다. 오래된 전자악기인 만큼 유지보수와 수리가 필요하고, 때로는 직접 개선해 볼 여지도 있다. 뜯어보고, 고치고, 데이터를 들여다보고, 원하는 기능을 만들어 보기에 아주 적당한 대상이다. 더구나 인공지능의 발전으로 과거의 나로서는 엄두를 내기 어려웠던 SysEx 분석이나 프로그래밍까지 직접 시도할 수 있게 되었다.

처음 다시 X2를 만지기 시작했을 때는 첫 번째 이유가 더 컸는지도 모르겠다. 하지만 지금은 분명히 두 번째 이유가 더 크다. X2는 이제 연주해야 할 오래된 악기인 동시에, 가지고 놀기에 아주 재미있는 오래된 기계가 되었다.

2026년 10월 6일 화요일

[KORG X2] 30년 된 신시사이저의 시퀀서 포맷을 파헤치다

집에 있는 Korg X2는 1990년대 초에 나온 신시사이저이다. USB 같은 것은 당연히 없고 데이터를 주고받으려면 플로피디스크나 MIDI를 이용해야 한다. 최근 고장 난 플로피 드라이브를 Gotek(USB 메모리를 이용하는 에뮬레이터)으로 바꿀까 고민하다가 엉뚱한 생각이 들었다. PC에 있는 MIDI 파일을 X2의 내장 시퀀서에 직접 집어넣을 수는 없을까?

PC에서 MIDI 파일을 재생하면서 X2를 음원으로 사용하는 것은 간단하다. 내가 해 보려는 것은 그것이 아니라 Standard MIDI File(SMF)을 X2의 시퀀서 데이터로 변환하여 SysEx로 보내는 것이었다.

다행히 X2/X3 Reference Guide에는 MIDI implementation이 꽤 자세히 나와 있다. X2의 시퀀서는 10개의 Song(S0~S9)과 100개의 User Pattern(P00~P99)을 저장할 수 있으며, 이것을 ALL SEQUENCE DATA라는 하나의 SysEx로 덤프할 수 있다. 실제 덤프를 풀어 보니 control data 뒤에 4 byte 단위의 Note, Program Change, Control Change, Pitch Bend 등의 event가 이어진다. 그렇다면 MIDI 파일의 event를 이것으로 바꾸어 SysEx로 전환하여 주면 될 것 같았다. GM 전용으로 할당된 S9를 목적지로 해야 한다.

시험곡은 Olivia Newton-John의 Physical이었다. 결코 쉽지는 않았다. 특히 velocity를 잘못 해석한 버전에서는 음이 거의 나오지 않고 틱틱 강하게 튀는 소리만 났다. 매뉴얼과 실제 dump를 다시 비교하여 고친 뒤 전송하니 드디어 X2의 S9에서 Physical이 제대로 연주되었다. 124 BPM도 정확했다. tempo를 달리 설정하여 받은 dump들을 비교해 보니 실제 저장값은 BPM - 30이라는 것도 알게 되었다. 다음은 MIDI 파일을 SysEx로 전환하여 X2로 전송하여 시퀀서의 S9 영역에 넣은 다음 재생하는 모습을 촬영하는 것이다. 오디오와 비디오를 따로 기록한 뒤 합치는 바람에 싱크가 썩 잘 맞지는 않는다.



처음에는 변환할 때 X2에서 받아 놓은 기존 sequence dump를 template으로 사용했다. 그런데 생각해 보니 굳이 그럴 필요가 없었다. X2에는 전원을 켤 때 S0~S9과 P00~P99를 모두 지우는 기능이 있다. 그렇게 완전히 비운 뒤 바로 dump를 받으니 4,240 byte짜리 아주 작은 SysEx가 생겼다. X2 자신이 만들어 준 빈 시퀀서인 셈이다. 이것을 converter 안에 넣어 버렸다. 이제 MIDI 파일 하나만 주면 빈 X2 시퀀서를 만들고 S9에 곡을 채워 넣을 수 있다. 기존 dump를 template으로 주면 S0~S8과 Pattern은 그대로 두고 S9만 바꾸어 준다.

중간에 MIDI 전송 때문에 엉뚱한 곳에서 고생하기도 했다. 싸구려 USB-MIDI 케이블로 큰 SysEx를 보내면 MIDI-OX에서는 끝났다고 하는데 X2는 계속 Processing... 상태에 머물렀다. Mackie Onyx Producer 2•2의 MIDI 인터페이스 기능을 사용하자 문제가 사라졌다. 현재 MIDI-OX에서는 input buffer 256 bytes × 32, output buffer 1024 bytes × 128, Auto-adjust Buffer Delays를 켜 놓고 사용한다.



SysEx의 크기가 40KB 정도 넘어가면 버퍼가 부족하다는 에러 메시지가 자꾸 나와서 애를 먹었다. 그 원인으로서 Windows의 새로운 MIDI Server 기능도 의심했다. 그래서 관리자 권한으로 PowerShell을 열고 다음 명령을 실행하여 기존 Legacy MIDI 방식을 사용하도록 설정한 뒤 Windows를 재부팅했다.

reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32" /v UseLegacyMidi /t REG_DWORD /d 1 /f

재부팅 뒤에는 다음 명령으로 MidiSrv.exe가 실행되고 있는지 확인했다. 단, 재부팅 직후에는 보이지 않을 수 있다. 새 MIDI 서비스를 사용하는 프로그램이나 장치가 서비스를 요청하였을 때에만 tasklist에 보이는 것이 기본이라 한다. 

tasklist | findstr /I MidiSrv 

아무것도 출력되지 않는 것을 확인했다. 적어도 이 상태에서는 MidiSrv.exe가 실행되고 있지 않았다. 원래 설정으로 되돌리려면 같은 레지스트리 값을 0으로 바꾸고 다시 재부팅하면 된다.

reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32" /v UseLegacyMidi /t REG_DWORD /d 0 /f

다만 이것이 SysEx 전송 문제를 해결한 결정적인 조치였다고 보기는 어렵다. 나중에 USB-MIDI 케이블 대신 Mackie Onyx Producer 2•2의 MIDI 단자를 사용하자 전송이 안정되었기 때문이다. 따라서 당시 문제의 원인은 Windows MIDI Services보다는 사용하던 USB-MIDI 인터페이스였을 가능성이 더 크다.

지금 프로그램 이름은 midi_to_korg_x2_s9_v6_1.py이다. 너무 길다. 앞으로는 이름을 SyX2ool이라고 바꾸어 볼 생각이다. 이는 SYX + X2 + Tool의 합성어이자 말장난이다. 향후 다음과 같은 subcommand 방식으로 개발을 완결할 것이다.

예:

syx2ool import
syx2ool export
syx2ool analyze
syx2ool compare

아직 할 일이 있다. 지금은 MIDI 파일을 X2의 S9으로 보내는 방향이 중심인데, 다음에는 반대로 X2에서 받은 sequence dump의 S0~S8을 각각 SMF Format 1으로 변환해 보려고 한다. User Pattern을 사용한 부분은 실제 MIDI event로 풀어내야 하므로 조금 더 분석이 필요하다. 이것까지 되면 MIDI → X2 SysEx → MIDI의 왕복 변환도 시험할 수 있다.

이 정도면 리버스 엔지니어링이라고 거창하게 부를 일은 아니다. Korg가 옛날 매뉴얼에 자료를 상당히 잘 남겨 놓았다. 매뉴얼을 읽고, X2가 내놓는 byte를 비교하고, 프로그램을 고쳐서 다시 집어넣어 보는 일을 반복했을 뿐이다. 이 과정에서 ChatGPT의 도움을 많이 받았다.

그래도 30년 넘은 신시사이저가 내가 만든 데이터로 Physical을 연주하기 시작했을 때는 꽤 재미있었다. 이래서 오래된 기계를 쉽게 버리지 못한다.


2026년 10월 5일 월요일

[KORG X2] 오후 내내 RAG를 만지작거리다가 원래 자리로 돌아왔다

오늘 오전에는 Korg X2/X3 매뉴얼을 좀 더 편하게 찾아보기 위한 작은 프로그램을 만들었다(원본 글). 가지고 있는 매뉴얼 PDF는 오래된 스캔 자료라서 텍스트를 직접 검색할 수 없다. 우선 OCR을 거쳐 각 페이지의 글자를 추출하고, 어느 매뉴얼의 몇 번째 PDF 페이지에서 나온 글인지 알 수 있도록 JSON 파일로 정리하였다. 여기에 Ollama에서 로컬로 실행하는 qwen3:1.7b를 이용하여 한국어 질문을 검색에 적합한 영어 표현으로 바꾸고, 관련성이 높은 매뉴얼 페이지를 찾아주는 기능을 붙였다. 검색된 페이지는 원래 PDF의 모습 그대로 화면에서 볼 수 있게 하였다.

처음에는 검색된 내용을 다시 언어모델에 넘겨 질문에 대한 답까지 만들어 보기도 했다. 그런데 여기에서 작은 문제가 발견되었다. 검색된 원문에는 없는 용어나 수치를 언어모델이 그럴듯하게 만들어 답에 섞는 일이 있었다. 오래된 신시사이저의 사용법을 알아보려고 매뉴얼을 찾는 것인데, 없는 기능을 AI가 만들어내면 곤란하다. 그래서 AI가 답을 대신 써 주게 하는 것보다 관련된 원문 페이지를 잘 찾아서 내가 직접 읽는 것이 이 용도에는 더 안전하겠다는 생각이 들었다.

그렇게 해서 오전 작업의 결과물은 거창한 AI 챗봇이라기보다는 일종의 지능형 매뉴얼 검색기에 가까워졌다. 한국어로 질문하면 관련성이 높은 페이지 몇 개를 제시하고, 그중 하나를 선택하면 실제 매뉴얼 페이지를 보여준다. Basic Guide와 Reference Guide의 목차를 이용해서 직접 찾아 들어갈 수도 있다. 인터넷 연결도 필요 없고 API 사용료도 들지 않는다. 드럼 키트의 편집 위치나 snare drum의 pitch 조정처럼 구체적인 질문에는 꽤 쓸 만한 페이지를 찾아 주었다. 여기까지만 해도 처음 원했던 것은 거의 이루어진 셈이었다.

그런데 오후가 되자 욕심이 생겼다. 예를 들어 “왼손으로는 베이스, 오른손으로는 피아노를 연주하려면 어떻게 하나?”와 같은 질문을 생각해 보았다. 사람이라면 이것이 건반을 두 영역으로 나누는 split 설정에 관한 질문이라는 것을 쉽게 알아듣는다. Korg X2의 구조를 조금 아는 사람이라면 Combination에서 각 Timbre의 Key Window를 설정하는 부분을 찾아야 한다는 것도 짐작할 수 있다. 그러나 작은 언어모델과 단순한 검색의 조합은 반드시 그렇게 생각하지 않았다.

여기에서 오후의 삽질이 시작되었다. 요즘 문서 기반 AI를 이야기하면 빠지지 않고 등장하는 것이 RAG(Retrieval-Augmented Generation), 즉 검색 증강 생성이다. 오전에 만든 프로그램도 넓게 보면 검색한 원문을 언어모델과 연결한다는 점에서 아주 단순한 RAG라고 할 수 있다. 그렇다면 조금 더 제대로 된 RAG 방식을 적용하면 검색 성능이 좋아지지 않을까 하는 생각이 들었다.

우선 페이지 전체를 검색 단위로 삼는 것이 문제일 수 있다고 생각하여 매뉴얼의 OCR 텍스트를 작은 덩어리, 즉 chunk로 나누었다. Basic Guide와 Reference Guide를 합쳐 모두 609개의 chunk가 만들어졌다. 결과를 직접 살펴보니 나누어진 모양 자체는 제법 괜찮았다. Split과 관련된 Key Window 설명도 적절한 덩어리로 잡혔고, snare drum의 Tune이나 tempo 설정에 관한 설명도 잘 나뉘어 있었다.

다음에는 각 chunk의 의미를 숫자로 표현하는 embedding을 만들었다. Ollama에서 nomic-embed-text 모델을 사용하였다. 609개의 chunk를 모두 embedding하는 데 내 노트북에서 약 249초가 걸렸다. 질문도 같은 방법으로 벡터로 만들면 단어가 정확하게 일치하지 않더라도 의미가 비슷한 설명을 찾을 수 있을 것이라고 기대하였다.

여기에 CrossEncoder라는 것도 동원하였다. embedding 검색으로 우선 후보를 뽑고, 질문과 각각의 후보를 다시 함께 비교하여 관련성을 좀 더 정밀하게 평가하는 reranking 방식이다. 문서 검색에서는 이미 널리 사용되는 전형적인 2단계 구조라고 한다. 처음에는 609개 chunk를 전부 CrossEncoder로 비교해 보았는데 너무 느렸고, 그래서 embedding으로 상위 20개 후보를 먼저 고른 뒤 그 후보만 다시 순위를 매기는 방식으로 바꾸었다. 어느새 오래된 신시사이저 매뉴얼을 좀 편하게 읽겠다는 일이 작은 정보검색 실험으로 변하고 있었다.

결과는 흥미로웠다. Snare pitch나 tempo처럼 질문과 매뉴얼의 용어가 비교적 잘 대응하는 경우에는 아주 잘 작동하였다. 정답에 해당하는 chunk가 embedding 검색에서 처음부터 1위에 들어왔고 reranking을 거친 뒤에도 1위를 유지하였다. 하지만 정작 개선하고 싶었던 split 질문은 그렇지 않았다. 관련된 Key Window chunk 하나가 embedding 검색 후보 16위에 겨우 들어왔고 reranking 뒤에는 5위가 되었다. 더 직접적으로 관련된 다른 chunk는 상위 20개 후보에도 들어오지 못했다. 엉뚱한 effect 관련 설명이 최종 1위를 차지하는 경우도 있었다.

검색 한 번에는 3초 남짓이 걸렸다. 오전에 만든 단순한 검색보다 구조는 훨씬 복잡해졌지만 결과가 그만큼 좋아졌다고 하기는 어려웠다. “왼손은 베이스, 오른손은 피아노”라는 일상적인 표현과 “Combination mode의 Timbre별 Key Window”라는 Korg X2의 전문 용어 사이에는 상당한 의미의 간격이 있다. 문서를 잘게 나누고 벡터를 만들고 순위를 다시 매긴다고 해서 그 간격이 저절로 사라지는 것은 아니었다.

그러다 문득 내가 왜 이 일을 하고 있는지를 다시 생각하게 되었다. 내가 필요한 것은 Korg X2에 관한 질문이라면 무엇이든 대답하는 인공지능이 아니다. 오래된 매뉴얼 두 권에서 내가 읽어야 할 페이지를 빨리 찾아주는 도구가 필요했을 뿐이다. 그렇게 생각하고 나니 오전에 만든 단순한 프로그램이 다시 달리 보였다.

질문을 입력하면 관련성이 높은 페이지 세 개 정도가 나온다. 그중 하나를 선택하여 원본 매뉴얼을 읽고, 설명이 앞뒤로 이어진다면 화살표를 눌러 한 페이지씩 넘겨 보면 된다. 결국 오후 늦게 프로그램에 추가한 가장 유용한 기능은 복잡한 RAG 기법이 아니라 PDF 페이지를 앞뒤로 넘기는 좌우 화살표였다. PDF를 작게 만드는 별도의 버튼도 처음에는 만들어 보았지만 그것조차 필요 없었다. 브라우저 창의 폭을 조절하면 PDF도 선명한 상태로 따라서 줄어든다. 몇 시간 동안 embedding, chunking, reranking을 돌아다닌 뒤 도착한 곳은 결국 책에서 관련 페이지를 찾아 앞뒤로 넘겨 읽는 방식이었다.

오늘 오후의 경험에서 얻은 교훈은 RAG나 embedding의 원리를 조금 더 알게 되었다는 것만은 아니다. 오히려 이미 잘 알려진 문제를 너무 처음부터 다시 풀려고 했다는 생각이 들었다. 문서 검색에는 오랫동안 사용되어 온 방법이 있고, embedding 검색과 reranking 역시 각각 어디에서 유용하고 어떤 한계를 갖는지 많은 사람이 이미 경험하였다. 그런데 AI가 코드를 척척 만들어 주니 “이것이 잘 안 되면 이것도 붙여 보자”는 식으로 하나씩 직접 시험하게 되었고, 어느 순간 남들이 이미 겪은 시행착오를 작은 Korg 매뉴얼 두 권을 가지고 다시 재현하고 있었다.

생각해 보면 AI를 이용한 프로그래밍에서 이것은 꽤 조심해야 할 점이다. 예전에는 새로운 방법을 시험하려면 코드를 작성하는 비용이 컸기 때문에 시작하기 전에 방법을 충분히 조사할 수밖에 없었다. 지금은 AI에게 부탁하면 몇 분 안에 다음 실험을 위한 코드가 나온다. 구현 비용이 낮아진 덕분에 오히려 충분히 조사하지 않고 여러 방법을 차례로 시험해 보는 일이 쉬워졌다. 코드를 빨리 만들 수 있다는 것과 문제를 빨리 해결한다는 것은 같은 뜻이 아니다.

다음에는 순서를 조금 바꾸어야겠다. 먼저 내가 풀려는 문제가 이미 어떤 이름으로 불리는지 알아보고, 그 문제에 널리 쓰이는 가장 단순한 방법이 무엇인지 찾아보는 것이 먼저다. 그것을 구현하여 실제로 써 본 뒤 부족한 점이 확인되었을 때에만 다음 단계를 추가하면 된다. AI 시대에는 코드를 만드는 비용이 크게 낮아졌다. 그래서 역설적으로 무엇을 더 만들 것인가보다 무엇을 만들지 않을 것인가를 판단하는 일이 더 중요해졌는지도 모르겠다.

609개의 chunk를 embedding하느라 노트북이 249초 동안 열심히 일한 것은 아마 그것을 배우기 위한 수업료였을 것이다. 다행히 API 사용료는 들지 않았다. 전기료는 조금 들었겠지만.

[KORG X2] 거창한 RAG 챗봇을 만들려다가 소박한 매뉴얼 검색기 구현으로 끝내다

며칠 전 오래된 Korg X2/X3 신시사이저의 매뉴얼을 뒤적이다가 한 가지 생각을 했다. Basic Guide와 Reference Guide를 AI에게 모두 읽혀 놓고 한국어로 질문하면 매뉴얼을 근거로 답해 주는 개인용 챗봇을 만들 수 있지 않을까? 요즘 흔히 말하는 RAG(Retrieval-Augmented Generation)를 로컬 PC에서 구현하면 될 것 같았다. 매뉴얼에서 질문과 관련된 내용을 검색하고, 그것을 로컬에서 실행되는 LLM에 넘겨 답을 만들게 하는 것이다. 별도의 API 사용료 없이 내 노트북에서 모든 것을 처리한다는 것도 매력적으로 느껴졌다.

처음 기대한 것은 제법 그럴듯했다. “드럼 키트는 어디에서 편집하지?”, “패턴을 트랙에 넣으려면?”, “MIDI로 Program을 선택하는 방법은?”과 같이 한국어로 물어보면 AI가 매뉴얼에서 근거를 찾아 답해 주는 시스템을 생각했다. 그러나 며칠 동안 작은 모델과 임베딩, OCR, 여러 단계의 답변 생성 방법을 시험해 본 끝에 결과물은 처음 구상과 상당히 달라졌다. 내 노트북의 제한된 자원으로 무엇을 할 수 있고, 무엇을 굳이 하지 않는 편이 나은지를 알아 가면서 목표 자체가 바뀌었기 때문이다. 내가 쓰는 노트북은 2022년 여름 용산에서 구입한 ThinkPad E14 Gen3이다(구입 당시 쓴 글).

Python 작업 환경부터 만들기

Windows에서 프로젝트 폴더를 하나 만들고 Python 가상환경(venv)을 만들었다. Python은 3.11을 사용했다. PowerShell에서 프로젝트 디렉터리로 이동한 다음 다음과 같이 가상환경을 만들고 활성화하였다.

python -m venv .venv
.\.venv\Scripts\Activate.ps1

PowerShell의 실행 정책 때문에 활성화가 막힌다면 현재 세션에 한해서 다음과 같이 허용할 수 있다.

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\.venv\Scripts\Activate.ps1

필요한 Python 패키지도 설치하였다. 최종적으로 남은 프로그램만 생각한다면 다음 정도면 된다.

python -m pip install --upgrade pip
pip install streamlit pymupdf requests pillow pytesseract

PDF가 스캔 이미지이므로 OCR을 위해 Tesseract도 별도로 설치했다. 여기에서 처음 접하는 사람이라면 조금 헷갈릴 수 있는데, pip install pytesseract로 설치되는 것은 OCR 프로그램 자체가 아니다. pytesseract는 Python에서 Tesseract를 호출하기 위한 인터페이스이고, 실제 Tesseract OCR 프로그램은 Windows에 따로 설치해야 한다.

처음에는 임베딩을 이용한 검색도 시도했기 때문에 다음 패키지도 설치하였다.

pip install sentence-transformers numpy

그러나 이것들은 최종 프로그램에서는 사용하지 않게 되었다. 시행착오를 그대로 재현하려는 것이 아니라면 설치할 필요가 없다.

스캔한 매뉴얼을 검색할 수 있게 만들기

내가 가지고 있는 Korg X2/X3 매뉴얼은 텍스트가 포함된 PDF가 아니라 스캔한 문서다. 따라서 PDF 파일을 열었다고 해서 Drum Kit나 Pattern 같은 단어를 곧바로 검색할 수 있는 것은 아니었다. PyMuPDF로 PDF의 각 페이지를 읽어 이미지로 만들고 Tesseract로 OCR을 수행한 뒤, 페이지별로 추출된 텍스트를 manual_index.json이라는 파일에 저장했다.

구조를 단순하게 표현하면 다음과 같다.

Basic Guide
  PDF page 1 → OCR text
  PDF page 2 → OCR text
  ...

Reference Guide
  PDF page 1 → OCR text
  PDF page 2 → OCR text
  ...

OCR 결과는 물론 완벽하지 않았다. 오래된 영문 매뉴얼을 읽히다 보니 170을 17O로 읽거나 171이 전혀 엉뚱한 문자로 변하는 일도 있었다. 그래도 내가 원하는 것은 완벽한 전자책을 만드는 것이 아니라 관련 페이지를 찾는 것이므로, Drum Kit, Pattern, MIDI Data Dump, Program Change 같은 기술 용어가 대체로 제대로 인식되는 정도면 충분했다.

RAG라면 임베딩부터 해야 하는 줄 알았다

RAG라는 말을 처음 접하면 문서를 잘게 나누고 임베딩(IBM의 짧은 설명)을 만들어 벡터 검색을 해야 할 것 같은 생각부터 든다. 나도 그렇게 시작했다. paraphrase-multilingual-MiniLM-L12-v2를 사용하여 288페이지의 매뉴얼을 384차원의 벡터로 만들고 manual_embeddings.npy라는 파일로 저장하였다. 한국어로 질문해도 의미가 비슷한 영문 매뉴얼 페이지를 찾아줄 것이라고 기대했다.

여기서 ‘문서를 잘게 나눈다’는 것은 긴 문서 전체를 한꺼번에 검색 대상으로 삼지 않고, 몇 문단이나 한 페이지 정도의 작은 단위로 쪼개는 것을 뜻한다. 그리고 ‘임베딩(embedding)’은 각각의 작은 문서 조각을 그 내용의 특징을 나타내는 여러 개의 숫자로 바꾸는 과정이다. 이렇게 만들어진 숫자의 묶음을 벡터(vector)라고 한다. 질문도 같은 방법으로 벡터로 바꾼 뒤, 질문 벡터와 가까운 문서 벡터를 찾으면 단어가 정확히 일치하지 않아도 의미가 비슷한 내용을 찾을 수 있다. 이것이 여기서 말하는 벡터 검색이다.

그런데 실제로 시험해 보니 이 매뉴얼에서는 생각만큼 만족스럽지 않았다. 내가 찾고 싶은 것은 문장의 추상적인 의미가 비슷한 페이지라기보다 Drum Kit Setup, Put to Track, Program Change, MIDI Data Dump처럼 매뉴얼에 실제로 쓰인 기술 용어가 등장하는 곳이었다. 그렇다면 굳이 모든 페이지를 벡터로 바꾸어 의미상의 거리를 계산하기보다, 한국어 질문을 매뉴얼에서 사용될 법한 영어 검색어로 잘 바꾼 다음 전통적인 문자열 검색을 하는 편이 나을 수도 있었다.

이것은 이번 작업에서 처음으로 목표를 크게 줄인 지점이었다. 임베딩 검색이 나쁜 기술이라는 뜻은 아니다. 내가 가진 자료의 양과 성격, 그리고 찾으려는 정보의 종류에는 더 단순한 방법이 잘 맞았다는 뜻이다.

작은 로컬 LLM에게 너무 많은 일을 시켰다

로컬 LLM은 Ollama를 통해 실행했다. 처음에는 Qwen 모델에게 질문을 영어 검색어로 바꾸는 일뿐 아니라 검색된 매뉴얼 내용을 읽고, 적절한 근거인지 판단하고, 마지막에는 한국어 답변까지 작성하도록 했다. 관련 없는 질문을 걸러 내는 relevance gate도 붙여 보고, 한 번의 호출로 잘 안 되면 두 번, 세 번에 나누어 일을 시키는 방법도 시험했다.

Qwen은 중국의 Alibaba Cloud가 개발하는 AI 언어 모델 계열이고, Ollama는 미국의 Ollama가 개발하는 로컬 AI 모델 실행 소프트웨어다. Qwen 자체는 일반 응용 프로그램이라기보다 문장을 이해하고 생성하도록 학습된 AI 모델이며, Ollama는 Qwen을 비롯한 여러 언어 모델을 내 컴퓨터에 내려받아 쉽게 실행하고 다른 프로그램에서 호출할 수 있게 해 준다. 이번 작업에서는 Ollama를 설치하고, 이를 통해 비교적 작은 Qwen 3 계열의 1.7B 모델(qwen3:1.7b)을 내 노트북에서 실행하였다.

문제는 내 노트북에 별도의 GPU가 없다는 것이다. Qwen 1.7B 정도의 작은 모델은 CPU만으로도 비교적 부담 없이 실행되었지만, 매뉴얼을 정확하게 해석하여 답을 만드는 일에서는 신뢰하기 어려운 경우가 있었다. 원문에는 분명히 Global Mode라고 적혀 있는데 답을 만드는 과정에서 다른 모드로 바꾸어 말하는 식의 오류가 생겼다. 더 큰 4B급 모델도 시험했지만 이번에는 기다리는 시간이 현실적인 문제가 되었다. 좋은 답 하나를 얻기 위해 매번 오래 기다려야 한다면 매뉴얼을 직접 펼쳐 보는 것보다 나을 것이 없다.

그렇다고 작은 모델이 쓸모없는 것은 아니었다. 오히려 일을 하나만 시키니 제법 잘했다. “답하지 말고, 한국어 질문을 이 영문 매뉴얼에서 검색하기 좋은 영어 단어로 바꾸어라”라고 역할을 제한한 것이다. 예를 들어 “드럼 키트를 편집하려면?”이라는 질문을 넣으면 drum kit edit setup global mode와 같은 검색어를 만들어 주고, “패턴을 트랙에 넣으려면?”이라고 하면 pattern put to track assign pattern track과 같은 결과를 내놓았다. 이 정도의 일은 1.7B 모델도 빠르고 제법 안정적으로 해냈다.

결국 검색 알고리즘은 아주 단순해졌다

LLM이 영어 검색어를 만들어 주고 나면 그다음부터는 AI라고 부를 만한 것도 별로 없다. OCR한 각 페이지에서 검색어가 얼마나 많이 등장하는지를 세고 점수를 주었다. 검색어 전체가 그대로 등장하면 추가 점수를 주는 정도의 단순한 방식이다.

핵심 아이디어를 단순화하면 다음과 같다.

def score_page(text, query):
    text = text.lower()
    query = query.lower()

    score = 0

    if query in text:
        score += 100

    for term in query.split():
        score += text.count(term) * 5

    return score

이렇게 해도 의외로 결과가 괜찮았다. 예를 들어 GM Song을 재생하는 방법을 묻는 질문에서 LLM이 gm song play라는 검색어를 만들면 Basic Guide의 Playing GM Songs가 있는 페이지가 상위에 나온다. 드럼 키트 편집을 물으면 Reference Guide의 Global Mode에 있는 Drum Kit Setup 페이지가 잘 검색된다. 기술 매뉴얼에서는 용어 자체가 상당한 정보를 가지고 있기 때문에 가능한 일일 것이다.

AI에게 답을 쓰게 하지 말고 원본 페이지를 보여 주자

여기에서 다시 한 번 방향을 바꾸었다. 검색된 OCR 텍스트를 작은 LLM에게 넘겨 답을 작성하게 하는 대신, 검색된 원본 PDF 페이지를 그대로 브라우저에 보여 주기로 했다. OCR은 어디까지나 검색용으로만 사용하고, 사람이 실제로 읽는 것은 스캔된 원래 매뉴얼이다.

이렇게 하니 여러 문제가 한꺼번에 사라졌다. OCR이 일부 문자를 잘못 인식하더라도 검색만 성공하면 원본 페이지에서 정확한 내용을 확인할 수 있다. 작은 LLM이 근거 문장을 잘못 해석하거나 그럴듯한 설명을 덧붙이는 문제도 없다. 무엇보다 내가 원하는 것은 Korg X2에 대해 유창하게 설명하는 AI가 아니라, 200쪽이 넘는 Reference Guide에서 필요한 페이지를 빨리 찾는 도구라는 사실이 분명해졌다.

결국 현재 프로그램의 처리 과정은 다음과 같이 단순해졌다.

한국어 질문
    ↓
Qwen 1.7B
    ↓
영문 매뉴얼용 검색어
    ↓
OCR 텍스트 검색
    ↓
관련 페이지 선정
    ↓
원본 PDF 페이지 표시

전형적인 RAG라면 마지막 단계에서 검색된 문서를 LLM에 다시 넣고 답변을 생성할 것이다. 내 프로그램은 그 단계를 아예 없애 버렸다. 따라서 이제 이것을 RAG 챗봇이라고 부르는 것은 적절하지 않다. “자연어로 매뉴얼 검색” 정도가 지금 하는 일을 가장 정확하게 표현한다.

Streamlit으로 검색 화면 만들기

사용자 인터페이스는 Streamlit으로 만들었다. 프로그램을 실행하는 방법은 간단하다.

streamlit run app.py

브라우저에는 Search, Basic Guide, Reference Guide의 세 탭이 나타난다. Search 탭에서 한국어나 영어로 궁금한 내용을 입력하면 관련도가 높은 Basic Guide와 Reference Guide 페이지를 각각 찾아 준다. 검색 결과 가운데 하나를 선택하면 바로 아래에 원본 PDF 페이지가 표시되고, 필요하면 앞뒤 페이지도 함께 볼 수 있게 하였다.

Basic Guide와 Reference Guide 탭은 전자 목차처럼 만들었다. 원래 매뉴얼의 Table of Contents를 OCR한 뒤 오류가 난 페이지 번호를 확인하여 별도의 toc.json으로 정리했다. Chapter와 Section을 선택하면 해당 원본 페이지로 바로 이동한다. 오래된 종이 매뉴얼을 스캔한 PDF가 이제는 검색과 목차 이동이 가능한 작은 웹 애플리케이션이 된 셈이다.

시행착오가 사라지고 남은 파일들

개발 중에는 여러 방법을 시험하느라 ask_manual_2call.py, ask_manual_3call_gate.py, ask_manual_grounded.py, search_embedding.py, build_embeddings.py 같은 파일이 계속 생겨났다. 이름만 보아도 작은 LLM에게 어떻게든 정확한 답을 만들어 내게 하려고 애쓴 흔적이 남아 있었다. 최종 방향을 정한 뒤에는 이런 실험용 파일과 임베딩 데이터도 모두 지웠다.

현재 남아 있는 것은 다음 정도다.

x2-assistant/
│
├─ .venv/
├─ manuals/
│  ├─ basic.pdf
│  └─ reference.pdf
│
├─ app.py
├─ build_index.py
├─ manual_index.json
└─ toc.json

app.py가 Streamlit 애플리케이션이고, manual_index.json에는 검색용 OCR 텍스트가 들어 있다. toc.json은 두 매뉴얼의 목차 이동에 사용하며, build_index.py는 나중에 PDF에서 OCR 인덱스를 다시 만들어야 할 경우를 대비해 남겨 두었다. 처음 생각했던 시스템에 비하면 놀랄 만큼 단출하다.

API, 로컬 LLM, RAG를 직접 만져 보면서

이번 일을 시작하기 전에는 API를 이용하는 AI와 내 컴퓨터에서 직접 돌리는 LLM의 차이, RAG에서 retrieval과 generation이 각각 무슨 역할을 하는지, 임베딩 검색이 왜 필요한지 같은 개념을 막연하게만 알고 있었다. 직접 만들어 보니 이런 용어들이 조금씩 구체적으로 느껴졌다. 특히 LLM을 사용한다고 해서 모든 단계를 LLM에게 맡길 필요는 없다는 점이 인상적이었다.

성능 좋은 외부 AI의 API를 사용했다면 검색된 몇 페이지를 넘겨서 꽤 훌륭한 답을 만들 수도 있었을 것이다. 그러나 이번에는 별도의 API 비용 없이 내 노트북 안에서 해결하는 것이 조건이었다. 그렇다면 CPU에서 작은 모델이 잘할 수 있는 일과 기존 프로그램이 훨씬 잘할 수 있는 일을 나누는 것이 합리적이다. 한국어 질문을 영어 기술 용어로 바꾸는 것은 작은 LLM에게 맡기고, 단어를 세어 페이지를 찾는 일은 평범한 Python 코드에 맡기며, 최종 판단은 원본 문서를 읽는 사람이 하도록 했다.

거창하게 시작했지만 이 정도가 오히려 쓸 만하다

처음에는 “내 노트북에서 돌아가는 Korg X2 전용 RAG 챗봇”을 생각했다. 임베딩을 만들고, 관련 문장을 추출하고, relevance gate를 붙이고, LLM을 여러 번 호출하면서 어떻게든 그럴듯한 답을 만들어 보려고 했다. 그러나 CPU만 사용하는 노트북에서 큰 모델을 돌리는 데에는 한계가 있었고, 작은 모델에게 복잡한 판단까지 맡기면 정확도가 마음에 들지 않았다. 결국 많은 기능을 하나씩 걷어 내고 작은 LLM, 단순한 문자열 검색, OCR 인덱스와 PDF 뷰어만 남겼다.

결과적으로 목표는 상당히 작아졌지만 실제 용도에는 오히려 더 잘 맞는다. 내가 필요한 것은 30년 된 신시사이저에 대해 AI와 대화를 나누는 것이 아니라, “Put to Track이 어디에 있었지?”라고 물었을 때 Reference Guide의 해당 페이지를 바로 펼쳐 주는 도구이기 때문이다. 제한된 컴퓨터 자원 때문에 타협했다고 생각할 수도 있지만, 며칠 동안 이것저것 만들어 보고 지우면서 느낀 것은 조금 다르다. AI를 얼마나 많이 사용하는가보다, AI에게 무슨 일을 맡기고 무슨 일은 맡기지 않을지를 정하는 것이 더 중요했다.

'자연어로 매뉴얼 찾기'는 약간 과장이다.

이번 작업은 거창한 AI 개발 프로젝트라기보다 AI를 직접 만져 본 나의 첫 작은 실험에 가까웠다. 그동안 AI를 이용하거나 관련 이야기를 접할 기회는 많았지만, 로컬 LLM을 직접 설치하고 임베딩을 만들어 검색해 보고, 작은 모델에게 답변을 시키면서 그 한계를 확인해 본 것은 이번이 처음이었다. 그런데 그 첫 경험이 업무에서가 아니라, 30년 된 신시사이저의 매뉴얼을 좀 더 편하게 찾아보겠다는 취미 프로젝트에서 이루어졌다는 점도 재미있다. 모든 일을 AI에게 맡기기보다 AI가 잘하는 작은 역할만 맡기고 나머지는 기존의 단순한 프로그램으로 처리하는 편이 더 나을 때가 있다는 것도 직접 확인했다. RAG나 임베딩, 로컬 LLM 같은 용어 역시 글로 읽을 때보다 직접 만들고 실패해 보니 훨씬 구체적으로 이해할 수 있었다.

이제 X2를 Ardule에서 어떻게 써먹을까?

이렇게 매뉴얼을 다시 들여다보고 SysEx와 MIDI 구조까지 조금씩 이해하게 된 이유는 결국 하나다. 30년이나 된 Korg X2를 지금 내가 만들고 있는 Ardule 생태계에서 어떻게 활용할 수 있을까? X2의 시퀀서나 패턴 기능을 오늘날의 소프트웨어로 그대로 흉내 낼 필요는 없을 것이다. 그런 일은 Raspberry Pi와 소프트웨어가 훨씬 자유롭게 할 수 있다. 대신 X2에는 지금도 쓸 만한 고유한 음색과 드럼 키트, Program과 Combination이 있고, MIDI와 SysEx를 이용하면 외부에서 이들을 꽤 세밀하게 제어할 수 있다.

따라서 Ardule에서는 FluidSynth와 SoundFont를 주된 음원으로 사용하면서 X2를 선택적으로 불러 쓰는 외부 하드웨어 음원으로 두는 것이 재미있을 것 같다. Ardule이 곡이나 연주 상황에 따라 MIDI 채널을 배분하고 Program이나 Combination을 선택하며, 필요한 경우 미리 준비한 SysEx를 보내 X2의 상태를 설정하는 식이다. 오래된 X2의 패턴을 분석하여 유용한 리듬은 Ardule 쪽의 패턴 라이브러리로 가져올 수도 있다. 그렇게 하면 X2의 낡은 시퀀서를 억지로 중심에 놓지 않으면서도 그 안에 들어 있는 소리와 데이터는 계속 활용할 수 있다.

어쩌면 이번 매뉴얼 검색기 만들기도 그 과정의 일부였던 셈이다. 1990년대의 신시사이저와 Raspberry Pi, Arduino, SoundFont, 그리고 이제는 로컬 LLM까지 한데 섞이기 시작했다. 서로 만들어진 시대도 다르고 원래 함께 쓰라고 만들어진 물건들도 아니지만, 필요한 부분만 골라 연결하는 것이 내가 생각하는 Ardule의 재미다. X2가 언제까지 정상적으로 작동할지는 모르겠지만, 적어도 당분간은 창고로 들어갈 이유가 하나 더 줄었다.

다음은 X2 하판을 고정하는 screw boss를 보강한 어제의 작업 결과를 사진으로 남긴 것이다. 


분해 조립을 자주 하면서 플라스틱으로 만들어진 나사산도 많이 뭉개지고, 몇 개의 보스는 갈라져 버렸다. 여기에 알리익스프레스에서 구입한 내경 8mm 스틸 무나사 스페이서를 끼워서 더 이상 갈라지지 않게 보강한 것이 주요 내용이다. 내경 9mm짜리를 구입했더라면 보스의 바깥을 갈아내느라 고생을 하지 않아도 되었을 것이다. 들어가다 만 것을 빼느라 플라이어로 이 금속 부품을 꽉 잡고 좌우로 돌려서 비틀었더니 보스 하나가 부러지는 사고를 치는 바람에 응급 수술도 하였다.


아직 뭉개진 나사산에 대한 보수 작업은 하지 않은 상태이다. 망가진 X2의 플로피 드라이브를 대신할 에뮬레이터를 구입할지도 아직 결정하지 못하였다. 이것이 있다면 USB 메모리를 이용하여 설정 상태를 백업하고 복원하는 일이 매우 편해진다. 모든 것을 SysEx 전송으로 해결할 수도 있지만 MIDI 자체의 전송 속도가 느리기 때문이다. 그나마 ChatGPT의 도움을 받아 KORG X2/X3의 SysEx 데이터와 SNG 파일 구조를 분석하는 리버스 엔지니어링 작업을 훨씬 수월하게 할 수 있다는 것이 다행이다.

2026년 9월 29일 화요일

회의는 AI가 다시 정리해 준다



부제: 게으른 국외출장자를 위한 영어 녹음·전사·요약 워크플로

생물학자에게 전사(transcription)라는 단어는 아주 특별한 의미로 각인되어 있다. 바로 DNA를 주형으로 RNA를 만드는 과정을 뜻한다. 중심원리(central dogma)를 처음 배울 때부터 DNA → RNA → Protein이라는 도식과 함께 전사와 번역(transcription and translation)을 수도 없이 외웠으니 그럴 만도 하다.

그래서 요즘 AI 서비스를 이야기하면서 “회의를 녹음해서 전사한다”라는 표현을 접하면 처음에는 조금 묘한 기분이 든다. 나에게 전사란 RNA polymerase가 하는 일이었으니까.

그러나 전사(轉寫)라는 말의 본래 의미를 생각하면 이상할 것이 없다. 영어 transcribe는 라틴어 transcribere에서 왔으며, trans-는 ‘건너서, 다른 쪽으로’, scribere는 ‘쓰다’를 뜻한다. 즉 본래 의미는 어떤 것을 다른 형태로 옮겨 적는 것이다. 한자어 轉寫도 말 그대로 ‘옮겨 쓴다’는 뜻이다.

DNA의 염기서열 정보를 RNA라는 다른 매체에 옮겨 적는 것도 transcription이고, 회의실에서 사람이 한 말을 문자로 옮겨 적는 것도 transcription이다. 생물학자에게 익숙한 전사가 오히려 이 넓은 의미의 한 사례인 셈이다.

그리고 이번 국외출장에서 새삼 깨달은 것이 있다.

AI-assisted transcription, 즉 AI를 이용한 전사는 출장 기록의 방식을 꽤 크게 바꿀 수 있다.

요즘 업무 회의를 마친 뒤 젊은 연구원들이 녹음 파일과 함께 AI가 자동으로 요약해 준 문서를 전달해 줄 때가 많다. 이처럼 AI를 이용하여 업무 효율화를 이루고 있는데, 나도 여기에 동참해야 하지 않겠는가. 그래서 이번에 싱가포르에서 열린 제14회 GA4GH Plenary에 참석하면서 수립한 워크플로를 글로 정리해 보았다. 미리 계획을 세우거나 조사한 것은 아니다. 회의장 테이블에서 발표내용을 기록하던 도중에 이리저리 검색하고 테스트하여 완성하였다. 따라서 이보다 더욱 효율적이면서도 정확한 기록 방법이 얼마든지 있을 수 있음을 미리 일러 둔다. 


출장보고서를 위해 회의 내용을 받아 적을 필요가 있을까

국외출장을 다녀오면 마지막에 남는 숙제가 있다. 출장보고서다.

회의 중에는 발표를 듣고, 슬라이드를 보고, 메모도 하고, 발표가 끝나면 사람들과 이야기도 해야 한다. 영어 발표라면 집중력도 더 필요하다. 그런데 이 모든 일을 하면서 동시에 “이 내용은 나중에 보고서에 써야 하니 적어놓자”고 생각하는 것은 상당히 피곤한 일이다.

이번 출장에서는 조금 다른 방법을 시험했다.

회의는 녹음한다. 슬라이드는 사진으로 남긴다. 그리고 나중에 AI에게 회의를 다시 정리하게 한다.

이때 가장 중요한 중간 단계가 바로 전사였다.

음성 녹음만 잔뜩 가지고 있어서는 활용하기 어렵다. 한 시간짜리 녹음을 다시 한 시간 동안 들으면서 필요한 내용을 찾는다면 AI를 사용하는 의미가 별로 없다. 음성을 검색하고 분석할 수 있는 텍스트로 바꾸어 놓아야 한다.

음성 → 전사된 텍스트 → 슬라이드와 결합 → AI에 의한 재구성

Otter와 Subtitle Edit는 쓰임새가 조금 다르다

영어 회의를 녹음하고 전사한다고 하면 먼저 떠오르는 서비스 중 하나가 Otter.ai다. 회의 녹음과 전사를 중심으로 만들어진 서비스라서 전사 결과를 확인하고 화자를 구분하며 회의 내용을 정리하는 데 편리하다. 온라인 회의나 협업 환경에서 쓰기에도 좋다. 나도 2년 전 워싱턴 DC 출장(AI-바이오과학 협력회의)에서는 Otter를 꽤 요긴하게 사용했었다.

그런데 이번 출장에서 내가 원했던 것은 조금 달랐다.

이미 녹음해 둔 한두 시간짜리 영어 음성 파일이 여러 개 있고, 이것을 인터넷 연결 상태에 크게 구애받지 않고 내 노트북에서 처리하고 싶었다.

여기에는 오픈소스 프로그램인 Subtitle Edit가 의외로 아주 잘 맞았다. 이름 그대로 원래 동영상 자막을 만들고 편집하는 프로그램이다. 하지만 이 프로그램 안에 Whisper 계열 음성인식 엔진을 이용하면 동영상뿐 아니라 녹음 파일을 자동으로 전사하는 데도 사용할 수 있다.

그리고 결과물로 SRT 자막 파일을 얻을 수 있다는 것이 이번 용도에는 아주 좋았다.

00:23:14 → 00:23:21
발표자가 이 시간에 한 말...

SRT에는 이렇게 시간 정보가 붙는다. 처음에는 그저 자막을 위한 시간표시라고 생각했지만, 나중에는 이것이 출장 기록에서 대단히 유용한 정보가 되었다.

Whisper 모델이란 무엇인가

Subtitle Edit 자체가 사람 말을 알아듣는 것은 아니다. 실제 음성인식을 담당하는 것이 Whisper다.

Whisper는 OpenAI가 공개한 음성인식 모델이다. 사람의 음성을 입력받아 문자로 변환하는 speech-to-text 모델이며, 여러 언어와 다양한 녹음 환경을 처리할 수 있다.

Subtitle Edit 프로그램에서 녹음 파일(MP3, M4A, WAV 등)을 연 뒤 Video → Audio to text (Whisper) 메뉴로 들어가 음성 인식 엔진으로 whisper.cpp를 선택한다. 처음 사용하는 경우 필요한 Whisper 실행 파일과 음성 인식 모델을 내려받아야 하는데, 나는 영어 회의 전사를 위해 **medium 모델(약 1.5GB)**을 사용했다. 모델이 클수록 일반적으로 인식 정확도는 좋아지지만 처리 시간과 메모리 사용량도 늘어나므로, 노트북에서 빠르게 처리하려면 small이나 medium 정도가 현실적이다. 언어는 회의가 영어라면 English로 명시해 주는 편이 좋고, 자동 감지에 맡길 수도 있다. 설정을 마치고 Generate를 누르면 Subtitle Edit가 녹음 파일을 구간별로 분석하여 자막을 만들며, 결과는 화면에서 바로 수정할 수 있고 SRT 파일로 저장할 수 있다. SRT에는 각 발화의 시간 정보가 함께 들어 있으므로, 나중에 AI에게 회의 내용을 요약시키면서 특정 발언이 녹음의 어느 부분에 해당하는지 추적하기에도 편리하다.

Whisper에는 크기가 다른 여러 모델이 있다. 일반적으로 작은 모델은 계산이 빠르고 필요한 컴퓨터 자원이 적은 대신 인식 정확도에서 손해를 볼 수 있고, 큰 모델은 처리 시간이 길어지는 대신 좀 더 나은 결과를 기대할 수 있다.

이번에는 Subtitle Edit에서 whisper.cpp와 medium 모델을 사용했다. 내가 선택한 모델의 용량은 약 1.5GB였다. 8GB의 데이터 로밍을 준비해 왔는데, 노트북을 휴대폰의 모바일 핫스팟에 연결해 이 모델을 다운로드하는 바람에 로밍 데이터를 상당히 소진하였다. 

2021년에 구입한 Dell XPS 노트북에서도 별도의 고성능 GPU 없이 처리할 수 있었다. 전사 시간이 실제 녹음 시간보다 조금 더 걸리기는 했다. 그러나 회의가 끝난 뒤 호텔에서 돌려놓는 작업이라면 큰 문제가 아니었다.

무엇보다 마음에 들었던 것은 일단 프로그램과 모델을 준비해 놓으면 인터넷에 연결하지 않고도 긴 녹음을 전사할 수 있다는 점이었다.

국내에서라면 클로바노트도 아주 편리한 선택이다. 한국어 회의뿐 아니라 외국어 음성도 처리할 수 있다. 영어 회의라면 노트를 만들 때 음성 인식 언어를 영어로 지정해서 사용하면 된다.

꼭 클로바노트 자체에서 녹음할 필요도 없다. 휴대폰의 기본 녹음기로 회의를 녹음한 다음 파일을 가져와 전사하는 방법도 있다.

문제는 이번과 같은 국외출장 환경이다.

클로바노트 같은 클라우드 기반 서비스를 이용하려면 결국 녹음 데이터를 서버로 보내야 한다. 짧은 음성이라면 별 문제가 아니지만 한두 시간짜리 회의를 하루에 몇 개씩 녹음하면 이야기가 달라진다. 호텔 Wi-Fi가 불안정하거나 로밍 데이터를 사용하고 있다면 대용량 음성 파일을 클라우드로 올리는 것 자체가 부담스럽다.

반면 Subtitle Edit + Whisper에서는 녹음 파일만 노트북에 가져오면 이후의 전사 작업은 로컬에서 이루어진다.

인터넷 연결이 충분하고 편리한 회의 관리가 중요하다면 클로바노트나 Otter,
긴 녹음 파일을 인터넷 연결 없이 내 컴퓨터에서 처리하고 싶다면 Subtitle Edit + Whisper.

녹음은 휴대폰이 가장 편했다

실제로 회의를 녹음해 보니 휴대폰이 가장 편했다. 별도의 녹음 장비를 가지고 다닐 필요가 없다. 테이블 위에 휴대폰을 놓고 녹음 버튼만 누르면 된다. 요즘 휴대폰의 마이크 성능이면 일반적인 회의실에서 발표 내용을 전사하기 위한 음질로는 충분했다.

문제는 녹음이 끝난 다음이다.

Whisper를 노트북에서 돌리려면 녹음 파일을 PC로 옮겨야 한다. USB 케이블을 연결하고 휴대폰 저장소를 찾아 들어가도 되지만 매번 그렇게 하는 것은 귀찮다.

이번에 써보니 이 문제의 답은 Quick Share였다.

Android 휴대폰과 Windows PC 사이에서 Quick Share를 이용하면 녹음 파일과 사진을 무선으로 바로 넘길 수 있다. 일반 Windows PC에서는 Google이 배포하는 Windows용 Quick Share를 사용할 수 있다.

휴대폰 녹음 → Quick Share → 노트북 → Subtitle Edit/Whisper → SRT

노트북 자체의 녹음기도 시험해 보았다. 이것도 생각보다 나쁘지 않았다. 어차피 회의장에서 노트북을 펼쳐 놓고 있다면 녹음이 끝나는 순간 파일이 이미 PC에 있으므로 Quick Share 과정조차 필요 없다.

그래도 휴대폰은 위치를 자유롭게 잡을 수 있고 녹음을 시작하고 끝내기도 편하다. 개인적으로는 휴대폰을 주 녹음기로 쓰는 쪽이 마음에 들었다.

게으른 출장자도 슬라이드 사진은 부지런히 찍어야 한다

여기에서 약간의 모순이 생긴다.

제목은 ‘게으른 국외출장자를 위한 워크플로’인데, 슬라이드 사진만큼은 부지런히 찍어야 한다.

슬라이드가 바뀔 때마다 가능하면 고해상도로 찍는다. 그렇다고 현장에서 사진 이름을 바꾸고 발표자별 폴더를 만들 필요까지는 없다. 중요한 것은 순서와 촬영 시각을 보존하는 것이다.

사진에는 촬영 시각이 기록되어 있다. SRT에는 녹음 시작점을 기준으로 각 발언의 시간이 기록되어 있다.

예를 들어 오전 9시 30분에 녹음을 시작했고 SRT의 00:27:30에 어떤 발언이 있다면 실제 시각은 대략 오전 9시 57분 30초다. 그 무렵 촬영한 사진을 찾아보면 당시 화면에 떠 있던 슬라이드를 찾을 수 있다. SRT의 타임코드와 사진의 촬영시각이 연결고리가 되는 것이다.

Subtitle Edit의 결과 화면.


Whisper가 틀린 것은 슬라이드가 고쳐 준다

Whisper의 영문 전사 결과는 놀라울 정도로 쓸 만했지만 당연히 완벽하지 않았다.

특히 국제학회는 음성인식 프로그램에 꽤 가혹한 환경이다. 여러 나라 사람들의 억양이 섞이고, 생소한 사람 이름과 기관명, 프로젝트명, 약어가 끊임없이 등장한다.

이때 슬라이드 사진이 위력을 발휘한다.

Whisper가 발표자의 이름을 엉뚱하게 받아썼더라도 첫 슬라이드에는 정확한 이름과 소속이 적혀 있다. 프로젝트명이나 전문용어, 숫자도 마찬가지다.

반대로 슬라이드에는 제목과 몇 개의 불릿만 있고 발표자가 그것을 어떻게 설명했는지는 나타나 있지 않다. 그 부분은 SRT가 채워준다.

슬라이드는 ‘무엇을 보여주었는가’를 기록한다.
SRT는 ‘무엇을 말했는가’를 기록한다.
손으로 쓴 메모는 ‘그중 무엇이 나에게 중요했는가’를 기록한다.

마지막으로 ChatGPT에 밀어 넣는다

이번에는 하루 동안 촬영한 슬라이드 사진이 200장을 넘었다. 여기에 여러 시간 분량의 SRT 파일도 생겼다.

예전 같으면 이 자료를 보는 순간 출장보고서를 쓸 의욕부터 사라졌을 것이다.

이번에는 사진을 시간 순서대로 묶고 SRT와 함께 ChatGPT에 넣었다. 그리고 세션을 구분하고, 발표자와 발표 제목을 확인하고, 슬라이드와 전사 내용을 대응시키면서 출장보고서 형태로 정리하도록 했다.

여기서 중요한 점이 있다. AI에게 아무 자료 없이 “오늘 학회에 다녀왔으니 출장보고서를 써줘”라고 하는 것이 아니다.

오히려 그 반대다.

가능한 한 충실한 원자료를 남기고, 그 원자료를 AI에게 다시 읽히는 것이 핵심이다.

음성에는 발표자의 설명이 있다. SRT에는 그것을 검색하고 분석할 수 있는 텍스트와 시간 정보가 있다. 사진에는 정확한 제목, 사람 이름, 기관명, 수치와 그림이 있다.

AI에게 맡기는 것은 기억이 아니라 재구성이다.

녹음 + SRT + 슬라이드 사진 → 발표 흐름의 재구성 → 요약 → 출장보고서

찍을 수 있는 것과 공개할 수 있는 것은 다르다

여기에는 중요한 전제가 하나 있다.

프로젝터에 보인다고 해서 모든 슬라이드를 촬영해도 되는 것은 아니다.

학회나 회의에 따라서는 발표 자료의 촬영이나 녹음을 금지하기도 한다. 미공개 연구 결과, 아직 출판되지 않은 데이터, 환자 또는 연구참여자와 관련된 정보, 기업의 기밀 자료 등이 포함될 수도 있다. 발표자가 특정 슬라이드에 대해 촬영하지 말아 달라고 요청하는 경우도 있다.

따라서 여기서 말하는 ‘슬라이드가 바뀔 때마다 찍는다’는 방법은 촬영이 허용된 범위 안에서만 적용되는 원칙이다. 녹음 역시 마찬가지다. 회의 성격과 주최 측의 규정을 먼저 확인해야 한다.

또 하나 중요한 것은 촬영과 공개는 전혀 다른 문제라는 점이다.

출장보고서를 작성하기 위해 개인적으로 촬영이 허용된 자료라고 해도 그 사진을 블로그나 SNS에 그대로 공개해도 된다는 뜻은 아니다. 발표 자료에는 저작권이 있고, 발표 당시에는 공개되었지만 온라인 재배포까지 의도하지 않은 내용도 있을 수 있다.

이번 워크플로에서 슬라이드 사진의 일차적인 목적은 공개가 아니라 기록과 확인이다. Whisper가 틀리게 인식한 이름이나 프로젝트명을 확인하고, 발표 순서를 복원하고, 발표자의 설명과 화면의 내용을 대응시키기 위한 원자료에 가깝다.

AI 서비스에 자료를 올리는 행위 역시 외부 서비스에 데이터를 제공하는 것이므로, 기밀자료나 개인정보처럼 외부 처리가 허용되지 않은 자료라면 업로드해서도 안 된다.

기록할 수 있는 것만 기록하고,
AI에 제공할 수 있는 것만 제공하며,
공개해도 되는 것만 공개한다.

그래서 이제 회의를 안 들어도 되는가?

물론 그렇지는 않다.

녹음에는 회의장의 모든 맥락이 담기지 않는다. 어떤 발표에서 사람들이 유난히 관심을 보였는지, 어떤 질문에서 분위기가 달라졌는지, 쉬는 시간에 누구와 무슨 이야기를 나누었는지는 직접 그 자리에 있었던 사람만 안다.

AI가 만들어 준 결과도 확인할 필요가 있다. Whisper가 고유명사를 틀릴 수 있고, 사진이 빠졌을 수도 있으며, AI가 서로 다른 발표의 내용을 잘못 연결할 수도 있다. 중요한 이름, 숫자, 발표 제목 정도는 원자료와 다시 맞춰보는 것이 좋다.

하지만 한 가지는 분명했다.

“출장보고서를 써야 하니까 지금 이 문장을 받아 적어야 한다”는 부담에서는 상당히 자유로워질 수 있다.

그 시간에 발표 자체에 더 집중하면 된다.

그리고 저녁이 되면 AI가 회의를 다시 정리해 준다.

정확히 말하면 AI가 나 대신 회의에 참석한 것이 아니다. 내가 남겨놓은 여러 종류의 기록을 시간축 위에서 다시 조립해 주는 것이다.

이번에 실제로 해보니 이 방법은 앞으로 국외출장에서도 계속 써먹을 만하다.

나의 새로운 출장 준비물은 별것 없다.

휴대폰, 노트북, Quick Share,
Subtitle Edit + Whisper, 그리고 ChatGPT.

아, 하나 더 있다.

슬라이드가 바뀔 때 사진 찍는 것을 잊지 않을 정도의 성실함.

그리고 그보다 더 중요한 것 하나.

찍어도 되는 것과 공개해도 되는 것을 구별하는 상식.

게으른 출장자에게 요구되는 성실함은 딱 그 정도면 될 것 같다. 

이 글을 마무리하면서 많은 고민을 하였다. 너무나 쉽게 출장 보고서를 쓰는 꼼수를 공개하는 부도덕한 일은 아닐까? 혹은 AI를 업무에 활용하여 자동화할 것은 최대로 자동화한다. 반면 회의장에서 듣고, 질문하고, 판단하고, 중요한 것을 알아채는 일은 사람이 한다. 이때 AI는 훌륭한 도구가 된다.

출장보고서 작성에 두 시간을 썼느냐 이틀을 썼느냐가 보고서의 성실성을 결정하는 것은 아니다. 중요한 것은 실제로 무엇을 보고 들었는지를 얼마나 충실하게 남기고, 그것을 왜곡하지 않고 전달하느냐일 것이다. AI 덕분에 그 과정이 쉬워졌다면, 그것은 요령이라기보다 도구의 발전에 가깝다.