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 교보문고

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

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

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

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

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