2026년 5월 27일 수요일

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

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


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

상판으로 사용할 아크릴판도 오늘 도착하였다. 가공을 의뢰한 전후판만 배송되면, 수일 내로 완성품을 만들게 될 것이다. 

 

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에 따라
누구나 자유롭게 복제, 수정, 배포, 활용할 수 있으며, 출처 표시도 필요하지 않습니다.

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