2026년 5월 29일 금요일

Fluid Ardule, LCD의 외계어 표시를 없애다

Fluid Ardule의 UI 컨트롤러에 해당하는 아두이노 우노에는 I2C LCD 모듈이 연결되어 있다. 이것이 이따금 '외계어'를 표시하는 문제가 있었다. 가끔 일어나는 노이즈 문제라고 생각하기에는 그 빈도가 너무 잦았다. USB 커넥터를 뽑았다가 다시 연결해도 완벽하게 해결되지 않았다. 만약 내가 만드는 물건이 '상품'을 목표로 한다면, 도저히 시장에 내놓기 부끄러운 상태였다.


이 모습은 영화 <프레데터>에 나오는 Yautja 알파벳을 닮았다. 작년에 개봉한 <프레데터: 죽음의 땅> 관련 기사(LA Times 링크)에서는 이 문자와 언어 체계에 대한 상세한 정보가 담겨 있다. 



문제는 이것이 단순한 미관상의 문제가 아니라는 점이다. LCD는 Fluid Ardule의 보조 진단 장치 역할을 한다. 전원을 넣은 직후 상태를 알려주고, Raspberry Pi와 연결되었는지 여부도 표시한다. 따라서 화면이 깨진다는 것은 사용자가 장비를 신뢰하기 어렵다는 뜻이다. 설령 실제 기능은 정상이라 하더라도 말이다.

처음에는 I2C 통신 자체를 의심했다. 하지만 곧 이상한 사실을 발견했다. 외계어 현상은 Raspberry Pi와의 통신이 시작되기 전에도 발생한 적이 있었다. 그렇다면 원인이 Serial 통신에만 있는 것은 아니었다.

ChatGPT와 더불어 온갖 가설 수립과 실험을 해 보면서 생각이 조금씩 바뀌었다. 

문제는 LCD가 아니라 초기화 순서일 수 있었다.

UNO, PCF8574 I2C backpack, HD44780 LCD 컨트롤러는 전원이 들어온 뒤 각각 안정화되는 시간이 조금씩 다르다. 만약 Arduino가 너무 빨리 실행되어 lcd.init()를 호출한다면 LCD 쪽이 아직 완전히 준비되지 않았을 가능성이 있다.

전원을 넣으면 아두이노 우노가 켜지면서('cold start') LCD 모듈(컨트롤러 포함)에도 전원이 인가되어 자연스럽게 화면이 나온다. 이 때에도 외계어가 발생한 사례가 있었지만 매우 드물었다.

그러나 라즈베리 파이가 완전히 부팅되고 Fluid Ardule 서비스가 시작되면서 아두이노 우노와 USB를 통한 시리얼 통신을 수립하는 과정에서 우노는 다시 재시작될 수 있다. Arduino Uno의 기본 자동 리셋(auto-reset) 기능 때문이다.

이 경우 LCD는 계속 전원이 공급되고 있는데 우노만 다시 시작되는 상황이 발생한다. ChatGPT는 이러한 비대칭적인 재시작 과정이 LCD 상태 불안정의 한 원인일 가능성을 제기하였다. 다만 이것이 유일한 원인인지는 아직 단정할 수 없다.

그래서 RESET-GND 사이에 10µF 전해 콘덴서를 추가하는 실험을 했다.

이 콘덴서는 전원 안정화용이 아니다. RESET 핀의 상승 시간을 약간 늦추어 Arduino가 조금 더 늦게 시작하도록 만든다. 즉 LCD와 PCF8574가 충분히 준비된 뒤 초기화가 이루어질 가능성을 높이는 것이다.

놀랍게도 효과가 있는 것으로 보였다. 외계어 발생 빈도가 눈에 띄게 감소하였다.

그런데 이번에는 예상치 못한 부작용이 나타났다.

Arduino IDE에서 펌웨어를 업로드하려고 하자 갑자기 다음과 같은 오류가 발생했다.

not in sync: resp=0x55

한참 원인을 찾다가 문득 깨달았다. 10µF 콘덴서가 Arduino의 자동 리셋 기능까지 방해하고 있었던 것이다. 실제로 콘덴서를 제거하면 업로드가 정상적으로 이루어졌고, 다시 연결하면 동일한 문제가 재현되었다. 이는 콘덴서가 RESET 타이밍에 실제 영향을 주고 있음을 보여주는 간접적인 증거이기도 했다.

결국 콘덴서는 납땜된 상태로 두지 않고, 필요할 때 꽂았다 뺄 수 있는 탈착식 구조로 변경했다. 다음과 같은 프로토타입 실드를 쓰고 있기 때문에 소켓 헤더의 Rst와 GND에 전해 콘덴서를 필요한 때에 꽂는 것으로 충분하였다. 어제는 리셋 버튼 스위치 근처에 납땜을 하였었다.



그 과정에서 또 하나의 개선점을 발견했다.

현재 UNO-1 펌웨어는 전원 투입 시 LCD를 초기화하지만, Raspberry Pi와 처음 연결되는 순간에는 LCD를 다시 초기화하지 않는다. 그래서 최초 HELLO 메시지를 수신할 때 LCD를 한 번 더 재초기화하는 코드를 추가했다. 일종의 복구 계층을 만든 셈이다(Commit 0380f4a).

정리하면 현재 구조는 다음과 같다.

  • RESET-GND 10µF 콘덴서 → 예방 계층
  • HELLO 수신 시 LCD 재초기화 → 복구 계층

하나는 문제가 발생하지 않도록 돕고, 다른 하나는 혹시 문제가 생겨도 다시 정렬해 준다.

수정 후에는 서비스 재시작을 25회 이상 반복했지만 외계어 현상은 관찰되지 않았다. 물론 원래도 매우 낮은 빈도로 나타나던 문제였기 때문에 완전 해결을 선언하기는 이르다. 그러나 적어도 지금까지의 결과는 상당히 고무적이다.

돌이켜보면 이번 사건은 단순히 LCD 글자가 깨지는 문제를 해결한 것이 아니었다. 오히려 시스템의 초기화 시퀀스를 이해하게 된 과정에 가까웠다. 전원 투입, RESET 해제, LCD 초기화, Raspberry Pi와의 링크 수립이 서로 어떤 관계를 갖는지 다시 생각하게 만들었다.

가끔은 가장 작은 부품 하나가 가장 큰 교훈을 준다.

 

질문에 독이 있다

모르는 것을 상대에게 묻는 것을 질문이라 한다. 자신이 모르는 정보를 알아내고 싶거나, 이해와 설명을 구하기 위함이다. 따라서 질문이란 나의 무지를 전제로 하며, 질문하는 태도에는 겸손함이 따라야 한다. 그러나 많은 경우에 질문자는 답변을 통해서 상대를 평가하려는 숨은 의도가 있다. 그리고 그러한 의도를 굳이 숨기려고 하지도 않는다. 좋은 점이 드러나면 다행이지만, 망신을 당하기도 한다. 선거를 앞두고 벌어지는 토론회가 그러한 사례가 될 것이다. 토론회는 원래 그런 목적으로 열리는 것이니까.

이러한 의도를 품은 질문은 미처 방어할 준비를 하지 못한 상대를 당혹스럽게 만든다. 질타하거나 비난거리를 찾기 위한 질문이 바로 그러한 질문이다. 질문자가 '갑'의 위치에 있을 때, 그리고 그 대화가 이루어지는 자리에 다른 사람들이 많이 모여 있을 때 그러한 질문은 더욱 위력을 발휘한다. 자신의 영향력이나 지위를 과시하기 위해 던지는 질문도 흔하다.

"내가 몰라서 묻는 줄 아세요?"

이렇게 질문을 하고 의기양양하게 좌우를 둘러보는 사람도 있었다.

이 말과 제스쳐는 사실 질문의 목적을 스스로 폭로하는 것이다. 자신이 알고 있는 것을 이미 정답으로 정해 놓았음을 선언하는 것이며, 정보를 얻기 위함이 아니라 상대를 시험하고 압박하고 있음을 보여주는 행위이다.

질문이 압박의 도구가 되면 심문으로 바뀐다. 그러면 올바른 답변이 나오지 않는다. 흔히 'garbage in, garbage out'이라 한다. 질문도 이에 비유할 수 있다. 올바르지 않은 질문에는 좋은 답변이 나오지 않는 법이다. 잘못된 전제를 깔고 있는 질문, 어떤 답변을 하든 상대를 불리하게 만드는 질문, 원하는 곳으로 결론을 끌고 가기 위한 질문...

그래서 나는 독이 든 질문에 답하고 싶지 않다. 

2026년 5월 27일 수요일

Fluid Ardule, Wi-Fi 설정 기능까지 밀어넣다

인터넷 라디오 기능까지 넣고 나니, 이 기기를 다른 장소에 가져갔을 때 휴대폰 핫스팟에 연결하여 음악을 듣고 싶어졌다. 하지만 키보드나 터치 입력이 원활하지 않은 환경에서 Wi-Fi 암호를 직접 입력하는 UI를 만드는 것은 꽤 번거로운 일이다. 그래서 이미 알고 있는 네트워크 정보를 별도의 설정 파일(/etc/wpa_supplicant/wpa_supplicant-wlan0.conf)에 저장해 두고, 현재 검출되는 SSID 중에서 하나를 선택하는 단순한 방식을 구현해 보았다.

Wi-Fi 선택 화면. '설정'이라고까지는 이야기하지 못하겠다. 암호를 입력하지는 못하므로. 상판으로 사용할 아크릴판도 오늘 도착하였다. 가공을 의뢰한 전후판만 배송되면, 수일 내로 완성품을 만들게 될 것이다. 

개발을 이어가면서 네트워킹 가이드 문서도 함께 정리하였다. Raspberry Pi OS의 실제 동작 방식과 systemd 기반 Wi-Fi 설정 구조를 반영하여 내용을 다듬었는데, 일반적인 라즈베리 파이 네트워크 설정 가이드로 보아도 크게 어색하지 않을 정도로 완성도가 높아진 것 같다.

가끔 Raspberry Pi 3 Model B 와 Arduino Uno 의 연결 상태가 끊어져 기기가 통제 불능 상태에 빠지기도 한다. 대부분은 아두이노 우노를 리셋하면 문제가 해결되지만, 그렇지 않은 경우에는 라즈베리 파이에 SSH로 접속하여 서비스를 재시작해야 한다. 또한 CP2102 기반의 시리얼 콘솔(PuTTY 등)을 이용하면 네트워크가 동작하지 않는 상황에서도 시스템 복구가 가능하다. 시리얼 콘솔은 이미 지금도 사용하고 있다. 

사실 사운드 모듈이라는 본래 목적에만 충실하다면 네트워킹 기능은 전혀 필요하지 않다. MIDI 입력과 음원 재생만으로도 독립적인 전자 악기처럼 동작할 수 있기 때문이다. 하지만 인터넷 라디오 기능까지 추가하다 보니, 결국 외부 세계와 연결되는 최소한의 통로는 유지할 수밖에 없다. Wi-Fi는 가장 일상적인 통로이고, 비상 사태에 쓰기 위한 통로는 다음의 글을 참고하라.

휴대폰을 비상 콘솔로 쓰기

라즈베리 파이 기반 장비를 헤드리스(headless)로 운영하다 보면, 가끔 SSH 접속조차 불가능한 상황이 발생한다. 특히 Fluid Ardule처럼 TFT-LCD와 아두이노 우노 기반의 전용 UI를 사용하는 시스템에서는 입력 장치 연결이 끊어지면 사실상 조작이 불가능해질 수도 있다.

이럴 때 라즈베리 파이의 UART 시리얼 콘솔은 매우 강력한 비상 복구 수단이 된다. 나는 GPIO UART에 연결된 CP2102 USB-UART 모듈을 항상 장착해 두고 있으며, 평소에는 노트북에서 PuTTY를 이용하여 접속한다. 그런데 같은 작업은 휴대폰만으로도 가능하다고 한다.

준비물

  • Android 스마트폰
  • USB OTG 어댑터
  • CP2102 USB-UART 모듈
  • 시리얼 터미널 앱(예: Serial USB Terminal)

연결 구조

Raspberry Pi UART
        ↓
      CP2102
        ↓ USB
 Android Phone

휴대폰에 OTG 어댑터를 연결한 뒤 CP2102를 꽂고, 시리얼 터미널 앱을 실행한다. 보통 baud rate는 115200bps로 설정하면 된다. 연결이 성공하면 라즈베리 파이의 Linux 콘솔 로그인 프롬프트가 휴대폰 화면에 나타난다.

간단한 복구 명령

sudo systemctl restart fluid_ardule.service
journalctl -u fluid_ardule.service -n 3

이 방식의 장점

가장 큰 장점은 네트워크 상태와 무관하다는 점이다. Wi-Fi가 죽었거나 SSH가 동작하지 않아도, UART 콘솔만 살아 있으면 시스템 복구가 가능하다. 서비스를 재시작하거나 로그를 확인하는 정도의 유지보수는 휴대폰만으로도 충분히 수행할 수 있다.

또한 Bluetooth나 VNC 같은 무거운 기능을 다시 활성화하지 않아도 된다. 최소 기능만 유지한 경량 appliance 스타일의 시스템에서는, 이런 단순한 UART 콘솔 방식이 오히려 가장 안정적이고 확실한 유지보수 수단인지도 모른다.

2026년 5월 26일 화요일

Fluid Ardule, 인터넷 라디오 기능까지 구현하다

 

가공을 의뢰한 전후판과 상판이 수일 내로 도착할 것이다.

잠시 동작이 불안정했던 아두이노 우노 펌웨어를 다시 손보고, 드디어 인터넷 라디오 기능까지 넣어 보았다. 방송국 목록은 json 파일 형태로 직접 제공하는 단순한 방식을 택했다. 기능 자체는 잘 작동하지만, 인터넷 라디오를 원활하게 쓰려면 결국 Wi-Fi 설정 문제가 따라온다.

그렇다고 Wi-Fi 설정까지 장비의 작은 UI 안에 넣으려 하면 일이 지나치게 복잡해진다. 버튼과 인코더만으로 암호를 입력하는 일은 생각보다 번거롭다. 그래서 이 부분은 장비 안에서 억지로 해결하기보다, 필요할 때 터미널에서 설정하는 편이 낫다고 보았다. 아무런 네트워크가 잡히지 않은 상태에서도 라즈베리 파이에 접근할 수 있는 방법, 즉 USB 시리얼 콘솔이 남아 있다는 점은 이럴 때 큰 장점이 된다.

위에서 소개한 사진에서는 Fluid Ardule이 SomaFM의 방송국 중 하나를 재생하고 있다. SomaFM은 미국 샌프란시스코 기반의 독립 인터넷 라디오 서비스이다. 2000년부터 운영되어 왔으며, 광고 없이(listener-supported) 운영되는 채널이 많다는 점이 특징이다. 

이 서비스는 단순히 음악을 자동 재생하는 스트리밍 사이트라기보다, 각 채널마다 뚜렷한 분위기와 선곡 철학을 가진 ‘큐레이션 라디오’에 가깝다. 특히 앰비언트, 다운템포, 드론, 전자음악, 라운지, 재즈 계열 채널이 강하며, 오랫동안 DIY 오디오 애호가와 개발자들 사이에서도 잘 알려져 있다. 

Fluid Ardule에는 우선 몇 개의 대표 채널만 시험적으로 넣어 보았다. 예를 들어 Groove Salad는 다운템포와 칠아웃 계열 음악 중심이며, Drone Zone은 느린 드론·앰비언트 음악 위주의 채널이다. Deep Space One은 우주적인 분위기의 실험적 앰비언트 전자음악을 제공한다. 

이들 방송은 공개 스트림 URL 형태로 제공되므로 별도의 웹브라우저나 계정 없이도 mpv 같은 플레이어에서 직접 재생할 수 있다. Raspberry Pi 기반의 소형 오디오 장비와 잘 어울리는 이유도 여기에 있다. 

오늘의 Fluid Ardule 파이썬 스크립트(260526b)는 7687라인이다. '미디어 스테이션'으로 복잡하게 진화하려는 욕망을 억제하는 것도 어렵다. '불편하고 작은 PC'를 만드는 것이 나의 최종 목표는 아니기 때문이다.

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개를 이용하여 약간은 수고스럽게 배선 작업을 해야 한다. 


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


2026년 5월 26일 업데이트

자작나무 합판으로 만든 틀에 다이소 바니시를 발라서 잘 말렸다. 전후판(알루미늄 3T)도 가공을 맡겼다. 재단한 합판을 접착해 놓고 보니 단차가 발생하여 매우 아쉽고, 겉으로 살짝 흘러나온 목공본드를 바니시 도포 전에 깨끗하게 닦아내지 못한 것은 더더욱 아쉽다.



지금은 약간 사족과 같은 '인터넷 라디오' 재생 기능을 추가해 보고 있다. 그 과정에서 UNO-1 버튼 입력 검출의 문제가 다시 드러나서 이를 수정하기 위해 적잖이 골머리를 앓고 있다. 엊그제 구현한 self-calibration 기능도 아직 완벽하지 못하다. 이를 자세히 알아보자.

현재 입력 처리 로직에서는 롱프레스가 발생한 뒤 사용자가 버튼을 실제로 떼기 전에, 여전히 눌린 상태의 입력이 새로운 버튼 이벤트로 다시 해석되는 문제가 발생할 수 있다. 특히 아날로그 저항 사다리 방식의 5-key 입력에서는 ADC 값이 잠시 유지되거나 흔들리기 때문에, 롱프레스 처리 직후 동일 버튼이 다시 short press나 다른 명령으로 인식되어 메뉴 이동, 중복 실행, 의도하지 않은 동작이 연속적으로 발생한다. 따라서 롱프레스 이벤트가 발생한 이후에는 버튼이 완전히 릴리즈되고 입력값이 안정된 것이 확인될 때까지 추가 입력을 무시하는 “wait-for-release” 상태 처리가 반드시 필요하다.

모든 불만을 저항 사다리 방식의 5-버튼 키패드 모듈 안정성 탓으로 돌리고 싶지만, 이러한 판단이 정말 공정한지는 아직도 잘 모르겠다. 하드웨어의 편차, 펌웨어의 판정 로직, 릴리즈 감지 기준, 그리고 라즈베리 파이와의 통신 구조가 서로 복잡하게 얽혀 있기 때문이다.

취미 수준으로 만족할 것이 아니라 제품 수준의 완성도를 목표로 하려면 얼마나 많은 고민과 시행착오를 거쳐야 하는지 조금은 알 것 같다.

나머지 안정성 개선은 각자의 하드웨어 환경과 시행착오 속에서 계속 다듬어질 수밖에 없을 것이다. 어쩌면 그것이 DIY 프로젝트의 한계이자, 동시에 매력인지도 모른다. 그렇다 하더라도 최초의 '기발자'(기획자 + 개발자)로서, 적어도 내가 겪은 문제와 해결 과정만큼은 끝까지 책임지고 다듬어 나가고 싶다.

[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을 보게 될 것으로 기대한다.

[사족] 왜 threshold max보다 center 값이 더 나은가

다음의 글은 실제 UNO-1 펌웨어 개선 과정에서 얻는 경험을 바탕으로 정리한 것이다.

Fluid Ardule의 UNO-1은 하나의 아날로그 입력(A0)에 연결된 5-button keypad를 읽는다. 이 키패드는 여러 개의 저항으로 이루어진 일종의 저항 사다리(resistor ladder)이며, 각 버튼을 누르면 서로 다른 ADC 값이 나온다.

처음에는 다음과 같은 방식으로 버튼을 판정할 수 있다. 극히 최근까지 이 방법을 사용했었다.

if (adc <= TH_LEFT_MAX)   LEFT;
else if (adc <= TH_UP_MAX)     UP;
else if (adc <= TH_DOWN_MAX)   DOWN;
else if (adc <= TH_RIGHT_MAX)  RIGHT;
else if (adc <= TH_SELECT_MAX) SELECT;
else NONE;

이 방식은 단순하고 이해하기 쉽다. 그러나 이 값들은 사실 각 버튼의 중심값이 아니라, 버튼 구간의 상한선(max threshold)이다. 즉 “현재 ADC 값이 어느 버튼 값에 가장 가까운가?”를 보는 것이 아니라, “정해진 경계값보다 작은가?”를 순서대로 검사하는 방식이다.

반면 center 기반 판정은 각 버튼의 대표 ADC 값을 저장해 두고, 현재 읽은 ADC 값이 어느 버튼의 중심값에 가장 가까운지를 계산한다. 예를 들어 다음과 같은 값이 있다고 하자.

LEFT   = 60
UP     = 195
DOWN   = 355
RIGHT  = 560
SELECT = 805
NONE   = 1015

ADC 값이 390이라면 DOWN 중심값 355와의 거리는 35이고, RIGHT 중심값 560과의 거리는 170이다. 따라서 이 값은 DOWN으로 보는 것이 자연스럽다.

이 방식은 저항값의 오차, 모듈마다 다른 특성, 전원 전압 변화에 더 유연하다. 특히 self-calibration을 도입한 경우에는 각 버튼의 실제 ADC 대표값을 측정하게 되므로, threshold를 직접 저장하기보다 버튼별 center 값을 저장하는 편이 더 타당하다. threshold는 필요하면 center 값 사이의 중간점으로 나중에 계산할 수 있다.

threshold = (center_A + center_B) / 2

즉 center는 원본 측정값이고, threshold는 그로부터 파생되는 값이다. 원본 데이터를 저장해 두면 나중에 허용 오차, hysteresis, release 판정 방식을 바꾸더라도 기존 calibration 데이터를 더 유연하게 활용할 수 있다.

물론 max threshold 방식에도 장점은 있다. 코드가 짧고 빠르며, Arduino 예제에서 흔히 쓰이는 방식이다. 하지만 Fluid Ardule의 UNO-1처럼 long press, rotary encoder, potentiometer, self-calibration, EEPROM 저장까지 포함하는 입력 컨트롤러라면 center 기반 판정이 더 안정적인 설계에 가깝다.

정리하면 다음과 같다.

max threshold 방식:
- 단순하다
- 디버깅이 쉽다
- 하지만 모듈 편차와 전압 변화에 약하다

center 기반 방식:
- 실제 버튼의 대표 ADC 값을 저장한다
- self-calibration과 잘 맞는다
- 가장 가까운 버튼을 찾는 구조라 더 자연스럽다
- threshold는 center 값에서 계산할 수 있다

따라서 Fluid Ardule UNO-1에서는 fallback 값도 고정 threshold보다는 버튼별 기본 center 값으로 관리하는 것이 바람직하다. EEPROM에 저장된 calibration 값이 없거나 손상되었을 때는 이 기본 center 값을 사용하고, 사용자가 self-calibration을 수행하면 실제 장치에 맞는 center 값으로 갱신하는 구조가 가장 안전하다.

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은 다음 단계의 설계 주제로 떠올랐다. 이 작은 악기가 점점 더 악기다워지고 있다.

2026년 5월 8일 금요일

헤드폰 이어패드 갈기

헤드폰의 이어패드는 몇 년 사용하면 표면이 갈라지고 부서져서 떨어져 나간다. 따라서 주기적으로 교체하는 것이 바람직하다. 고급 헤드폰이라면 교체용 이어패드를 쉽게 살 수 있지만, 저가품은 그렇지 못하다. G마켓을 뒤져서 사이즈가 맞을 것으로 추정되는 것을 골라 보았다. 

먼저 아이리버 유선 헤드셋 IR-H30V. 2019년 4월 제조품이다. 온라인 회의를 하려면 반드시 필요한 물건이다. 음질고 그저 그렇고, 너무 귀를 꽉 눌러서 오래 착용하면 불편하다. 패드를 끼우는 부분은 측정 결과로는 대략 75mm x 90mm의 타원형인데 G마켓의 판매자는 이것에 딱 어울리는 물건을 갖고 있지는 않다. 75mm x 94mm의 것을 구입하였다. 아주 잘 맞지는 않는다.

다음으로 오디오 테크니카의 TH-380AV. 원형 이어패드로서 직경 7cm인 것을 구입하였다.

이어패드를 교체한 IR-H30V(왼쪽)과 TH-380AV.

이상의 두 헤드셋/헤드폰은 사무실에서 사용한다. 다음으로는 집에서 음악 작업으로 쓰는 베링거 BH 470. 내가 사용하는 헤드폰 중에서는 음질과 착용감 면에서 가장 우수하다. 이 헤드폰은 크기가 딱 맞는 교체용 이어패드가 이미 존재하여 한 차례 바꾸었었다. 잘 쓰다가 헤드밴드 부위의 패드가 찢어져서 아예 빼 버린 흉칙한 생태였는데, 마침 이어패드와 함께 파는 것이 있길래 구입해 보았다. 헤드밴드 커버는 지퍼로 채우는 형태이다. 밴드에 붙어 있던 내부 쿠션까지 다 떼어버린 상태라서 주변에 굴러다니는 스펀지를 잘라서 채웠다. 그래서인지 교체 완료한 헤드밴드 패드의 모양이 영 예쁘지 못하다.

BH 470 헤드폰의 이어패드는 현재 쓰고 있는 것의 상태가 아직 나쁘지 않아서 교처하지 않았다.

이어패드가 부스러지기 시작한 아이리버 헤드셋은 워낙 저가품이라서 아예 새것으로 구입할 생각도 해 보았으나 전기적으로 고장난 것이 아니라면 패드를 갈아서 계속 사용하는 것이 더 낫다는 결심을 하였었다. 실행에 옮긴 결과에도 그런대로 만족한다. 탄소배출 저감에 조금이라도 기여하지 않았겠는가?

당일치기 제주도 출장

번잡한 삶을 싫어하는 나에게 겹겹이 엉킨 출장 스케쥴은 여간 고역이 아니다. 강릉에서 열렸던 워크샵에서 늦은 발표를 마치고 만찬도 참석하지 못한 채 차를 몰고 자정이 다 되어 대전으로 돌아온 뒤, 바로 다음날 아침 청주국제공항으로 향했다. 제주에서 열리는 <2026 제주 바이오기업 AI 대전환 컨퍼런스>에 발표 요청을 받았기 때문이다(뉴스 링크). 행사장(메종글래드 제주 호텔)이 제주국제공항과 가까운 것은 천만다행이었다.

행사 현장을 취재한 기사는 검색이 되지 않아서 아쉽다.


편의점에서 샌드위치로 점심을 때우고 행사에 참석하여 발표를 마쳤다. 원래 저녁 만찬까지 이어지는 행사였기에 주최측인 제주테크노파크에서 1박을 지원해 준 상태였다. 그러나, 다음날 과기부 회의를 들어가려면 아침 비행기로 돌아가서는 도저히 동료들과 회의 자료에 대한 사전 검토를 할 시간이 없을 것 같았다. 주최측에 사정 이야기를 하여 숙박을 취소한 뒤, 항공권을 바꾸어서 저녁 6시 비행기로 다시 돌아와야만 했다. 생명(연) 및 KOBIC에 관심을 갖는 새로운 사람들을 만나는 것은 좋았으나, 너 많은 사람과 교류할 수 있는 기회를 스스로 반납한 채 급박하게 돌아오게 되어 너무 아쉬웠다. 자리를 끝까지 지키지 못한 것에 대해 주최측에는 너무나 죄송스런 마음이 든다.

정오가 지나 제주에 도착하여 저녁 6시에 제주를 떠나다.

당일치기 제주 출장은 사실 이번이 처음은 아니다. 김포공항에서 출발하여 제주에서 학술행사를 마친 뒤 그날 다시 돌아온 일이 몇년 전에 딱 한번 있었다. 대전 집에 무사히 도착하니 자정을 넘긴 시각이라서 출장일 당일에 모든 일이 이루어진 것은 아니었다. 그러나 이번 출장에서는 단 6시간 이내에 제주에서 모든 일을 마치고 돌아오는 신기록을 세웠다.

다음주 금요일에도 이와 비슷한 일정을 소화해야 한다. 대륙을 바쁘게 오가는 큰 기업의 CEO도 아니면서 겨우 이정도의 일에 비명을 지르면 엄살일 것이다.

관광지의 여유를 전혀 느끼지 못했던 2026년 5월 7일의 제주 출장.


2026년 5월 3일 일요일

[Fluid Ardule] 외부 사운드 모듈을 제어하기 시작하다

Fluid Ardule은 사운드폰트 기반 DIY 신시사이저 모듈로서 충분한 목표 기능에 도달하였다. UNO-2(아두이노 기반 MIDI 입력 처리기)는 Fluid Ardule의 필수 구성품은 아니지만 DIN MIDI IN/OUT을 갖춘 장비를 연결하기 위한 기구 용도로 사용해 왔었다.

UNO-2에 달린 MIDI OUT을 이용하여 내부에서 생성된 MIDI 연주 신호를 외부 모듈로 보내보려고 노력해 보았으나 결과는 그렇게 만족스럽지 않았다. 그래서 USB MIDI 케이블을 사용해 보기로 했다. 라즈베리 파이에 연결한 키보드의 연주 신호를 그대로 복제하여 USB MIDI 케이블로 내보내는 것은 그다지 어렵지 않았다. 이를 'Mirror' 기능이라 부르기로 하였다.

다음으로는 이렇게 연결한 외부 모듈이 File Player를 통해 작동하게 만들었다. 재생 동작 자체는 문제가 없었으나 stop/pause를 실시하면 stuck note가 발생한다. 소프트웨어 신스를 쓸 때에는 중단/일시정지 동작에서 자동적으로 사운드 엔진을 재시작하게 만들었지만, 외부 모듈에까지 미치지는 못한다. 이 문제를 해결하기 위하여 약간의 작업을 실시하였다.

여기까지 진행을 하면 다음 단계는 너무나 자연스럽게 Program Change가 되도록 만드는 것 아니겠는가? 구현은 그다지 어렵지 않았다.

드디어 Fluid Ardule을 통해 외부 GM sound module의 제어가 되기 시작하였다.

하나를 해결하면 또 다음 숙제가 자연스럽게 떠오른다. USB MIDI cable 말고도 나는 롤랜드 사운드캔버스 SC-D70을 갖고 있지 않은가? 라즈베리 파이와 이것을 USB 케이블로 연결하면 외부 DAC와 MIDI interface 및 음원으로서 활용 가능하다. 이토록 훌륭한 기능을 가능성으로만 남겨 둘 이유가 없다.

그래서 열심히 일요일 개발을 이어갔는데... 드디어 6천 라인을 넘겼다. 리팩토링을 시작할 시점이 되었다는 신호를 주고 있는 셈이다. 원하는 기능은 어렵지 않게 구현하였다. 복잡한 메뉴 속에서 길을 잃을 상황은 아니다. 거미줄처럼 뒤엉킨 케이블을 내가 어떤 의도로 연결했는지 잊지 않는 것이 중요하다.

이 장치의 복잡성은 라즈베리 파이에 연결된 USB 기기가 결정한다. 키보드 컨트롤러라면 그것으로 끝이다. 하지만 UNO-2라든가, 사운드캔버스 SC-D70의 경우라면 이야기가 달라진다(사실 SC-D70을 DAC가 아닌 USB 기기로 동작시키는 것은 오늘 구현하였음). SC-D70은 MIDI 신호를 받아서 내부 음원을 울릴 수 있지만. 자체 DIN MIDI IN/OUT을 통해 확장이 가능하기 때문이다. 따라서 오늘 개발의 마지막 단계에서는 '(라즈베리 파이에) 꽂아야 UI에 비로소 보인다'는 원칙을 지키고자 하였다.

새 버전의 파이썬 스크립트(launch_fluidardule.py, 저장소)가 만들어졌을 때 테스트할 기능도 점점 많아져서 이제는 점검용 시나리오를 써야 할 수준이 되었다. 그에 따라서 UI 자체가 심각하게 복잡해지지는 않았으니 다행이라고나 할까.

취미의 시작은 '(장비)탑 쌓기'로부터 시작한다. 그러나 이건 너무나 소박한 탑이다.

원래 systemctl로 시작해야 할 파이썬 스크립트를 테스트하기 위해 터미널에서 직접 실행 및 중단('Ctrl + C')을 반하다보면 UNO-1(아두이노 기반 UI 입력 컨트롤러, 버튼/인코더/포텐셔미터를 처리)과의 시리얼 통신이 깨지고는 한다. 왜 그러한지 ChatGPT에게 상세한 설명을 부탁하였다.

수동 실행 시 UNO-1 시리얼 연결이 불안정해지는 이유

launch_fluidardule.pysystemctl로 실행할 때에는 UNO-1과의 통신이 대체로 안정적이다. 그러나 터미널에서 직접 실행하고 Ctrl+C로 종료한 뒤 다시 실행하면, 가끔 UNO-1이 기대한 것처럼 리셋되지 않거나 연결이 불안정해지는 경우가 있다.

1. 기본 구조

UNO-1은 Raspberry Pi와 USB-serial 방식으로 통신한다.

UNO-1 → USB serial → Raspberry Pi의 Python 스크립트

Python 스크립트는 지정된 시리얼 포트를 열어 UNO-1과 데이터를 주고받는다.

2. DTR의 역할

Arduino UNO는 시리얼 포트가 열릴 때 DTR(Data Terminal Ready) 신호 변화에 의해 리셋되는 구조를 갖고 있다. 이는 Arduino IDE에서 스케치를 업로드할 때 보드를 자동으로 리셋하기 위한 일반적인 동작이다.

serial.open()
→ DTR 신호 변화
→ UNO 리셋

따라서 Fluid Ardule 스크립트가 UNO-1의 시리얼 포트를 열면, 보통 UNO-1은 자동으로 리셋되고 초기 상태에서 통신을 시작한다.

3. 터미널 수동 실행에서 생길 수 있는 문제

터미널에서 스크립트를 직접 실행하고 Ctrl+C로 종료하는 과정을 반복하면 다음과 같은 상황이 생길 수 있다.

  • 이전 Python 프로세스가 아직 시리얼 포트를 점유하고 있음
  • Ctrl+C 종료 시 시리얼 포트가 완전히 정리되지 않음
  • DTR 상태가 이미 바뀐 상태로 남아 있어 다시 열어도 리셋 펄스가 발생하지 않음
  • systemd 서비스와 수동 실행 프로세스가 같은 포트를 동시에 사용하려 함
  • UNO-1 리셋 직후의 초기 메시지와 새 실행의 통신이 섞임

이 경우 UNO-1이 리셋되지 않거나, Python 스크립트가 초기 handshake를 안정적으로 받지 못할 수 있다.

4. systemctl 실행과의 차이

systemctl로 실행할 때에는 보통 부팅 후 한 번만 스크립트가 시작된다.

부팅
→ systemd 서비스 시작
→ Python 스크립트 실행
→ 시리얼 포트 open
→ DTR 변화
→ UNO-1 리셋
→ 정상 통신 시작

반면 터미널 수동 실행에서는 다음과 같은 흐름이 반복된다.

python3 실행
→ Ctrl+C 종료
→ 다시 python3 실행
→ 이전 시리얼 상태가 남아 있을 가능성

따라서 재부팅 후에는 정상인데, 터미널에서 반복 실행할 때만 불안정한 현상이 나타날 수 있다.

5. 수동 테스트 시 권장 절차

터미널에서 직접 테스트할 때에는 먼저 서비스를 중지하고, 남아 있는 프로세스가 없는지 확인하는 것이 좋다.

sudo systemctl stop fluid_ardule.service
pkill -f launch_fluidardule.py
sleep 1
python3 /home/pi/scripts/launch_fluidardule.py

필요하면 시리얼 포트를 점유한 프로세스를 확인할 수 있다.

lsof /dev/serial/by-id/usb-Arduino__www.arduino.cc__Arduino_Uno_12724551266415469650-if00

이 명령에서 아무 프로세스도 나오지 않아야 수동 실행하기 좋은 상태다.

6. DTR을 명시적으로 토글하는 방법

더 확실한 리셋이 필요하다면 Python 코드에서 DTR을 명시적으로 토글할 수 있다.

ser.setDTR(False)
time.sleep(0.1)
ser.setDTR(True)

다만 이 방법은 개발 편의용 보강책에 가깝다. 실사용 환경에서 systemd가 부팅 시 한 번 실행하는 구조라면 반드시 필요한 처리는 아니다.

7. 정리

터미널에서 수동 실행할 때 UNO-1 연결이 가끔 불안정해지는 것은 하드웨어 고장이라기보다 USB-serial 포트와 DTR 신호 상태가 반복 실행 과정에서 깔끔하게 초기화되지 않기 때문일 가능성이 높다.

재부팅하면 정상으로 돌아오고, systemctl 실행에서는 문제가 없다면 구조적인 결함으로 보기보다는 개발 중 수동 실행에서 생기는 일시적인 상태 꼬임으로 보는 것이 적절하다.

ChatGPT의 설명은 여기까지. 

오늘의 결론은 간단하다. Fluid Ardule은 이제 내부 SoundFont 음원 모듈을 넘어 외부 GM sound module까지 제어할 수 있는 작은 MIDI 스테이션이 되었다. 그러나 동시에 더 이상 무작정 기능을 얹어서는 안 되는 단계에 도달했다. 앞으로의 과제는 기능 추가가 아니라 정리, 저장, 그리고 리팩토링이다.

그리고... 이런 책을 읽기 시작하였다. 내가 지금의 취미 개발 프로젝트를 하는 것은 샘 올트먼이 세운 '제국' 덕분이다. 이 기술이 취미 생활의 효율을 상상할 수 없는 수준으로 가속하는 것은 인정하지만, 세상의 모든 자원을 빨아먹는 이 기술에 나 자신과 세계관을 맞추어 나가야 하는지는 여전히 의심스럽다.



2026년 5월 2일 토요일

[게으른 독서 기록] 천문학자의 쓸모없음에 관하여 외 3권

빌렸던 책을 반납하러 도서관에 가기 전에 꼭 해야 할 일은 기록을 남기는 것이다. 오늘은 기록을 남기는 방식 중 게으른 방법을 택하려 한다. 외부 링크를 연계하여 책 정보에 대한 최소한의 기록만 남기려 한다.


《천문학자의 쓸모없음에 대하여》ISBN: 979-11-24070-35-2 교보문고

《당신도 러너다》'러너임바의 러닝 참견' ISBN: 978-89-6744-304-7 교보문고

《인구는 거짓말하지 않는다》'세상의 모든 변화를 결정하는 인구의 경제학' ISBN: 978-89-01-29917-4 교보문고

《브레이크넥》'변호사의 나라 미국과 엔지니어의 나라 중국은 어떻게 미래를 설계하는가' ISBN: 978-89-01-29936-5 교보문고

교보문고 링크의 리뷰는 그다지 영양가가 없는 것 같다. 일반 상품 구매에 비유한다면 '아직 포장도 뜯지 않았지만 좋은 상품인 것 같아요'라는 수준의 것이 많았기 때문이다.

네 권의 책 중에서 앞의 두 권은 가볍게 읽기에 좋았다. 저자와 편집자(그리고 출판사)에게는 미안한 이야기지만, 나도 책 한 권 내고 싶다는 욕심이 들게 만드는 책이었다. 물론 두 권의 책을 깎아내리려는 것은 절대로 아니다.

《인구는 거짓말하지 않는다》는 인구 감소의 심각성과 이를 되돌리기 위한 모든 정책이 실패했음을 적나라하게 보여주고 있지만, 그래서 무엇을 어떻게 해야 하는가에 대한 특별한 답은 주지 않는다. 그것은 우리 세대가 해결해야 할 숙제이니까. 《브레이크넥》에서는 서로 주도권을 잡기 위해 대결하는 듯한 미국과 중국 두 나라의 차이를 공학자(엔지니어)와 변호사의 나라라는 차원에서 매우 흥미롭게 다루었다. 책 뒷표지에 인쇄된 글귀를 인용해 본다.

  • 변호사의 나라 미국: 거의 모든 분야에서 '세계 최초' 혁신을 이뤄 왔으나 규제와 절차에 갇여 물리적 역동성을 읽어버린, 핵 기밀 부품조차 만들 수 없는 빈약한 제조 역량과 노후화된 기반 시설만 남은 나라
  • '엔지니어의 나라 중국': 이공계 출신 권력자들의 빠르고 과감한 의사결정, 바닥부터 다진 절차적 지식과 압도적 생산력으로 급부상했으나 억압과 통제의 대가를 뒤늦게 치르고 있는 나라

우리나라는 어떤 길을 걷고 있는가? 미국과 중국 외의 다른 모델도 물론 존재할 수 있을 것이다. 그러나 자칫 잘못하다가는 두 나라의 좋지 않은 점만 절묘하게 택할 가능성도 없지는 않을까 두렵다. 혁신은 줄고, 규제는 늘며, 생산력은 떨어지고, 통제는 강화되는 그런 사회 말이다. 요즘 내가 사무실에서 접하는 상황과 딱 맞아 떨어지는 느낌이 든다.

2026년 5월 1일 금요일

밴드 KRIBBtonite, 4월 공연을 마치다




저지르고 조르면 꿈은 이루어진다. 그렇게 밴드 KRIBBtonite는 결성 이래 가장 큰 무대에서 가장 좋은 음향 장비를 앞세우고 공연을 마쳤다. 좋은 기회를 준 한국생명공학연구원, 공연을 즐겨 준 연구원 식구들, 그리고 어려운 여건 중에도 연습과 당일 공연에 열과 성을 다해 준 멤버들이 너무나 고맙다. 아마추어 밴드로서 앞으로도 이만한 규모의 공연을 또 경험할 수 있을까? 어쩌면 처음이자 마지막인지도 모른다. 연구원 전 직원이 참여하는 야외 행사를 개최한 것도 얼마만인지 모른다.


음향팀과 사전에 충분한 협의를 거치지 못한 상태라서 걱정이 많이 되었었다. 일단 나는 팀의 리더이긴 하지만 이런 큰 규모의 야외 공연 경험이 전무하고, 겨우 총 출력과 필요한 채널, 마이크 수, 케이블 종류 정도만 요구한 상태였기 때문이다. 공연 경험이 있던 젊은 멤버 덕분에 그나마 막바지 의사소통을 할 수 있었다. 심지어 공연 전날까지 '갑자기 과기부에서 회의한다고 부르면 어떻게 하지?'라는 걱정을 하고 있었다.

그러나 이런 걱정은 전부 기우였다. 전문적인 음향 엔지니어 덕분에 사운드 체크는 순식간에 끝났다. 

"베이스 드럼 쳐 보세요."

"스네어 쳐 보세요."

다음에 또 음향장비를 빌려서 공연을 할 때에는 이날의 경험을 바탕으로 하여 우왕좌왕하는 일이 없을 것 같다. 결성된지 이제 1년 반 정도에 불과한 밴드로서 연구원 내부에서 소규모 공연을 진행해 왔기에 이번 행사를 통해 얻는 경험은 정말 값지다고 말하지 않을 수 없다.



무대 위에 삼각대를 설치하고 개인 기록을 위해 셀프 영상을 찍었는데 그냥 두기는 아깝다는 생각이 들었다. 다른 사람이 찍은 자료를 합쳐 편집한 뒤 두 편으로 나누어 유튜브에 올렸다. 아래는 소개를 위한 쇼츠 영상.


그리고 나머지 분량을 정식 유튜브용으로 편집하였다. OpenShot Video Editor로 세로 영상 좌우에 blur 처리를 한 영상을 채워서 가로 포맷을 만드느라 정말 미련한 방법을 동원하였다.


모든 행사를 마치고 무대를 정리하면서 모든 멤버와 함께 기념 사진을 찍었다.




6월에는 김천에서 버스킹을 할 것 같다. 참여자를 확정하고 선곡 및 연습을 또 진행해야 한다. 이번에는 내 자작곡을 올릴 수 있을 것이다. 

2026년 4월 30일 목요일

JKD: 세상에 없는 저널

만우절에 창간호를 발행하면 딱 좋을 패러디 저널을 생각해 보았다. 이름하여 Journal of the KOBIC Director (JKD-RIFT: Rapid exchange of Inconvenient truths & critical reFlecTion)! 데이터와 인공지능의 파도에 지친 실무자들의 고민과 불만을 담은 글을 싣는다는 취지이다. 가상의 임팩트 팩터는 -10. 인용하는 사람이 손해!

JKD cover
인공지능이 생성한 패러디 저널 JKD의 창간호 예상 표지.

키워드를 ChatGPT에 던져주고 자동 작성한 글을 꽤 갖고 있으니 이를 정리하여 창간호를 만들면 어떨까? 예를 들어 이런 것들이다.

  • Crossing Data, Connecting Life — 데이터 연계를 넘어 데이터 세트로
  • AI 독재 / 데이터 독재 담론에 대한 근거 기반 비판: 'AI-readiness' 압박에 대한 메모
  • 연구데이터는 왜 막히고 병원 데이터는 흐르는가 — 가명처리 시대의 구조적 자기모순과 정책 실패
  • 데이터 구축 사업과 데이터 리포지터리 서비스는 왜 다른가
  • 유전체 민감정보의 Controlled Access: 한국 데이터 거버넌스에서의 구조적 질문
  • 국가 데이터 플랫폼은 성과관리 시스템이 아니다 — 데이터 인프라와 연구 행정의 혼동에 대하여

꽤 그럴싸한 제목과 내용을 담고 있으며, 학술지 투고까지 이룰 수 있는 수준은 아니지만(또 그렇게 해서도 안되겠지만) 이 분야의 공부와 논의를 위해서 활용하기에는 나쁘지 않다. 물론 자동 생성한 글이 담고 있는 주장에 대해 근거를 확인하는 일은 반드시 필요하다.

이런 아이디어는 새로운 것도 아니다. 이미 작년에 인공지능 100%로 만든 신문 특별호가 나왔으니 말이다.

이탈리아 세계 최초 '100% AI 신문' 나왔다

출판계에서는 이미 대세가 되었다. 가디언 에 따르면 특정 분야, 예를 들어 허브(herb)를 이용한 치유 분야-약초학-에서는 82%의 서적이 인공지능에 의해 쓰인 것으로 의심된다고 하였다. 문제는 전적으로 인공지능을 통해 만든 글을 마치 사람이 직접 수고를 들여 만든 것처럼 속이는 데에 있다.

독자들에게 생각할 거리를 던지는 것을 목표로 하는 패러디 저널 — 디렉터의 지시에 따라 인공지능이 자동 생성한 글로 채워진다 — 나쁘지 않다. 일년에 두 차례 정도 온라인 전용으로 발행하되, 언젠가는 Journal of the Former KOBIC Director가 될 것이다. 그때가 되면 더욱 날카롭고, 더 자유로우며, 더 불편한 글을 실을 수 있을 것이라 기대해 본다.

2026년 4월 26일 일요일

건반은 늘어가고, DIY Synth의 완성도는 높아가고

사운드 모듈(Fluid Ardule, GitHub) DIY에 빠져 있으니 다음 관심사는 여기에 잘 어울리는 건반을 하나 더 구하는 것이다. 심심할 때마다 Mule 장터나 당근마켓을 뒤적거리다가 ICON iKeyboard 8Nano가 매력적인 가격에 나온 것을 발견하였다. 나는 이미 같은 브랜드의 5Nano(49키 제품)을 갖고 있지만, 키 수가 약간 부족한 것에 불만을 느끼고 있었다. Korg X2 Workstation(76키)는 외장형 사운드 모듈의 컨트롤러로 쓰기에는 부족함이 없지만, 필요할 때마다 꺼내서 펼치기에는 꽤 무겁다. 작년 이맘때에는 X2를 수리하느라 여념이 었었다(KORG X2 Self-Repair). 전원부를 개조하고, 모든 tactile switch를 교체하는 등 많은 노력을 들였었다.

ICON iKeyboard Nano 시리즈는 알루미늄 하우징으로 둘러싸여 있어서 견고한 반면 슬림한 형태로 만들어 재료 소요량을 줄인 덕문인지 그렇게 무겁지 않다. 88키 제품(8Nano)의 경우 무게는 약 6.5kg 정도이다. 당근마켓에 올라온 매물을 흥미롭게 하루 이틀 지켜보고 있던 중 다른 사람이 걸어 놓은 예약이 무산되면서 가격이 더 떨어진 상태가 되었다. 기회가 나에게 온 것으로 확신하고 구입 예약을 한 뒤 일요일 오전 한남대학교로 향했다.



위에서 두 번째 건반이 이번에 구입한 ICON 8Nano.

Fluid Ardule은 하루가 다르게 발전하여 이제는 Yoshimi까지 울릴 수 있는 상태가 되었다. 지금까지 구현한 많은 기능을 아직도 파이썬 스크립트 파일 하나에 쑤셔 넣어서 버티고 있다. 현재 스크립트는 4,600 라인을 넘었다. 음색에 대한 편집 및 저장 기능까지 넣게 되면 드디어 파일을 분할해야 될 것 같다.

현재 가장 즐겨 사용하고 있는 미디어 파일 재생 기능.

버스 파워로 구동되는 기기를 라즈베리 파이에 꽂을 때마다 'Undervoltage detected!' 경고문이 뜨는 것이 마음에 들지 않아서 오늘 오후에는 간단한 케이블 어댑터를 만들었다. 3개 선(D+, D-, GND)으로만 두 기기가 연결되게 하되 시스템 전체에 전원을 공급하는 Meanwell 5V 10A SMPS에서 선을 뽑아서 하위 기기의 VBUS에 연결하였다.


위 사진의 케이블 어댑터의 실제 구조는 다음과 같다. 두 개를 만들어서 SMPS에 연결하는 선을 한데 합친 뒤 Y형 압착 단자로 말단 처리를 하였다. 지난 1월에 만든 "또 다른 버전"에서는 외부 전원을 연결하지 않은 방식을 택하였었다(사진, 원본 글). 이때 만든 케이블 어댑터를 쓰려면 USB 기기에는 직접 5V 전원을 공급해 주어야 한다.

왼쪽에는 라즈베리 파이(호스트), 오른쪽에는 건반과 같은 USB 디바이스를 연결한다. USB 디바이스는 호스트가 아니라 Mean Well SMPS로부터 충분한 전류의 5V 전원을 공급받는다. 개조하지 않은 일반 케이블을 사용한다면 라즈베리 파이에서 포트 당 0.5A 정도의 전류를 뽑을 수 있으나 총합은 1.2A 내외로 제한된다. 이러한 부족함을 돌파하고자 USB 디바이스에 아예 외부 전원을 공급하는 케이블 어댑터를 만들게 된 것이다.

이렇게 하였더니 UI controller로 쓰이는 아두이노 우노(UNO-1)에 전원이 공급될 때 나오던 undervoltage 경고는 사라졌다. 그러나 MIDI 키보드 컨트롤러는 여전히 연결 직후에 전압이 부족하다는 메시지를 내보인다.

이 메시지에 이어서 항상 'Voltage normalised'라는 표시가 나오기 때문에 기기에 따라서 연결 직후에만 순간적인 전압 강하 현상이 일어났다가 즉시 정상 상태로 복귀가 되는 것으로 여겨진다. 그러나 내가 갖고 있는 유전원 USB나 10A급 SMPS로도 말끔하게 해결되지가 않는 것은 여전히 미스테리이다.

ICON 8Nano를 연결하고 사진을 찍었다.

전압 관련 메시지는 시스템 콘솔(시리얼 통신을 이용하여 PuTTY에서 접속) 화면이나 dmesg -w 명령을 통해서 실시간으로 볼 수 있다. dmesg는 부팅 이후 경과한 시간을 초 단위로 커널 메시지를 보여주므로, 우리에게 익숙한 시각(몇시 몇분 몇초)으로 표시하려면 dmesg -wT가 더 편리하다.

'dmesg -wT'를 실행한 뒤 키보드를 연결했을 때 나오는 메시지.

dmesg는 시스템 작동에 대한 모든 메시지가 다 나오므로 다소 번잡하다. 라즈베리 파이의 전원 상태, 특히 저전압 발생 여부를 확인하려면 다음 명령어(vcgencmd)를 사용한다.
vcgencmd get_throttled

예를 들어 다음과 같이 출력될 수 있다.

throttled=0x0

이 경우는 정상이다. 현재 저전압도 없고, 과거 저전압 기록도 없다는 뜻이다. ChatGPT를 이용하여 이 명령어의 결과 설명에 대해 좀 더 알아보자.


주요 결과 해석

출력값 의미
throttled=0x0 정상. 저전압 또는 클럭 제한 이력 없음
throttled=0x1 현재 저전압 상태
throttled=0x2 현재 클럭 제한(throttling) 상태
throttled=0x50000 과거에 저전압 및 클럭 제한이 발생한 적 있음
throttled=0x50005 현재도 저전압/클럭 제한이 있고, 과거에도 발생한 이력이 있음

자주 보는 비트 의미

비트값 의미
0x1 현재 저전압 감지
0x2 현재 클럭 제한 중
0x4 현재 주파수 제한 중
0x10000 부팅 이후 저전압이 발생한 적 있음
0x20000 부팅 이후 클럭 제한이 발생한 적 있음
0x40000 부팅 이후 주파수 제한이 발생한 적 있음

즉, 0x1이 포함되어 있으면 지금 전압이 낮다는 뜻이고, 0x10000이 포함되어 있으면 현재는 괜찮더라도 부팅 이후 한 번 이상 저전압이 있었다는 뜻이다.


실전 해석

USB MIDI 장치, 오디오 DAC, 아두이노, 외장 USB 메모리 등을 라즈베리 파이에 함께 연결했을 때 장치가 끊기거나 재인식된다면 이 명령어를 먼저 확인해 보는 것이 좋다.

vcgencmd get_throttled

결과가 throttled=0x0이면 전원 상태는 비교적 양호하다. 그러나 0x1, 0x10000, 0x50000, 0x50005 같은 값이 나온다면 전원 공급, USB 케이블, 커넥터, 허브, 배선 저항 등을 점검해야 한다.

특히 라즈베리 파이 3B처럼 USB와 이더넷이 내부적으로 같은 버스를 공유하는 보드에서는 전원 품질과 USB 부하가 시스템 안정성에 큰 영향을 줄 수 있다. ChatGPT 설명은 여기까지.

갑자기 아이디어 하나가 머리를 스치고 지나갔다. 오늘 만든 케이블 어댑터를 통해 키보드를 연결한 상태에서 전원을 올린다면? 키보드는 SMPS를 통해 즉시 전원을 공급받게 되니 라즈베리 파이가 부팅되는 동안 이미 ON된 상태가 될 것이다. 이때 잠시 전압이 출렁거린다 해도 라즈베리 파이의 부팅 과정에 영향을 크게 줄 것 같지는 않다. 부팅이 끝난 뒤에는 저전압에 대한 기록이 당연히 남지 않을 것이다. 실제로 실험을 해 보니 과연 그렇다. 성가신 저전압 경고 메시지를 보이지 않게 하는 것(눈 가리고 아웅?)이 최종적인 목표라면, 이렇게 해서 안 될 이유가 없다.

아마 특별한 일이 없다면 내 인생에서 더 이상 건반을 사는 일은 없을 것이라고 다짐해 보지만, 그것을 또 어찌 알겠는가? 예전에 쓰던 사무실에서 수선을 기다리고 있는 StudioLogic SL-990은 또 어떻게 할 것인가? 고치겠다고 분해를 해 놓은 뒤 10년 가까이 지나고 있으니 말이다(당시 작성한 글 링크).

Fluid Ardule의 개발 역사 및 오늘의 테스트(Yoshimi 즉흥 연주)를 간략하게 담은 영상을 만들었다.


2026년 4월 28일 업데이트

드디어 MIDI CC(Control Change)를 이용하여 프리셋을 편집하는 기능을 넣었다. 상업적인 모듈형 신시사이저에 한층 더 다가간 느낌이다. 포텐셔미터는 평소에는 볼륨 조절이지만, 정해진 버튼 하나를 길게 누르면 CC 값 변화용으로 전환된다. 바로 곁에 놓인 로터리 인코더와 사실상 중복되는 셈이지만, '한 바퀴를 돌려서 0~127 전체 범위를 커버할 수 있다'는 편리함은 인코더보다 훨씬 낫다. 지난 1년 동안 아두이노 DIY 작업을 하면서 인코더 신호를 다루기가 제법 까다로움을 알게 되었기 때문이다. 물리적 포텐셔미터(그러나 품질이 좋은)의 조작 편의성은 아무리 강조해도 지나치지 않다.

Sound Edit 창이 처음 선을 보였다.

물론 포텐셔미터를 CC 입력용으로 같이 사용할 때 주의할 점이 없는 것은 아니다. Vol = 64의 위치에서 CC 입력 모드로 전환한 뒤 127까지 회전한 다음 다시 볼륨 조절 모드로 돌아갔다고 가정해 보자. 기본적으로 포텐셔미터는 현재 회전 각도에서 정해진 값을 즉시 반환하게 되어 있다. 그렇다면 별안간 볼륨이 최대가 되는 부작용이 생긴다. 따라서 볼륨 조절 모드로 복귀한 다음에도 노브를 돌려서 직전에 맞춘 값 근처에 왔을 때 비로소 수치를 가져오게 만드는 이른바 soft takeover/pickup 기능을 넣어야 자연스럽다. 초보 개발자가 이런 기법을 어떻게 알겠는가? 전부 ChatGPT가 제안한 것이다.

파이썬 스크립트는 어제로서 5천 라인을 넘어섰다. 편집한 음색을 저장하고 이를 다시 불러오는 기능까지 넣는 것이 아마 단일 파일 프로젝트의 한계라고 생각한다. 여기까지 만들어 놓으면 쓸만한 물건을 만들었다고 자랑을 해도 부족함이 없을 것이다. 기왕이면 멋진 케이스를 가공하여 완성을 하면 더 좋을 것이다.

그 이상으로 기능을 추가한다면(예: combination/split 설정) 그때부터는 파일을 분할하는 리팩토링에 돌입해야 한다. 여름 이후에나 가능할 것 같다.

2026년 4월 23일 목요일

우주는 누구의 것인가? 유네스코 보고서가 던진 질문



KISTEP(한국과학기술기획평가원)에서 개최한 2026 기술영향평가 대상기술 추천회의에 작년에 이어 올해에도 참석하였다. 이는 과학기술기본법 제14조에 의한 것으로, 사회구성원이 참여한 기술영향평가(TA, Technology Assessment)를 통해 미래 신기술이 초래할 결과를 예측하여 사전 대응 방안을 마련하고자 함이다.

2003년부터 작년까지 총 26개 기술에 대한 기술영향평가가 진행되었다. 평가 주기가 매년으로 바뀐 것은 2010년이다. KISTEP이 자체 연구를 통해 도출한 평가 대상 기술 중 최종 3개 정도의 후보 기술을 선정하는 것이 이 위원회의 임무이다. 만약 내가 속한 분야의 기술이 후보에 올라가면, 평가회의 이후에도 후속 작업에 참여할 수도 있다고 한다. 최종 후보 기술의 확정은 과기정통부가 담당한다. 하반기에는 이에 대해서 전문가 분석과 시민 포럼, 정책협의체 등을 거쳐 최종 결과를 마련한 뒤 12월에 국가과학기술자문회의에 보고하는 것으로 그 해의 임무가 끝난다.

최초의 '재료'는 50대 국가전략기술이다. 사전 분석 과정에서는 한국언론진흥재단의 빅카인즈(BIGKinds) 뉴스 빅데이터 시스템에서 이에 대한 관련 기사의 전처리된 키워드를 수집하여 활용하였다고 한다. 기술 준비도 추정이나 우려(4개 유형 불확실성, 즉 무지, 모호함(갈등), 불확실성, 위험) 관련 키워드를 수집하여 분석하는 과정은 '아, 그러한 것도 있구나'하고 설명을 듣고 겨우 이해할 정도였다. 전문가적 식견이 필요한 일 같았다.

지난 2년 동안 선정된 대상 기술은 안전·신뢰AI(2024), 그리고 AI 에이전트(2025)였다. 올해는 또 다른 종류의 'AI'가 사람들의 입에 오르내리고 있으며, 당연히 11개 후보 기술 중 이름을 달리하여 몇 가지로 올라와 있었다. 

이런 회의에 참석하여 얻는 유익함이란 바로 과학과 기술, 그리고 인문을 망라하는 다양한 분야의 전문가들과 아무런 사심 없이 이야기를 할 수 있다는 것이다. 

오늘 쓰고자 하는 글은 11개 후보 기술 중 포함되어 있었던 우주와 관련한 것이다. 발사체 기술이 계속 발전하면서 과거에는 상상도 할 수 없는 싼 가격에, 그리고 전 세계에서 수시로 쏘아 올리는 로켓 덕분에 우주(space)로 무엇인가를 내 보낼 수 있게 되자 인간이 하는 모든 활동을 우주에서 해 보려는 시도가 이어지고 있다고 한다. 이는 항공우주연구원 정대원 박사님의 의견이었다.

여기에서 잠깐, 우리가 '우주'라고 하나의 낱말로 사용하는 그 개념을 보다 정확하게 세분해 보자. 최근에 읽었던 책에서도 이러한 개념 쪼개기가 있었다. 다음의 설명은 과기정통부 블로그(링크)에서 가지고 왔다.

  • Space: 지구 대기권 밖의 물리적 빈 공간(탐사 대상)
  • Universe: 별, 은하, 물질을 포함한 과학적 의미의 전체 우주
  • Cosmos: 질서와 조화를 갖춘 철학적·인문학적 우주 

단순한 과학적 탐사를 넘어서 통신, 국방, 지구 관측(감시?) 등 space에서 할 수 있는 활동의 분야는 점점 넓어지고 있다. 아주 최근 사람을 싣고 달 비행을 마치고 지구로 귀환한 아르테미스 2호 역시 장기적으로 달을 탐사 대상이 아니라 잠재적 자원 활용의 대상으로 바라보는 흐름과 무관하지 않아 보인다.

한양대학교 철학과 이상욱 교수님은 유네스코 세계과학기술윤리위원회(COMEST, World Commission on the Ethics of Scientific Knowledge and Technology) 위원으로 활동한 바 있는데, 작년 말에 이 위원회에서 우주 탐사(space exploration)에 대한 윤리적 쟁점에 관한 보고서를 발간하였다고 한다. 

UNESCO라니? 최근 읽은 책《생각의 진화》에서 소개한 줄리언 헉슬리가 바로 UNESCO의 초대 사무총장이었다(독서 기록 링크). 이 책에서는 그가 1946년 유네스코의 초대 사무총장으로 지명된 후, 조직과 비전을 구상하고 실제로 2년에 불과한 임기 동안 무척 많은 고뇌를 겪은 것으로 알려져 있다. 갑작스런 사무총장으로 임명되고 나서 그는 약 2주간 휴가를 내고 틀어박혀서 <유네스코: 그 목적과 철학>을 썼는데, 그 과정이 바로《생각의 진화》에 잘 표현되어 있다. 하지만 이 문서는 결국 공식 문서로는 채택되지 않았다고 한다.

흥미로운 일이다. 나하고는 아무런 인연이 없을 것 같았던 유네스코, 그것도 독서를 통해서 겨우 알게 된 이 국제기구의 설립 스토리에 이제 막 흥미를 갖게 된 시점에 실제 그 위원회서 활동했던  전 보고관(Former Rapporteur)을 바로 곁에서 만나게 되다니.

몹시 궁금하여 원문을 찾아서 이 교수님에게 이 자료가 맞는지 확인받은 뒤, ChatGPT를 이용하여 요약을 해 보았다. 잠깐 조사를 해 보았으나 이 보고서는 국내 언론을 통해 거의 소개되지 않은 것 같았다. 이러한 담론 속에서 '우주 윤리'는 거의 논의되지. 흔히 우주라고 하면 일론 머스크의 다소 기행에 가까운 행보, 그가 주도하는 스페이스X나 스타링크, 그리고 주가에 미치는 기대감 정도가 커뮤니티나 언론을 통해 소비되고 있지 않은가?

우주를 '개발'하는데 윤리라니? 그러나 우주에 대하여 개발이나 활용이라는 낱말을 함부로 쓰는 것은 인간의 기술력을 너무 높게 평가하는 것이다. 아직까지는 보다 겸손하고 조심스럽게 '탐사'라는 말을 쓰는 것이 더 낫다고 생각한다. 유네스코 보고서의 제목에서 드러나듯이.

제목: Report of the World Commission on the Ethics of Scientific Knowledge and Technology (COMEST) on the ethics of space exploration and utilisation (유네스코 세계과학기술윤리위원회의 우주 탐사 및 활용의 윤리에 관한 보고서), 2025년 9월 18일. 원문 링크.

유네스코 산하 세계과학기술윤리위원회(COMEST)가 2025년에 발표한 이 보고서는 우주 탐사와 활용이 본격적인 상업화 및 국제 경쟁 단계로 진입한 상황에서, 이를 둘러싼 윤리적 쟁점을 종합적으로 분석하고 향후 글로벌 거버넌스 방향을 제시하는 데 목적을 둔다.

보고서는 먼저 인류가 오랜 역사 속에서 우주를 관찰하고 이해해 온 문화적·과학적 맥락을 강조한다. 별과 행성에 대한 관측은 단순한 과학적 활동을 넘어 문화와 세계관 형성에 깊이 관여해 왔으며, 현대의 우주 탐사 역시 이러한 인간 경험의 연장선에 있다. 그러나 오늘날 우주는 더 이상 순수한 탐사의 대상이 아니라, 자원 개발, 군사적 활용, 상업적 경쟁이 결합된 복합적 공간으로 변화하고 있다.

특히 보고서는 “트랜스헤미스페릭(transhemispheric)” 관점을 제안한다. 이는 서구 중심의 과학적 시각뿐 아니라 다양한 문화권과 원주민 지식 체계를 포괄하여 우주를 이해해야 한다는 주장이다. 우주를 단순히 ‘정복’의 대상으로 보는 것이 아니라, 공동의 유산으로 인식하고 존중해야 한다는 윤리적 전환이 요구된다는 것이다.

현재 우주 활동은 달, 화성, 소행성, 우주관광 등 다양한 영역으로 확대되고 있다. 달은 자원 활용과 기지 건설의 핵심 거점으로 주목받고 있으며, 화성은 장기적 거주 가능성 연구의 중심이다. 또한 근지구천체(NEO)는 행성 방어와 자원 채굴 측면에서 중요한 대상이며, 민간 기업 중심의 우주 관광 산업도 빠르게 성장하고 있다. 이러한 발전은 기술 혁신과 경제적 기회를 제공하지만, 동시에 환경 파괴, 우주 쓰레기 증가, 생물학적 오염, 군사적 긴장 등 다양한 위험을 동반한다.

윤리적 쟁점은 크게 몇 가지로 정리된다. 첫째, 형평성과 접근성 문제이다. 현재 우주 활동은 일부 국가와 기업에 의해 주도되고 있으며, 개발도상국이나 비우주 국가의 참여 기회는 제한적이다. 둘째, 환경 보호 문제이다. 우주는 더 이상 무한한 공간이 아니며, 인공위성 증가와 우주 쓰레기 문제는 장기적 지속가능성을 위협한다. 셋째, 군사화와 이중용도 기술 문제이다. 우주 기술은 민간과 군사 목적이 혼재되어 있으며, 이는 국제적 긴장을 심화시킬 수 있다. 넷째, 세대 간 책임 문제이다. 현재의 우주 개발이 미래 세대의 권리를 침해하지 않도록 신중한 접근이 필요하다.

보고서는 우주를 “글로벌 커먼즈(global commons)”로 볼 것인지, 아니면 국가 또는 민간의 소유 대상으로 볼 것인지에 대한 논쟁도 다룬다. 일부 국가는 우주 자원의 소유권을 인정하는 법을 제정하고 있으나, 이는 국제 협력과 형평성 측면에서 갈등을 야기할 수 있다. 따라서 공동 관리와 공정한 이익 분배를 위한 국제 규범이 필요하다고 강조한다.

현행 국제법 체계, 특히 1967년 우주조약(Outer Space Treaty)은 기본적인 원칙을 제공하지만, 상업화와 기술 발전 속도를 따라가지 못하는 한계가 있다. 이에 따라 보고서는 보다 포괄적이고 강제력 있는 글로벌 거버넌스 체계 구축을 제안한다. 유엔 및 관련 국제기구의 역할을 강화하고, 다자 협력을 통해 규범을 발전시켜야 한다는 것이다.

또한 보고서는 “우주 윤리 스케일(space ethics scale)”이라는 개념을 제안하여, 다양한 우주 활동의 윤리적 영향과 위험을 평가할 수 있는 기준을 마련하려 한다. 이는 정책 결정자와 과학자, 산업계가 공통의 기준 아래에서 의사결정을 할 수 있도록 돕는 도구로 활용될 수 있다.

최종적으로 보고서는 다음과 같은 방향을 제시한다. 첫째, 국제 협력과 투명성을 강화하여 신뢰를 구축할 것. 둘째, 우주 활동의 환경적·사회적 영향을 체계적으로 평가할 것. 셋째, 공정한 자원 분배와 참여 기회를 보장할 것. 넷째, AI 및 자율 시스템 등 신기술의 윤리적 기준을 마련할 것. 다섯째, 장기적으로 지속가능한 우주 이용을 위한 단계적 로드맵을 수립할 것.

결론적으로 이 보고서는 우주 탐사가 단순한 기술적 도전이 아니라, 인류 전체의 가치와 미래를 좌우하는 윤리적 과제임을 강조한다. 우주를 공동의 유산으로 인식하고 책임 있는 방식으로 활용할 때, 비로소 우주 시대의 발전이 인류 전체의 이익으로 이어질 수 있음을 역설한다.

우주 활동이 정말 가시적인 성과로 나타나는 지금, 올바른 접근에 대한 윤리적 기준 수립과 더불어 인류 공동체의 공정하고 지속 가능한 참여가 지금부터 이루어져야 한다고 본다.

지난주에 읽었던 지웅배 교수의《천문학자의 쓸모없음에 관하여》도 생각이 난다. NASA의 자료에서 '창백한 푸른 점'에 관한 사진과 태양계 가족 사진을 찾아 보자(링크). 이보다 더 비장한 컴퓨터의 셧다운이 또 있었을까. 이렇게 작은 세계에서 우리는 자원과 해협을 둘러싸고, 실익도 명분도 없는 치열한 겨루기를 하고 있으니 말이다. 누가 죽어나가든, 내 주식만 오르면 그만인가.