2026년 5월 24일 일요일

새벽의 성공, 이어지는 hotfix

원래의 제목은 '어제의 성공, 오늘의 hotfix'로 하려고 했었다. 그러나 실제로는 어제 밤늦게 작업을 한 뒤 자정을 넘겨 '성공'에 대한 포스팅을 했기 때문에 지금  hotfix에 관한 글을 쓰는 시점과 날짜는 같다. 그래서 '새벽의 성공, 이어지는 hotfix'라고 제목을 지었다. Hotfix란 급하게 수정해야 하는 버그 잡기 정도라고 정의하면 된다. 중요한 기능을 구현했다고 김칫국부터 마시면서 릴리즈했다가 치명적인 문제가 포함되었음을 깨닫고 다시 급하게 수정본을 배포하는 행위에 해당한다.

어제 Fluid Ardule의 UNO-1 입력 컨트롤러에 자동 캘리브레이션 기능을 넣고 꽤 뿌듯해하고 있었다(관련 글 링크). 저항 사다리(resistor ladder) 방식의 5-버튼 키패드는 단 하나의 아날로그 입력만 사용하기 때문에 구조가 단순하고 배선도 간결하다. 비용도 적게 든다. DIY 프로젝트에서는 꽤 매력적인 방식이다.

이번에 구현한 기능은 각 버튼의 ADC 중심값을 자동으로 측정해 EEPROM에 저장하는 방식이었다. 사용자가 LEFT, UP, DOWN, RIGHT, SELECT 버튼을 차례대로 누르면 시스템이 직접 기준값을 계산해 주는 구조다. 저항 편차나 전원 상태 변화에도 좀 더 유연하게 대응할 수 있을 것 같았다. 실제로 처음 테스트했을 때는 제법 그럴듯하게 동작했다. 이제는 펌웨어 자체를 수정하여 컴파일 후 업로드하지 않아도 작동 중에 보정치를 구해서 직접 적용할 수 있으니 정말 영리하게 목표를 달성했다고 자부하고 있었다.

하지만 늘 그렇듯, 진짜 문제는 “잘 되는 것처럼 보인 뒤”에 나타난다.

테스트를 반복하던 중 이상한 현상이 보였다. 캘리브레이션 모드에 진입한 직후 아직 LEFT 버튼을 누르지도 않았는데 시스템이 이미 LEFT 입력을 받은 것처럼 다음 단계로 넘어가 버리는 경우가 생긴 것이다. 처음에는 threshold 계산 문제인가 싶었다. 그런데 원인을 추적해 보니 더 흥미로운 곳에 문제가 숨어 있었다.

문제는 캘리브레이션 진입 자체에 사용했던 롱프레스 입력이었다.

사실 인코더 롱프레스는 원래 인코더 회전 가속(acceleration) 단계를 변경하는 기능에 이미 할당되어 있었다. 따라서 캘리브레이션 진입을 같은 롱프레스 동작에 연결하자 메뉴 의미가 충돌하기 시작했다. 결국 캘리브레이션은 인코더와 SELECT 버튼을 동시에 길게 누르는 조합 입력으로 변경하였다. 일반적인 조작과 유지보수 기능을 분리하기 위한 선택이었다.

그런데 시스템은 아직 그 입력 상태의 “잔향” 속에 있었는데도 이미 다음 단계로 넘어가 LEFT 입력을 기다리고 있었다. resistor ladder 방식에서는 버튼을 떼는 순간 ADC 값이 잠깐 불안정한 영역을 지나간다. 그 transient 값이 우연히 LEFT 버튼 영역을 스치면서 실제로는 누르지도 않은 LEFT가 눌린 것처럼 보인 셈이다.

결국 이번 hotfix에서는 캘리브레이션 state machine 자체를 손보게 되었다.

캘리브레이션 진입 직후에는 먼저 모든 버튼이 완전히 해제된 안정 상태를 확인하도록 바꾸었고, 단순히 “현재 눌려 있는 상태”가 아니라 NONE 상태 이후 새롭게 발생한 press edge만 유효 입력으로 인정하도록 수정하였다. 각 단계 사이마다 반드시 버튼 release를 확인하는 과정도 추가했다.

사실 이런 문제를 겪다 보면 임베디드 시스템에서 가장 어려운 것은 화려한 기능이 아니라 상태 전이(state transition)라는 생각이 든다. 특히 아날로그 입력, 롱프레스, 노이즈, 실시간 이벤트가 한꺼번에 얽히기 시작하면 예상하지 못한 모서리(edge case)가 끝없이 나타난다.

그래도 이런 시행착오가 재미있다. “왜 이런 일이 생겼지?”를 추적하다 보면 회로와 펌웨어가 실제 세계와 어떻게 부딪히는지가 조금씩 보이기 때문이다.

한편으로는 현재의 resistor ladder 구조를 계속 유지할지에 대한 고민도 다시 하게 된다. 장기적으로는 PCF8574 같은 I2C 기반 GPIO 확장 칩도 검토해 보고 싶다. 버튼마다 독립적인 디지털 입력을 사용하면 threshold drifting 같은 문제에서는 훨씬 자유로워질 수 있기 때문이다. 물론 배선은 조금 복잡해지겠지만 말이다.

자작나무 합판이 도착하여 드디어 케이스 만들기에 착수하였다. 목공용 플램프가 없어서 이번에도 접합 후에 단차가 약간 발생하였다. 충분히 주의하면서 위치를 잡은 후 무거운 것으로 눌러 두었음에도 불구하고... 만약 PCF8574 확장 칩을 쓴다면 사진 가운데에서 보이고 있는 패널용 누름 버튼 스위치 5개를 이용하여 약간은 수고스럽게 배선 작업을 해야 한다. 


어쩌면 이번 경험은 단순한 버그 수정이라기보다, “입력 장치를 만든다”는 것이 생각보다 훨씬 깊은 세계라는 사실을 다시 배우는 과정인지도 모르겠다.

[Fluid Ardule] 아두이노 우노 펌웨어에 자동 보정 기능 도입

자정을 넘겨서 그림을 만들도록 했더니 5월 24일 업데이트라는 제목을 달아 버렸다.

저항 '사다리'를 이용한 5-버튼 키패드는 겨우 하나의 아날로그 입력을 사용하기 때문에 매우 단순하다. 하지만 사용을 거듭하면서 동일한 문제가 자꾸 반복하여 발생하기 시작하였다. ADC 값이 항상 일정하지는 않기 때문에 고정 threshold 방식만으로는 안정적으로 처리하기 어려웠다. 어제는 잘 작동하던 Left 버튼이 오늘은 Up 버튼처럼 행세한다.

Threshold를 이따금 조정하는 방식으로는 아두이노 우노의 펌웨어 자체를 매번 고쳐서 업로드해야 하니 여간 성가신 것이 아니다. 근본적으로는 "현재 환경의 실제 ADC 중간값"을 다시 학습해야 한다는 결론에 이르렀다. 이에 따라서 키패드의 self calibration 기능을 아예 구현하여 넣기로 했다.

새로운 펌웨어에서는 엔코더를 길게 누르면 캘리브레이션 모드로 진입한다. LCD는 순서대로 각 버튼을 누르라고 안내하며, 사용자가 버튼을 충분히 길게 누르고 있는 동안 여러 차례 ADC 값을 샘플링한다. 이 과정에서 원래 작동 상태를 나타내는 LED가 아닌 LCD 자체를 blink시키도록 하였는데, 결과적으로 꽤 직관적인 UI가 되었다. 측정 중에는 LCD가 점멸하고, 안정된 값이 확보되면 steady on 상태로 바뀌며 “Release key” 메시지가 나타난다. 사용자는 그때 손을 떼면 된다.

측정된 값은 EEPROM에 저장된다. 따라서 매번 threshold를 코드에 하드코딩할 필요가 없어졌다. 사용 환경이나 부품 상태가 변하더라도 사용자가 직접 다시 보정할 수 있다. 또한 calibration 중에는 runtime BTN/ENC/POT 이벤트를 모두 억제하고, Pi와의 링크는 heartbeat만 최소한으로 유지하도록 하여 watchdog 문제를 피하도록 하였다.

오늘의 개선은 CHANGELOG.md 파일에 5월 24일의 것으로 기록해 넣었다. 내가 생각해도 꽤 버튼 작동과 관련한 부품을 바꾸지 않은 상태에서 가장 최적의 개선을 이룬 것 같다.

Fluid Ardule을 케이스에 넣기 위하여 전후판(3mm 알루미늄)을 설계하면서 디스플레이도 전면판에 수직으로 고정하기로 하였다. 이를 위해서 라즈베리 파이와 TFT-LCD를 연결할 40핀 리본 케이블도 구입하였다. 특별한 것이 아니라 예전에 40핀 IDE HDD용 케이블로 쓰던 것을 그대로 팔고 있었다. 약간 생각을 잘못하여 케이블 양 말단이 female로 마감된 것을 구입하였다. 라즈베리 파이에 붙어 있던 GPIO 헤더 확장용 직각 커넥터를 이용하여 얼추 연결을 마쳤다. 이번에는 라즈베리 파이 -> 40핀 케이블 -> 확장용 직각 커넥터 -> TFT-LCD의 순서로 연결되므로 여기에서 분기하는 I2C DAC(PCM5102A) 등의 점퍼 연결에 주의해야 한다. 라즈베리 파이에 붙어있는 40핀 GPIO와는 좌우가 반전된 것으로 생각해야 하기 때문이다. 글로 옮기려니 쉽지 않다. 배선을 한참 들여다보며 점퍼를 연결하여 겨우 시리얼 콘솔 화면이 뜨게 만들었다.


아이베란다에서 주문한 자작나무 합판도 마침 도착하였다. 수 주일 내에 완성된 모습의 Fluid Ardule을 보게 될 것으로 기대한다.

2026년 5월 22일 금요일

AI는 우리를 어디까지 지치게 할까

출장지에서 잠시 낮 시간을 이용하여 달려 보았다. 오늘 이 지역의 최고 온도는 섭씨 27도. 나는 거의 항상 밤에만 달리는 사람이라서 초여름 낮 달리기의 '위험함'을 간과하고는 한다. 역시 이런 날씨에 인스파이어 엔터테인먼트 리조트를 두 바퀴 달리는 것은 쉽지 않았다. 이따금 만난 횡단보도가 잠깐 숨을 돌리는 좋은 핑계가 되었다.



요즘은 이틀 쉬고 달리기를 반복하고 있다. 다시 예전처럼 간격을 줄여서 하루 쉬고 하루 달리는 것으로 돌아가고 싶은 생각이 없지 아니하다. 페이스 향상은 어차피 기대하지 않는다. 다만 워밍업에 좀 더 신경을 써야 할 것 같다. 

독후감을 쓰겠다고 출장지까지 다 읽은 책을 들고 왔는데, 정작 책 꾸러미는 멀리 주차장에 세워 둔 차 속에 있다. 도서관 앱을 열어서 책 제목만 찾아냈다.

가장 인상 깊게 읽은 책은 카렌 하오의 <AI 제국: 권력, 자본, 노동>이었다. 시간을 들여서 다시 처음부터 천천히 읽고 싶었다. 지금도 나는 오픈AI의 ChatGPT를 이용하여 업무와 취미의 많은 부분에서 도움을 받고 있다. 그러나 회사의 이름과 달리 샘 올트만의 '제국'은 결코 투명하지 않으며, 그 지속 가능성도 의문시된다. 앤트로픽이 독립하고 일론 머스크가 손을 뗀 것도 그러한 문제점과 결코 무관하지 않다. 

AI를 기치로 한데 뭉쳐서 국가의 경쟁력 강화에 역량을 집중해야 한다는 논리에 요즘은 선뜻 반기를 들기 어렵다. 나도 한편으로는 AI를 이용하여 과거에는 불가능했을 일을 하고 있으니 최신 기술에 함부로 비판을 가해서는 안 될 것만 같다. 


하지만 그 지속 가능성은 누구도 낙관하기 어렵다. 인공지능을 개발하기 위한 하드웨어 인프라(반도체 및 클라우드)를 제공하는 업체는 막대한 수익을 올리고 있지만, 1세대 AI 서비스 개발사는 아직도 막대한 개발 비용 때문에 적자를 면치 못하고 있기 때문이다. 카렌 하오의 책에서도 지적했듯이, 데이터에 라벨을 붙이고 모더레이션1)을 하는 데에는 사실상 저개발 국가의 저임금 노동에 크게 기대고 있으며, 데이터 센터의 구축과 유지에 필연적으로 동반되는 부정적 외부효과 또한 막대하다. 이러한 숨겨진 비용을 1세대 AI 서비스 개발사는 제대로 지불하지 않음에도 불구하고 여전히 적자라는 뜻이다. 과연 이것이 지속 가능할까? 그리고 기술 개발이 이 문제를 정말로 해결해 줄까?

지난 수요일, 서울대학교병원 헬스케어AI연구원의 이형철 원장(마취통증의학과 교수)의 초청 세미나에서 촬영한 슬라이드를 소개한다.

  • ChatGPT(2022년 11월 30일) - 이게 되네
  • DeepSeek(2025년 1월 20일) - 심지어 값싸게
  • Claude(2025년 5월 22일) - 끝났네 끝났어



'끝났네 끝났어'가 '우리는(우리 인간은|우리의 직업은) 이제 망했네 망했어!'가 되지 않아야 한다. 이제는 AI가 신기하고 재미있는 기술이라고 피상적으로 여기기에는 너무나 우리 삶 깊이 들어와 버렸다. AI가 유발하는 과몰입(또한 과노동), 그리고 숙련자를 육성하려는 노력을 경시하게 되는 문제점은 이미 많은 사람이 느끼고 있다. 출장에서 접한 숱한 파워포인트는 이미 인공지능의 터치를 거쳐 상향 평준화가 되어 있었다. 오히려 내가 발표를 하기 위해 대부분 손으로 만든 슬라이드가 촌스럽게 느껴질 정도였으니 말이다. 나도 이제 시대에 뒤떨어진 사람이 된 것일까?

이 기술이 정말 지속 가능하며 인류가 살아가는 보람에 흠을 입히지는 않을지 진지하게 고민해 볼 때가 되었다. 이번에 읽은 책 <완벽하지 않은 것이 살아남는다>에서 이야기하는 생물권의 원칙을 다시 되새겨 보았다. 정리 또한 AI가 해 주었다.

  1. 자연관 (자연계의 자원 보전): 자연을 인간이 통제하고 착취해야 할 외부 자원으로 보지 않고, 우리가 보존하고 관리해야 할 대상으로 인식합니다.
  2. 성장 모델 (내재적 잠재력): 무한한 경제 및 기술 성장을 추구하기보다, 생물과 환경이 함께 진화해 나갈 수 있는 내재적 잠재력과 회복력을 개발하는 데 집중합니다.
  3. 보전과 공생 (관계와 제도): 생물 다양성을 유지하고, 생태계 및 다른 종들과 공생공락(협력적 보전)하는 관계를 맺습니다.
  4. 환경 대응 (진화적 회복력): 환경은 끊임없이 변화하므로, 완벽한 적응(최적화)에 얽매이지 않고 위기를 극복할 수 있는 진화적 회복력을 유지합니다.
흥미로운 것은, 이 책이 말하는 생물권의 원칙이 AI 산업의 미래에도 그대로 적용될 수 있다는 점이었다. 완벽한 최적화와 무한 성장을 추구하기보다, 회복력과 공생 가능성을 고민해야 한다는 메시지 말이다.

1 데이터 모더레이션(Data Moderation)이란, AI 모델이 유해하거나 편향된 내용을 배우지 않도록 학습 데이터 속 위험 요소를 걸러내고 관리하는 검수 작업이다(구글의 AI 모드 답변). 

2026년 5월 14일 목요일

ChatGPT를 이용한 악보 그리기(Lilypond)

Lilypond를 이용하여 악보를 그리는 일은 LA TEX 으로 문서를 편집하는 일과 매우 흡사하다. 어떻게 생각하면 '코딩'과 유사한 면이 없지 아니하다.

나의 자작곡 <화장을 지우고>(유튜브 링크)의 악보를 Lilypond로 가장 마지막에 만들어 놓은 것이 벌써 2년 전이다. 엔딩의 반복 부분에 가사를 다르게 표시하는 방법을 잘 몰라서 불완전한 상태로 방치하였다가 이를 완성하기로 하고 다시 Frescobaldi를 실행하였다. Frescobaldi는 Lilypond를 위한 IDE에 해당하며, Python + Qt로 만들어져 있다.

이 프로그램은 마우스로 음표 위치와 종류를 찍어서 악보를 만드는 것이 아니다. 

  % Ending 1st time
  b2
  r8 d,8 b'8 b
  b16 c8 c16~ c2 r8 a16 b
  c8 c16 c~ c8 b16 d~ d c8. b8 a16 (g)  
  g4. r8 a8 g fis d8  \break
  e2  e8 fis16 g~ g8 a      
  g8 d8~ d4 r8 d8 g a    
  b4 a g8 a4 a8~ a2 r8 d,8 g a  \break

이것이 Lilypond 파일(.ly)의 일부이다. 텍스트 정보를 표현하는 마크다운 문서와 비슷하다는 기분이 든다. 이를 LA TEX 으로 처리하듯이 'Engraving'을 거치면 비로소 PDF 형식의 악보가 나온다. latex에 이어서 dvi2ps를 실행하듯. 

Lilypond 문법은 자주 쓰지 않으면 쉽게 기억이 나지는 않는다. 예를 들어 큐 노트(cue notes, 다른 악기의 중요한 멜로디를 작은 음표로 잠깐 보여주는 기능)을 그리려면 초보자의 경우 매뉴얼을 보고 상당히 궁리를 해야 한다. 잠시 고민을 하다가 아예 ChatGPT를 이용해 보기로 했다. '.ly' 파일 전체를 텍스트 형태로 복사해서 넣은 뒤, 원하는 방식으로 수정을 해 달라고 했다. 그랬더니 놀랍게도 잘 '컴파일'된 결과를 얻을 수 있었다.


Lilypond는 인쇄 품질 면에서는 매우 우수하지만, 대중음악용 악보를 적기에는 그렇게 친절하지는 않다. 기타(guitar)의 벤딩을 표현하거나, 슬래시를 이용하여 간략하게 표기하기에는 좋지 않다.

LibreCAD, KiCad, Lilypond. 이들은 전부 "시각 결과물"을 만들지만 본질은 구조 기술(description)을 위한 도구이다. 정해진 규칙에 따라서 정밀한 결과물을 만들어내는 용도로 쓰인다는 뜻이다. 

오랜만에 Frescobaldi를 다시 실행해 보니, 잊고 있었던 Lilypond 문법보다 먼저 떠오른 것은 이 독특한 감각이었다. 음표를 그린다기보다는 구조를 기술하고, 이를 다시 컴파일하여 결과물을 얻는 느낌. 그래서인지 나에게 Lilypond는 단순한 악보 프로그램이라기보다, 음악을 위한 또 하나의 프로그래밍 언어처럼 느껴진다.

더 늦기 전에 Fluid Ardule 케이스를 설계해야 되는데...

2026년 5월 15일 업데이트

Fluid Ardule 케이스 설계 및 주문을 시작하였다. 자작나무 합판부터 먼저 주문한다.


LibreCAD를 펼쳐놓고 겨우 사각형 두 개를 그렸다. 사용법이 잘 기억나지 않는다.


하루가 지난 뒤의 작업 결과물. 버니어 캘리퍼스로 대충 잰 부품 수치가 잘 맞는지 모르겠다. 가공 주문을 하기 전에 몇 번 확인을 거쳐야 할 것이다.




2026년 5월 11일 월요일

데이터, 데이터셋, 코호트를 구별하자

바이오 데이터 플랫폼을 소개하는 자료를 보다 보면 종종 이런 질문을 듣게 된다.

“그래서 데이터셋이 몇 개 있나요?”

예전에는 자연스러운 질문이었다. 그러나 인공지능(AI) 시대의 바이오 데이터 플랫폼에서는 점점 적절하지 않은 질문이 되어 가고 있다. 현대의 플랫폼은 정적인 데이터 파일 묶음을 보관하는 저장소(repository)를 넘어, 사용자가 목적에 맞는 데이터셋(dataset)을 동적으로 생성하는 환경으로 진화하고 있기 때문이다.

특히 대규모 바이오 데이터 플랫폼에서는 “데이터(dataset)”와 “코호트(cohort)”의 개념이 서로 다른 층위에서 사용된다. 이를 구별하지 않으면 플랫폼의 역할과 가치를 제대로 이해하기 어렵다.

데이터(data)는 가장 넓은 개념이다

데이터는 가장 포괄적인 개념이다. 유전체 서열, 임상 정보, 의료 영상, 웨어러블 센서 기록, 생활습관 설문, 분석 결과 파일 등은 모두 데이터에 해당한다.

즉 데이터는 가공 여부와 관계없이 저장·수집되는 개별 정보 단위를 의미한다.

예를 들면:

  • FASTQ 파일
  • VCF 파일
  • MRI 이미지
  • 혈액검사 결과
  • 생활습관 설문 응답
  • 웨어러블 센서 로그

등은 모두 데이터이다.

코호트(cohort)는 사람 집단이다

코호트는 본래 역학(epidemiology)에서 나온 개념이다. 핵심은 “누가 포함되는가”이다.

예를 들어 다음은 모두 코호트가 될 수 있다.

  • 65세 이상 여성
  • 흡연 경험이 있는 사람
  • 특정 암 환자군
  • 10년 이상 추적 관찰된 참여자

즉 코호트는 연구 대상 집단을 정의하는 개념이다.

현대의 바이오 플랫폼에서는 사용자가 다양한 조건을 조합하여 코호트를 구성할 수 있다. 예를 들어 다음과 같은 방식이다.

  • 여성
  • BMI 30 이상
  • MRI 보유
  • 당뇨 환자 제외
  • 5년 이상 longitudinal follow-up 존재

이러한 조건을 조합하면 연구 목적에 맞는 새로운 코호트가 즉시 생성된다.

데이터셋(dataset)은 목적에 맞게 구성된 데이터 묶음이다

반면 데이터셋은 데이터를 어떻게 구성했는가에 초점이 있다.

예를 들면:

  • variant matrix
  • RNA-seq expression table
  • AI 학습용 feature matrix
  • 영상 + 임상 + 유전체를 결합한 multimodal training set

등이 데이터셋이다.

즉 데이터셋은:

  • 어떤 feature를 쓸 것인가
  • 어떤 modality를 결합할 것인가
  • 어떻게 QC를 했는가
  • train/validation/test split을 어떻게 나눌 것인가

같은 데이터 공학적 관점이 핵심이다.

현대 플랫폼에서는 “데이터셋”이 고정되어 있지 않다

대표적인 사례가 UK Biobank와 같은 플랫폼이다.

이러한 시스템에서 플랫폼이 제공하는 것은 단순한 정적 dataset 하나가 아니다. 대신 사용자가 cohort builder를 이용하여 원하는 연구 대상군을 정의하고, 그 결과를 바탕으로 자신만의 데이터셋을 생성한다.

즉:

  • 플랫폼이 보유한 것은 거대한 data space
  • 연구자가 만드는 것은 목적 특화 dataset

이라고 보는 편이 정확하다.

따라서 현대 바이오 플랫폼은 단순 저장소라기보다:

  • dataset factory
  • cohort generation platform
  • queryable bio data environment

에 가까워지고 있다.

그림으로 보면 더 이해가 쉽다



이 그림에서 중요한 점은 “데이터”, “코호트”, “데이터셋”이 서로 다른 개념이라는 것이다.

  • 데이터는 개별 정보 단위
  • 코호트는 연구 대상 집단
  • 데이터셋은 특정 목적에 맞게 구성된 데이터 묶음

예를 들어 동일한 코호트라도:

  • 유전체만 추출할 수도 있고
  • 영상 데이터만 사용할 수도 있으며
  • 멀티모달 AI 학습용 feature matrix를 생성할 수도 있다.

즉 하나의 코호트로부터 매우 다양한 데이터셋이 생성될 수 있다.

그래서 중요한 것은 dataset 개수가 아니다

이제 중요한 질문은 다음과 같이 바뀌고 있다.

  • 어떤 데이터 타입을 보유하고 있는가?
  • metadata quality는 어떤가?
  • cross-modal linkage가 가능한가?
  • cohort construction이 얼마나 유연한가?
  • 재현 가능한 query를 지원하는가?
  • AI 학습용 feature extraction이 가능한가?
  • 정책·윤리 기반 접근 통제가 가능한가?

즉 AI 시대의 경쟁력은 단순 저장량이 아니라 “얼마나 유연하게 코호트와 데이터셋을 생성할 수 있는가”에 가까워지고 있다.

그리고 이것은 국가 바이오 데이터 플랫폼의 역할 역시 단순 repository에서 AI-ready data platform으로 이동하고 있음을 의미한다.


저자 및 이용 안내

이 문서는 정해영의 아이디어와 지시에 따라 AI 도구(ChatGPT)의 도움을 받아 작성되었습니다.
본 문서는 Creative Commons CC0 1.0 Universal Public Domain Dedication에 따라
누구나 자유롭게 복제, 수정, 배포, 활용할 수 있으며, 출처 표시도 필요하지 않습니다.

다만, 내용의 정확성은 보장되지 않았으며, 정해영은 본 문서의 내용에 대해 어떠한 법적 책임도 지지 않습니다.

2026년 5월 10일 일요일

'해피 630'을 위하여

운동을 전혀 하지 않던 사람도 8주 정도 체계적으로 훈련하면 30분을 쉬지 않고 달릴 수 있다고 한다. 나도 그렇게 런데이라는 앱을 통해서 달리기에 입문하였다. 러닝에서는 흔히 30분 동안 5km를 달릴 수 있는지를 초보자와 중급자를 가르는 기준으로 본다고 한다.

그렇게 2년 가까운 시간이 흘렀다. 하루 쉬고 하루 뛰기를 반복하다가 지금은 하루 뛰고 이틀 쉬는 방식으로 굳어졌다. 달리는 거리는 1회에 6~7km 사이. 그러나 '600 페이스'는 꿈과 같은 일이다. 입문 6개월 정도에 두어 차례 600을 달성하였을까? 지금은 6분 20초 수준을 오르내린다.

달리기 기록
어젯밤의 달리기 기록. 실제로는 2km를 더 달려서 7km를 조금 넘겼다.

인터벌 트레이닝이라든가 추가적인 하체 근육 단련 같은 것을 하지 않기 때문에 기록이 이렇게 제자리걸음인 것 같다. 간혹 온라인 커뮤니티(달리기 관련 아님)의 글을 보면 나와 같은 평생 초보에게는 어질어질한 기록을 올리는 사람이 많다. 예를 들어 러닝 3년차인데 기록이 나오지 않는다는 이런 글을 보면 나와 같은 사람은 어쩌란 말인가!

1. 페이스별 시속

페이스 (min/km) 시속 (km/h) 비고
6분 00초 (600) 10.0 km/h
6분 10초 (610) 9.73 km/h 약 9.7~9.8
6분 15초 (615) 9.6 km/h
6분 20초 (620) 9.47 km/h 약 9.5
6분 30초 (630) 9.23 km/h
7분 00초 (700) 8.57 km/h 약 8.6

2. 시속별 분당 페이스

시속 (km/h) 페이스 (min/km)
8.0 km/h 7분 30초 페이스
8.5 km/h 7분 04초 페이스
9.0 km/h 6분 40초 페이스

대회에 나갈 것도 아니니, 이제 목표를 조금 바꾸어도 되지 않을까 싶다. 600이 아니라 630. 나에게는 그것이 훨씬 현실적이고 지속 가능한 목표다. 이름하여 '해피 630'. 1시간 5분 동안 해피 630으로 달리면 10km를 채울 수 있다.

요즘 나의 페이스로 총 6km 정도를 달릴 때 가장 편안한 순간은 대략 4km 정도를 지날 때인 것 같다. 이러한 상태로 10km를 채울 수 있다면 더 이상 바랄 것이 없겠다.

2026년 5월 9일 토요일

[Fluid Ardule] User Preset에서 Combination 설계로


오늘도 총 13차례에 걸쳐 Fluid Ardule 메인 스크립트를 수정하였다. 분량은 총 7,340라인에 이른다. 예전 같으면 수정을 한 번 거칠 때마다 GitHub에 commit하였겠지만, 이제는 요령이 생겨서 그날 마지막으로 개발한 것을 올리게 되었다. 커밋문과 CHANGELOG.md 파일도 마지막 버전과 최종 버전을 실제 비교하여(물론 ChatGPT의 도움으로) 매우 상세히 기록해 나가고 있다. 

시스템은 매우 안정적으로 돌아간다. 각 사운드폰트에서 로드한 음색을 편집하여 user preset으로 저장하고 다시 불러오는 것까지 구현해 놓았다. 단일 스크립트에서 수용하는 기능으로는 거의 한계에 이르지 않았나 싶다. 이제는 combination 음색을 편집하고 사용하는 기능을 넣을 차례이다. 

Fluid Ardule에서 Combination은 여러 음색을 조합하여 하나의 연주 환경으로 만드는 기능이다. 여기에는 layer와 split이 모두 포함된다.

정리하면 다음과 같다.

  • Layer: 여러 음색이 같은 건반 범위에서 동시에 울림
  • Split: 건반 범위에 따라 서로 다른 음색이 울림
  • Combination: layer와 split을 모두 포함하는 일반화된 구조

중요한 점은 Combination을 새로운 음색 데이터로 만들지 않는다는 것이다. 이미 존재하는 User Preset 또는 edited User Preset을 조합한다. 즉 User Preset은 “음색 자체”이고, Combination은 그 음색들을 “어떻게 배치하고 연주할 것인가”를 정의한다.

User Preset
= sound identity

Combination
= performance / routing structure

구현 방식도 비교적 명확하다. 입력 MIDI를 여러 내부 채널로 복제하고, 각 채널에 서로 다른 User Preset을 배정한다. 여기에 key range를 적용하면 split이 되고, key range가 겹치면 layer가 된다.

Input CH1 note
 → Main Sound  → CH1
 → Layer Sound → CH2
 → Split Sound → CH3

각 채널은 독립적으로 Program Change와 CC 값을 가질 수 있으므로, 리버브나 코러스 send level도 채널별로 다르게 적용할 수 있다. 따라서 Combination 자체가 CC 값을 복잡하게 덮어쓸 필요는 없다. 각 User Preset이 이미 자신의 Sound Edit 값을 갖고 있고, Combination은 volume, key range, transpose 같은 연주 배치 정보만 갖는 것이 바람직하다.


UI 설계 방향

Combination 기능에서 가장 어려운 것은 기능 자체보다 UI다. 내부적으로는 part 구조를 쓰더라도, 사용자에게 굳이 “Part 1”, “Part 2” 같은 기술적 표현을 노출할 필요는 없다. 악기처럼 쓰려면 다음과 같은 표현이 더 자연스럽다.

  • Layer
  • Split
  • Upper / Lower (키 범위)

처음부터 4-part workstation을 만들려고 하기보다는, 2개의 음색을 조합하는 것부터 시작하는 것이 현실적이다. 예를 들어 Piano + Pad layer, Bass + Piano split 정도만 구현해도 실제 연주에는 매우 유용하다.

초기 Combination 편집 항목은 다음 정도면 충분하다.

  • User Preset 선택
  • 상대 볼륨
  • Key Low / Key High
  • Transpose
  • Mute / Solo

Mute와 Solo는 꼭 필요하다. 여러 음색을 조합할 때 각 음색을 따로 들어 보며 밸런스를 잡아야 하기 때문이다.


다음 단계

오늘 만든 설계 문서는 GitHub의 docs/combination-system-design.md에 둘 수 있을 정도로 정리되었다. 아직 구현은 시작하지 않았지만, 방향은 꽤 분명하다.

Fluid Ardule는 이제 단순한 FluidSynth 프론트엔드가 아니라, User Preset과 Combination을 기반으로 한 작은 DIY workstation으로 진화하고 있다. 아직은 단일 Python 스크립트로 유지하고 있지만, Combination 편집기부터는 별도 모듈로 분리하는 것이 자연스러울 것이다. 3.5인치에 불과한 TFT-LCD 화면과 몇 개의 버튼/인코더를 이용하여 Combination을 편집하는 UI를 구성하려면 꽤 공을 들여야 할 것이다. 생각보다 많은 시간이 걸릴 수도 있다. 또한 Combination 관련 기능은 별도의 파이썬 파일로 독립시키는 것이 바람직하다. 동시에 케이스 설계도 병행해 나가는 것이 좋을 것이다. 

오늘의 작업을 통해 User Preset은 이제 실사용 가능한 수준으로 다듬어졌고, Combination은 다음 단계의 설계 주제로 떠올랐다. 이 작은 악기가 점점 더 악기다워지고 있다.