TECH 으로 돌아가기
TECH HACKER NEWS 오늘 7분 읽기 24 READS

발밑 MIDI 페달을 맥 단축키로: fcbnerd가 택한 '읽기만 하는' 설계

발밑 MIDI 페달을 맥 단축키로: fcbnerd가 택한 '읽기만 하는' 설계
SOURCE IMAGE · HACKER NEWS

기타리스트나 건반 연주자에게 익숙한 베링거 FCB1010 같은 MIDI 풋 컨트롤러를, 코딩이나 회의 중 손을 떼지 않고 쓰는 보조 입력 장치로 바꿔주는 도구가 등장했다. James Ryan이 공개한 fcbnerd는 macOS에서 CoreMIDI 소스에 연결해, 풋스위치나 익스프레션 페달이 보내는 메시지를 감지하고 사용자가 지정한 셸 명령을 실행한다. 이름은 FCB1010을 겨냥했지만 실제로는 특정 기기에 묶인 코드가 없어 CoreMIDI로 인식되는 어떤 MIDI 소스든 동작한다. 발로 테스트를 돌리거나, CI 완료를 기다리거나, 마이크를 음소거하는 식의 반복 동작을 페달에 매핑하는 것이 핵심 사용 시나리오다.

권한을 만들지 않는다는 설계 철학

fcbnerd에서 가장 눈여겨볼 지점은 기능이 아니라 책임의 분리다. 키를 누르거나 스크립트를 실행하는 등 맥에 실제로 작용하는 동작은 샌드박스 앱이 얻을 수 없는 권한을 요구하고, 사용자마다 원하는 동작도 제각각이다. 그래서 fcbnerd 자신은 아무런 권한도 필요 없는 'MIDI 읽기'만 담당한다. 실제 행동은 사용자의 셸이나, 이미 접근 권한을 가진 Hammerspoon·Keyboard Maestro 같은 도구에 맡긴다. 권한을 요구하는 부분과 요구하지 않는 부분을 아키텍처 수준에서 갈라놓은 것으로, 보안 표면을 줄이면서도 확장성을 확보한 실용적 판단이다.

동작 방식은 두 가지다. 하나는 PATTERN=COMMAND 형식의 바인딩을 --bind 옵션으로 걸어 특정 메시지가 올 때 명령을 실행하는 방식이고, 다른 하나는 listen 하위 명령으로 모든 MIDI 메시지를 한 줄에 하나씩 JSON으로 출력해 다른 프로그램이 해석하도록 넘기는 방식이다. 상태 메시지는 stderr로, 이벤트는 stdout으로만 나가며 각 줄은 쓰이는 즉시 플러시되어 파이프가 지연 없이 이벤트를 받는다. 출력 채널을 엄격히 분리해 파이프라인에 끼워 넣기 좋게 만든 설계다.

파이프라인 도구다운 세부 처리

실무에서 골치 아픈 부분은 대부분 문서화되어 있다. 모든 스톰프는 명령을 실행하므로 빠르게 두 번 누르면 첫 실행이 끝나기 전에 두 번째가 또 돌고, 매칭되는 메시지마다 셸이 새로 뜬다. 그래서 ::127이나 pc:: 같은 광범위한 패턴을 노이즈가 많은 기기에 걸지 말라고 경고한다. 예외는 익스프레션 페달의 스윕(sweep)이다. 초당 수십 개의 값을 뿜기 때문에, * 값을 가진 바인딩은 컨트롤(채널·컨트롤러)마다 명령이 한 번에 하나만 돌고 실행 중에는 가장 최신 값만 유지했다가 다음에 실행한다. 덕분에 셸 개수를 억제하면서도 페달의 최종 위치에서 끝난다. 명령이 5초 넘게 돌면 stderr로 알려주고, fcbnerd를 종료하면 아직 도는 명령과 그 자식 프로세스에까지 SIGTERM을 보낸다.

셸 환경에 대한 안내도 현실적이다. sh -c에는 대화형 셸의 함수나 별칭이 로드되지 않는다. bash에서는 함수를 export해야 보이고, macOS의 /bin/sh는 bash라 기본 셸에서는 노출된다. 반면 zsh는 함수를 export할 수 없으므로 파일에 넣고 source로 불러와야 한다. 또 FCB1010은 스위치에서 발을 뗄 때 아무 메시지도 보내지 않아 바인딩은 '누름'에서만 발동한다. 켜고 끄는 토글이 필요하면 /tmp의 파일을 뒤집는 식으로 상태를 명령 쪽에 직접 두라고 권한다.

JSON 스트림과 알아둘 한계

listen이 내보내는 JSON 객체는 type, source(소스 표시 이름), time(수신 시각, ISO 8601·UTC·밀리초)을 공통으로 갖는다. 채널은 1~16, 노트·컨트롤러·프로그램·벨로시티·프레셔는 0~127 원시 MIDI 값이다. MIDI 클럭 같은 시스템 실시간 메시지와 송 포지션·MTC 같은 시스템 공통 메시지는 내보내지 않는다. 향후 새 타입이나 필드가 추가될 수 있으나 기존 의미는 바뀌지 않으니, 소비 측은 모르는 타입과 필드를 무시하도록 짜야 한다. list --format json은 소스별로 name과 CoreMIDI 고유 id를 담은 다른 형태를 낸다.

다만 놓치기 쉬운 함정이 하나 있다. 소비 프로그램이 스트림을 제때 읽지 않으면 fcbnerd는 이벤트를 메모리에 쌓아뒀다가 읽기가 재개될 때 한꺼번에 전달한다. 멈춰 있던 소비자가 재개되는 순간 오래된 페달 입력이 몰려 실행될 수 있다는 뜻이므로, 스트림은 지체 없이 읽어야 한다. 또 페달 출력이 부분 청크로 도착할 수 있어 개행 단위로 버퍼링해야 하고, Homebrew 경로가 애플 실리콘 기준이라 인텔 맥에서는 /usr/local/bin으로 달라진다.

소프트웨어 엔지니어를 위한 examples/developer.sh에는 테스트 실행, CI 대기, 브랜치 동기화, 마이크 음소거 등 열 개 스위치와 출력 볼륨을 조절하는 익스프레션 페달 설정이 주석과 함께 들어 있다. DRY_RUN=1로 먼저 돌려 각 스위치의 동작을 확인하라고 안내한다. 구조적으로도 MIDI 디코딩·출력 포매팅·바인딩 파싱을 맡는 FCBNerdCore는 CoreMIDI 의존성이 없어 하드웨어 없이 테스트가 돌고, CoreMIDI 연결과 핫플러그, 시뮬레이터는 별도 CLI 모듈이 담당한다. 화려한 GUI 대신 유닉스 파이프 철학에 충실한 작은 도구로, 자동화 도구를 이미 쓰는 실무자라면 손쉽게 자신의 워크플로에 끼워 넣을 수 있다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://github.com/JamesRyanATX/fcbnerd
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기
처리 중...