2026년 3월 3일 화요일

APS StepSeq 입력 도구의 다변화



Nano Ardule 드럼 패턴학 생태계를 이루고 있는 APS는 기본에 충실한 '스텝 시퀀서' 기능을 내장하고 있다. 16분음표 단위로 세분화된 스텝에 드럼킷을 구성하는 각 악기의 연주 정보를 입력하거나 편집하고, 메인 화면에서는 이를 연결하여 곡 단위의 arrangement 파일(패턴을 이어 붙인 곡 구성표)을 만드는 역할을 한다. 이 생태계를 구성하는 모든 파일 포맷은 ChatGPT와 의논하면서 정의해 나갔다.

스텝 시퀀서, 그러나 실시간에 대한 욕심

스텝 시퀀서라고는 하지만 실시간 입력에 대한 욕심을 충족하지 말라는 법은 없다. 킥 드럼 찍고, 비트마다 하이햇 찍고, 스네어 드럼 소리 찍어 올리고... 이 과정을 실시간으로 오버더빙하듯이 누적하여 입력하면 얼마나 편리하겠는가? 이러한 욕심은 NanoArdule 깃허브 프로젝트에서 메인과 독립한 별도의 브랜치(refactor/stepseq-v3.0a)를 만드는 것으로 이어졌고 마침내 필요한 기능을 모두 구현하게 되었다. 최종 테스트를 거친 뒤 이를 다시 메인 브랜치와 병합하는 일이 남았다.

현재 HEAD는 어디를 가리키는가?

다음은 사무실 PC에서 바라본 각 브랜치의 모습이다. HEAD가 어느 브랜치(또는 커밋)를 가리키는지 확인해 보자. 보다 기술적으로 말하자면, '현재 체크아웃된 브랜치를 확인해 보자'가 되겠다.

PS E:\Projects\NanoArdule\APS> git branch
  main
* refactor/stepseq-v3.0a
PS E:\Projects\NanoArdule\APS> git branch -a
  main
* refactor/stepseq-v3.0a
  remotes/origin/HEAD -> origin/main
  remotes/origin/main
  remotes/origin/refactor/stepseq-v3.0a
PS E:\Projects\NanoArdule\APS> git branch -vv
  main                   5a38227 [origin/main] docs: add Windows 11 KB5077241 compatibility notice
* refactor/stepseq-v3.0a 83625bd [origin/refactor/stepseq-v3.0a] StepSeq: disable REC arm when using GS Wavetable or no MIDI OUT
    

리얼타임 입력 도구

리얼타임 기반의 입력 도구는 컴퓨터 키보드(4×4 keyboard grid)MIDI 키보드 컨트롤러의 두 가지를 선택하여 쓸 수 있다. 전자의 경우 자판의 왼쪽 16개 키를 이용하며, 이 때에는 벨로시티를 조정하지는 못한다. 후자의 경우는 AKAI MPK Mini MKII의 4×2 패드를 사용한다. 사실 어떤 MIDI 키보드 컨트롤러를 써도 상관은 없다. AKAI 미니 키보드에서는 패드 설정을 바꾸어서 원하는 악기 소리가 나도록 해 두었다. 드럼의 각 악기 선택과 패드 배열에 대한 상세한 정보는 별도의 스펙 문서로 정리하였다. PC 키보드 일부를 4×4 패드처럼 쓰는 방식을 나는 4×4 keyboard grid라고 부르기로 했다. 아래 그림에서 알파벳 두 글자로 표기된 드럼계열 악기명 약어의 설명과 실제 GM 드럼킷에서 할당하는 노트번호는 위에서 언급한 스펙문서에 상세히 설명되어 있다.



Microsoft GS Wavetable Synth의 한계

문제는 latency다. PC에 내장된 Microsoft GS Wavetable Synth가 소리를 내는 상태에서는 반응 속도가 느려서 리얼타임 입력 도구를 사용하기 곤란하다. 따라서 MIDI OUT이 외부 음원 모듈로 연결되지 않았다면 Record가 아예 되지 않게 만들었다. 이러한 상태에서 'R'을 누르면 'REC disabled: Microsoft GS Wavetable is high-latency'라는 경고문이 나온다. 녹음은 타이밍 정확도가 중요하므로 차단하고, 미리듣기(Preview)는 학습/확인 목적이므로 허용한 것이다. 그러나 외부 MIDI 음원이 없더라도 녹음 모드가 아니라면 키보드 또는 패드를 누를 때 Microsoft GS Wavetable Synth를 통해서 소리는 난다('Preview').

앞으로 나아갈 방향

ASIO를 사용하는 DAW를 대체하기 위하여 APS/StepSeq을 만든 것은 아니니, 이러한 latency 문제를 적극적으로 해결할 계획은 아직까지는 없다. APS는 완성형 드럼 머신과 경쟁하려는 도구가 아니다. 그러나 입력 방식의 실험이라는 점에서 충분히 의미 있는 시도가 될 것이다.

2026년 3월 1일 일요일

운영체제가 나의 TUI를 부수던 날

오늘은 Nano Ardule의 APS 개발에서 이정표 하나를 세울 수 있는 날이었다. StepSeq 코드를 개선하여 '루퍼'와 유사하게 드럼 연주 정보를 입력하도록 만들었기 때문이다. 16 x 12로 펼쳐진 그리드 위에서 커서를 화살표로 이동하여 엔터키를 눌러 노트를 입력하는 스텝 시퀀서 본연의 기능은 이미 잘 다져진 상태였다. 여기에 외부 장비인 AKAI MPK MINI MkII를 연결하여 패드를 터치하면 드럼 패턴을 실시간으로 자연스럽게 녹음할 수 있다. 메트로놈 소리를 들으면서 베이스 드럼을 먼저 찍고, 다음으로 스네어 드럼, 그 다음에는 하이햇... 스크립트 실행 전 MIDI 기기 연결 상태를 점검하는 환경변수 설정을 먼저 해야 했던 다소 비효율적인 최근의 변경도 훨씬 안전하고 단순한 방식으로 고쳐 놓았다.

StepSeq의 기능을 이렇게 맞추어 나가기 위해 메인에서 독립한 별도의 브랜치(refactor/stepseq-v3.0a)까지 만들어서 몇 시간을 투자한 끝에 원하는 목표까지 달성을 하였다. 마침 Windows update가 있다는 알림이 있어서 설치를 지시해 놓고 아내와 함께 잠시 장을 보고 돌아왔는데...

APS에서 화면이 하나도 나오지 않는 것이다. 말 그대로 까만 터미널 창 그 자체의 '조용한 실패'였다. 챗GPT와 질문을 주고 받으면서 별의별 노력을 다 해 보았지만, TUI(text user interface)를 구현하기 위한 핵심인  ncurses 라이브러리의 작동이 Windows update와 더불어 문제를 일으킨 것 같다는 것이 최종 결론이었다.


오늘 설치한 Windows 11 버전 25H2 및 24H2(KB5077241)에 대한 비보안 업데이트는 KB5077241이다. 원인을 확실하게 알기 위해서 이 업데이트를 제거한 뒤 재설치해 보았다. [설정 > Windows 업데이트 > 업데이트 제거] 순서로 작업하면 된다.

KB5077241은 프리뷰(선택적) 업데이트였다. 설치하지 않아도 Patch Tuesday에 배포되어 자동으로 설치되는 다음 정식 누적 업데이트에 포함될 것이고, 안정성이 중요한 개발 환경에서는 보통 건너뛰는 것이 안전하다고 한다.

그러면 다음번 정식 업데이트가 KB5077241를 그대로 포함할 것이니 또 TUI와 관련한 문제가 재발하지 않겠는가? 꼭 그렇지는 않다. 문제 있는 부분은 수정되거나 제외될 수 있기 때문이다. 프리뷰 업데이트를 기계적으로 설치하는 버릇을 고쳐야 되겠다.

KB5077241를 삭제하였더니 업데이트를 하라는 알림이 트레이에서 다시 뜨기 시작하였다. '최신 업데이트가 제공되는 즉시 받기'를 꺼 두기로 하였다.

업데이트를 제거한 결과는? 언제 그랬느냐는 듯이 멀쩡한 APS 화면으로 돌아왔다. 어째서 이런 일이 벌어진단 말인가... 챗GPT에 의하면, Windows 업데이트 이후 curses/ncurses 계열이 깨지는 일은 꽤 자주 보고된다고 한다. 개발이 쉬울 것이라 생각해서 TUI를 선택하였는데, OS 변화 영향이나 Windows 호환과 관련해서는 nurses TUI보다 GUI가 더 낫다니 이는 미처 예상하지 못했던 일이다.

장기적으로는 curses 의존도를 줄여 나가는 것이 좋을 것이다. 앞으로 개발에 약간의 수고가 더 들더라도 GUI로 갈아타는 것을 오늘 처음으로 고민하기 시작하였다. 간단한 조사를 통해서 다음과 같이 결론을 내려 보았다.

🚩 PySimpleGUI로 전체 GUI 스켈레톤을 먼저 만들고,
StepSeq가 답답하면 그 부분만 Dear PyGui 스타일로 개선

refactor/stepseq-v3.0a 브랜치의 테스트를 완벽히 마친 뒤 main과 병합한 다음, GUI로 넘어가기 위한 탐색을 시작하련다. 만약 오늘의 작은 '사고'가 아니었더라면, GUI에 대한 호기심은 일절 갖지 않았을 것이다. 취미 코딩의 종착역이 어디까지 가게 될지 모두지 알 수가 없다.

오늘의 결론은 이러하다. 코드는 멀쩡했다. 운영체제가 바뀌었을 뿐이다. 이것이 새로운 시도로 이어지는 계기가 될 수도 있겠다.


2026년 2월 27일 금요일

갈라질 결심(Creating a Git Branch)

갈라진다고 하여 사람이나 조직과 인연을 끊거나 헤어진다는 뜻은 아니고, Git에서 새로운 기능을 넣기 위해 처음으로 메인에서 독립하여 별도의 브랜치를 만들겠다는 뜻이다.


Nano Ardule 드럼 패턴학 생태계에서 PC쪽 패턴 생성 및 편집기, 즉 APS(Ardule Pattern Studio)는 기본적으로 키보드를 두드려서 입력을 하는 데 충실하게 만들었다. 실시간 연주를 받아들이는 것이 아니라 StepSeq, 즉 16분음표 단위의 스텝으로 커서을 이동하여 선정된 악기의 타격 신호를 기록한다. 2차원 그리드 위에 체크 표시를 한다고 생각하면 간단하다. 어제도 코드 효율을 높이기 위한 약간의 수정을 하여 commit를 한 상태이다.

이번 단계의 목표는 AKAI MPK Mini MKII를 입력 장치로 쓰게 만드는 것이다. 그러면 컨트롤러의 4x2 패드를 이용하여 드럼 패턴을 입력할 수 있기 때문이다. 이미 패드를 두드려서 스텝 단위 입력을 할 수 있게 만들어 두었으나, 욕심을 좀 더 부려서 마치 루퍼처럼 오버더빙 형식의 실시간 입력을 가능하게 만들고 싶다.

그러려면 상당한 수준의 코드 수정이 필요하기에 아예 이번 기회에 branch를 새롭게 생성해 보기로 하였다. 브랜치 생성 요령은 별도의 문서('Safe Git Branching Guide for StepSeq Refactoring')로 정리해 두었다. 어제까지 완성하여 안정화된 기능(키보드를 통한 스텝 입력)은 일절 건드리지 않아야 한다.

그리고 한가지 더. GUI나 DAW로 관심이 이동하면 절대로 안 된다! 그건 나의 본분을 잊는 행위이다. 목표를 명확히 하고 개발의 시행착오를 줄이기 위하여 이번 단계의 설계 개념은 문서로 충분히 작성해 두었다. 

레코딩('녹음'이라고 표현하면 오디오 신호 자체의 기록이라는 느낌이 강하게 든다)을 자체 개발 파이썬 스크립트로 소박하게 구현해 보면서 몇 가지 중요한 개념을 공부하게 되어 좋은 기회라고 생각한다.  녹음과 재생에 대한 각종 설정 또는 제어 상태는 다음과 같은 계층 구조로 이해하면 좋다.

  1. Transport layer: 플레이헤드 진행 및 루프 범위 제어
  2. Record arm layer: 입력이 패턴을 수정할 수 있는지 결정
  3. Write policy (overwrite or overdub): 기존 데이터와 새 입력의 병합 방식 정의

만약 이 브랜치에서 성공적으로 개발이 완료된다면, APS의 StepSeq은 아주 쓸모 있는 장난감이 될 것이다. 

그리고... 업무 스트레스를 달리기로 푼 어제의 기록. 기온이 많이 올라서 야간 달리기를 하기에 아주 좋았다. 479kcal를 태웠으니 라면 한 그릇의 열량을 소모한 정도?

만족스럽지 못한 2월의 달리기 기록. 일본 여행과 날씨 탓이 크다. 어제는 오랜만에 7km를 넘게 달렸다.


2026년 2월 26일 목요일

데이터 분야 'AI 준비도'(AI readiness)의 압박

지금은 인공지능 대전환기이자 대혼란기이다. '대혼란기'라고 한 이유는, AI와 관련하여 '몇 시까지 자료 만들어 주세요(보통 2~3시간 이내)'라는 급박한 요청이 부쩍 늘어났기 때문이다. 자발적인 것이든 외부 요인에 의해 어쩔 수 없는 것이든 실제로 AI에 적응하려면 조직, 나아가 개인의 일하는 방식이나 사고 방식에 이르기까지 해체에 가까운 변혁이 필요하다. 좀 천박하게 말한다면 매일 'AI 대환장 파티'가 벌어지고 있다.



IBM의 웹사이트에서  Thriving through AI disruption이라는 글을 읽어 보았다. AI 준비도(AI readiness)의 5대 축은 다음과 같이 묘사된다.

  1. Strategy & business alignment
  2. Data foundation
  3. Technology & architecture
  4. Talent, skills & culture
  5. Operating model & governance

내가 일하고 있는 조직, 특히 바이오와 같은 high-stakes 영역에서는 2번 data foundation이 가장 중요하다. 왜냐하면 우리는 바이오 연구 데이터의 수집, 관리 및 활용 기반을 제공하는 곳이기 때문이다. 이러한 체제를 갖추어서 실제로 부끄럽지 않은 수준으로 돌아가게 된 지는 그렇게 오래 되지 않았다.

논문에 쓰인 연구 데이터를 과학 발전을 위해 공유하는 아름다운 관행은 인공지능이 유행을 타기 훨씬 전부터 널리 퍼져 있었다. 이를 위해서 데이터 리포지토리가 매우 중요한 역할을 해 왔다. 현재의 문제는 리포지토리에 모인 데이터를 인공지능 학습용으로 그대로 가져다 쓸 수 있느냐에 있다. 

완벽한 데이터란 실제로 그렇게 많이 존재하지 않는다. 그러나 우리는 다음과 같은 말을 많이 듣는다.

'쓸 만한 데이터가 없다'
'AI 학습이 가능한 형태로 가공되어 있지 않다' 

수요자 입장에서는 충분히 나올 수 있는 이야기이다. 하지만 이것이 'AI 투입을 위해 모든 자원이 갖추어져야 한다'라는 입장으로 변질되어 권력의 틀을 쓰면 모두가 힘들어진다.

우리가 늘 준거집단으로 삼는 미국에서는 최근 Genesis Mission의 출범을 통해 AI 총동원 기조가 강화되고 있다. 데이터와 (인적·컴퓨팅)자원을 AI에 총동원해야 한다는 주장은 무한 경쟁 시대의 국가적 생존이나 경제·안보 등의 키워드를 등에 업으면 그 자체가 '권력'이 된다. 특히 더 나은 모델을 늘 벤치마킹해야 한다는 압박에 시달리는 우리나라에서는 국외의 사례가 정책 정당성의 근거로 과도하게 사용될 위험이 있다.

  • 선진국 사례가 곧 '정당성'이 아니다.
  • 국가안보 또는 경쟁 프레임은 안전과 권리에 대한 논의를 약화시킨다.
  • AI 에이전트/파운데이션 모델은 검증 비용을 없애지 않는다.

나에게 본업이 아닌 취미 활용 영역에서 AI란 매우 흥미롭고 효율을 높여주는 도구이지 동반자였다. AI가 제시한 전자회로와 코드는 반드시 나의 실증을 거쳤고, 그러한 최종 마무리 과정에는 결코 적지 않는 노력이 들었다. 확인되지 않은 AI 활용 결과물은 개인 차원의 재미 추구에는 문제가 없다. 그러나 그것이 정책으로 번져 나가면 그 파급효과는 너무나 크다. 가뜩이나 쏠림이 심한 우리나라 사회에서 역적으로 몰리기는 너무나 쉬운 일이니까.

AI가 애써 고민하고 결론을 내리는 인간의 영역을 완전히 대체하는 방향까지 나아가는 것은 경계한다.

다음과 같은 글에도 관심을 가져 보자.

데이터센터 모라토리엄 - 경향신문 에디터의 창, 2월 26일.

'AI 데이터센터 특별법처럼 이익은 사유화하고 비용은 공공이 지게 하려는 시도에 제동을 걸어야 한다.'

2026년 2월 25일 수요일

포커스 그룹 인터뷰(FGI)의 그늘: 우리가 놓치기 쉬운 부작용

A lot of times, people don't know what they want until you show it to them. - 스티브 잡스, Bloomberg, May 1998.

It's really hard to design products by focus group. A lot of times, people don't know what they want until you show it to them. - 스티브 잡스, Forbes, Oct 2011.

포커스 그룹 인터뷰(Focus Group Interview, FGI)는 정책 설계와 서비스 기획에서 널리 활용되는 질적 연구 방법입니다. 소수의 참여자를 모아 특정 주제에 대해 자유롭게 토론하게 함으로써, 설문조사로는 포착하기 어려운 맥락과 인식을 드러내는 데 강점이 있습니다.

그러나 최근 여러 현장에서 FGI 결과가 과도하게 일반화되거나 정책 판단의 근거처럼 사용되는 사례를 보며, 이 방법론이 가진 구조적 한계를 다시 짚어볼 필요성을 느낍니다. FGI는 유용한 도구이지만, 잘못 쓰이면 오히려 의사결정을 왜곡할 수 있습니다.


1. 작은 표본이 만드는 큰 착시

FGI의 가장 근본적인 한계는 표본 규모입니다. 일반적으로 한 그룹은 6~10명 수준에 불과합니다. 이는 심층 의견 탐색에는 적절할 수 있지만, 그 자체로 어떤 집단의 ‘대표 의견’을 말해 주지는 못합니다.

문제는 이 결과가 때때로 다음과 같이 해석된다는 점입니다.

  • “현장에서는 이렇게 생각한다”
  • “사용자들은 이것을 원한다”
  • “전문가 의견이 모였다”

이러한 표현은 FGI의 본래 용도를 넘어서는 일반화입니다. 소수의 목소리가 전체의 경향처럼 포장될 때, 정책과 서비스는 잘못된 방향으로 흘러갈 위험이 있습니다.


2. 그룹 다이내믹이 만들어내는 편향

FGI는 ‘집단 토론’이라는 형식 자체에서 여러 편향을 내포합니다.

  • 목소리 큰 참여자의 의견이 토론을 지배
  • 분위기에 따른 동조 압력(groupthink)
  • 사회적으로 바람직한 답변으로의 수렴
  • 진행자의 질문 방식에 따른 유도 효과

특히 기술이나 정책처럼 정답이 불분명한 주제에서는, 토론 분위기 하나로 의견 분포가 크게 달라질 수 있습니다. 이 경우 우리가 관찰하는 것은 ‘개별 참여자의 진짜 생각’이 아니라, 토론 상황에서 형성된 집단 산물일 가능성이 큽니다.


3. 탐색 도구가 결정 도구로 오용되는 문제

FGI의 본래 목적은 결론을 확정하는 것이 아니라, 다음과 같은 탐색적 역할입니다.

  • 가설 생성
  • 문제 맥락 이해
  • 사용자 언어와 인식 파악
  • 추가 연구 설계의 단서 확보

그럼에도 불구하고 실무에서는 FGI 결과가 정책 방향을 정당화하는 근거처럼 사용되는 경우가 적지 않습니다. 질적 탐색 도구가 정량적 근거를 대체하는 순간, 의사결정의 기반은 급격히 취약해집니다.


4. ‘기대 담론’이 증폭되기 쉬운 구조

최근 AI, 데이터, 디지털 전환과 같은 분야에서는 긍정적 기대가 사회 전반에 강하게 형성되어 있습니다. 이런 환경에서 진행되는 FGI는 자연스럽게 다음과 같은 경향을 보이기 쉽습니다.

  • 기술 낙관론의 과대표출
  • 위험 요소의 과소 언급
  • 실행 비용과 현실 제약의 축소

참여자들은 종종 “바람직한 미래”를 말하지, “실제로 작동 가능한 현실”을 말하지 않습니다. 이 차이를 구분하지 못하면, 정책은 구호는 크고 실행은 어려운 방향으로 흘러갈 수 있습니다.


5. 책임의 비대칭성

FGI에서 나온 아이디어나 방향이 실제 정책이나 시스템으로 구현될 경우, 흥미로운 비대칭이 발생합니다.

  • 의견 제시는 소수 참여자가 수행
  • 실행과 책임은 기관과 현장이 부담

특히 데이터 거버넌스나 AI 활용처럼 법적·윤리적 부담이 큰 영역에서는, 초기 아이디어의 파급력을 과소평가하기 쉽습니다. 즉흥적 제안 하나가 실제 운영 단계에서 상당한 비용과 위험을 동반할 수 있습니다.


균형 잡힌 활용을 위하여

FGI는 여전히 가치 있는 도구입니다. 사용자 맥락을 이해하고, 문제의 언어를 포착하며, 새로운 가설을 만드는 데 있어 강력한 방법임은 분명합니다.

다만 다음 원칙은 반드시 지켜질 필요가 있습니다.

  • FGI 결과를 일반화하지 말 것
  • 정량 자료와 교차 검증할 것
  • 정책 결정의 단독 근거로 사용하지 말 것
  • 참여자 구성과 토론 맥락을 투명하게 공개할 것

FGI는 방향을 비추는 손전등이지, 결론을 확정하는 판결문이 아닙니다. 이 기본을 잊지 않을 때, 우리는 이 유용한 도구를 과신도 과소평가도 하지 않는 균형 잡힌 위치에서 활용할 수 있을 것입니다.

이 글은 현장 경험을 바탕으로 FGI 방법론의 한계를 성찰하기 위해 작성되었습니다.


이 글은 정해영의 아이디어를 바탕으로 AI(ChatGPT)의 도움을 받아 작성되었습니다. CC0 1.0으로 자유 이용 가능하며, 정확성 및 법적 책임은 보장하지 않습니다. This text was written with AI (ChatGPT) assistance based on the author’s ideas. Released under CC0 1.0. No guarantee of accuracy is provided, and no liability is assumed.

바꿀 수 있는 것과 없는 것 - 고장난 전원 스위치 하나가 남긴 질문

43 오극관 싱글 앰프의 망가진 전원 스위치

내 사무실에는 내가 직접 만든 오디오 앰프가 몇 대 있다. 그중 진공관으로 자작한 것이 두 대쯤 되는데, 사무실에 처음 찾아온 사람과 가볍게 이야기를 풀어나갈 때 꽤 좋은 소재가 되곤 했다. 나의 오디오 앰프 자작 기록은 공식 웹사이트의 위키 문서에 따로 정리해 두었다.

그 가운데 하나가 1940년대에 만들어진 항아리 형태의 43 오극관을 사용한 소출력 앰프였다(자작 기록). 상판은 CAD를 이용해 설계한 뒤 도면을 가공업체에 보내서 만들었고, 바닥의 나무틀도 손수 도색하여 나름대로 정성을 들여 만든 기기였다. 진광관 자체가 고전적인 항아리 모습이라 개인적으로도 꽤 애착을 갖고 있던 진공관 앰프였다. 처음에는 빵 굽는 트레이 위에 프로타입을 만드는 것으로 시작하였었다(링크). 프로토타입 제작 당시에는 R-core에 직접 감은 출력트랜스포머를 여기에 처음 연결해서 사용했었다.

그런데 어제 전원 스위치가 들어오지 않는 것을 발견했다. 조명이 들어오는 시소형 전원 스위치였는데, 아무리 움직여도 ON 포지션에 고정이 되지 않았고 불도 들어오지 않았다. 수동 부품의 내구성에 대해 나름 높은 기준을 갖고 있던 나로서는 꽤 실망스러운 상황이었다. 일단 인터M R150 PLUS '레퍼런스' 앰프로 바꾸어 놓았다. 이는 대출력 앰프라서 사무실 책상 위에서 쓰기에는 적합한 수준은 아니다.

R150 PLUS 파워앰프. 책상 위에 놓고 잔잔하게 음악을 듣기에는 너무 출력이 커서 레벨 조정용으로 베링거 믹서를 달아 놓았다.

참고로 말하자면 내가 블로그에 쓴 글 중에서 램프형 스위치의 올바른 결선법(2016.5.29.)은 항상 가장 많은 조회수를 보이고 있다.

물론 전원 스위치 수리는 어려운 일이 아니다. 상판 타공 사이즈에 맞는 부속을 다시 구해 납땜만 하면 되는 문제이기 떄문이다. 전기/전자제품이란 당연히 수명이라는 것이 있다. 특히 자작 기기인 경우 스위치나 소켓, 커넥터와 같은 수동/기구 부품은 값이 좀 비싸더라도 좋은 것을 써야 후회가 없는데 제작 당시에는 좋은 결심을 하지 못하는 것이 늘 문제이다.

이 일 자체는 매우 사소한 일이었다. 부품을 구해서 바꾸어 끼고 납땜을 새로 하면 해결될 문제였다.

하지만 최근 2년 동안 내가 직장에서 맞닥뜨린 몇 가지 일들은 그렇게 간단하지 않았다.

어디선가 읽은 글이 떠올랐다. 어떤 이는 자신의 성공 비결이 아무리 노력해도 바꿀 수 있는 것과 바꿀 수 없는 것을 빨리 구별하는 데 있다고 말했다. 즉, 바꿀 수 없는 일을 개선하려고 쓸데없는 에너지를 낭비하지 말자는 뜻이었다.

물론 아주 작고 조금만 조절하면 될 일까지도 바꿀 수 없다고 성급히 판단해버리는 것은, 자신의 능력과 가능성을 스스로 잠재워버리는 게으른 핑계가 될 수도 있겠다고 생각했다.

그럼에도 불구하고 아무리 노력해도 바꿀 수 없는 것들이 우리 주변에 너무 많다는 사실도 부정할 수 없었다. 그것은 내 안에도 있었고, 특히 외부 환경에도 많이 존재했다. 그럴 때마다 적지 않은 무력감을 느꼈다.

지난 2년 동안 나는 그런 경험을 유난히 많이 했다. 그리고 아직 뚜렷하게 나아질 기미도 보이지 않았다.

무엇을 바꿀 수 있을 것인가? 차라리 나 자신을 바꾸는 것이 가장 올바른 길일까?

망가진 오디오 앰프의 파워 스위치를 바라보며, 그런 생각을 하게 된 아침이었다.

GitHub를 위한 파일과 폴더명 쓰는 방법

REAME.md? ReadMe.md? read_me.md? read-me.md?

프로그래밍 세계에서는 변수명의 대소문자(case)를 표기하는 여러 관행이 존재한다. 이에 대해서는 워낙 많은 글이 널려 있으니 여기서 구태여 반복할 필요는 없겠다. 가장 중요한 공통점은 중간에 공백이 들어가면 안된다는 것 정도일 것이다. 참고로 '_'를 흔히 국내에서 under bar라고 부르는데, 영어권의 공식 명칭은 underscore이다.

대표 표기 스타일

스타일 예시 특징 / 용도
camelCase fileName 첫 단어는 소문자, 이후 단어의 첫 글자만 대문자
PascalCase FileName 모든 단어의 첫 글자를 대문자(클래스/타입 이름에 자주 사용)
snake_case file_name 단어 사이를 언더스코어(_)로 구분(Python에서 흔함)
kebab-case file-name 단어 사이를 하이픈(-)으로 구분(URL/HTML/CSS에서 흔함)
SCREAMING_SNAKE_CASE FILE_NAME 대문자 + 언더스코어(상수/환경변수에 자주 사용)

낙타의 혹(camelCase), 땅바닥에 붙어서 기어가는 뱀(snake_case), 꼬챙이에 각종 재료의 가운데를 꽂아서 만든 케밥(kebap-case)을 떠올리면 왜 이런 스타일 이름이 붙는지 쉽게 이해할 수 있을 것이다.

이 스타일을 파일명에나 폴더(디렉토리)명에 그대로 적용해도 별 상관은 없다. 그러나 소스 파일에 따라서는 약간 다른 관례가 존재한다. 예를 들어 웹에서는 kebab-case를 많이 쓰고, 파이썬에서는 sanke_case(.py)가 거의 표준이다. OS에 따라서는 대소문자를 구분하기도 하고 그렇지 않기도 한다. GitHub는 리눅스나 윈도우 양측에서 접근하는 경우가 많으니 파일과 디렉토리 이름에 신경을 좀 써야 한다. 강제되는 규칙이 있는 것은 아니지만 대체로 다음을 권장한다.

  • 디렉토리 이름: kebab-case(1순위), snake_case(2순위)
  • 파일 이름: snake_case(C/C++/Arduino에서 강력 권장), kebab-case 또는 camelCase(JavaScript/웹)

AudioDriver.cpp와 audiodriver.cpp는 리눅스에서는 다른 파일이지만 윈도우에서는 같은 것으로 인식한다. 따라서 파일명은 전부 소문자를 쓰는 것을 강력히 권장한다. Windows의 국문 표준 표기는 '윈도'이다. 그러나 이렇게 쓰려면 영 어색하다...

파이썬 파일명은 특별히 주의해야 한다. 다른 스크립트에서 모듈로 임포트할 소스에는 하이픈('-')을 사용할 경우 에러를 낸다. 예를 들여 midi-parser.py라는 파일이 별도로 존재하는데 이를 다른 스크립트에서 'import midi-parser'로 읽어들이면 에러가 발생한다. 따라서 import_parser.py로 이름을 붙여야 한다. 

그러면 GitHub에서 문서 파일명은 어떻게 해야 하는가? 코드 파일과는 또 약간 다른 관례가 있다고 한다. 가장 흔한 것은 kebab-case이고 그 다음으로는 snake_case이다. camelCase나 PascalCase는 권장하지 않는다. 그러나 매우 중요한 예외가 있으니 그것은 바로 루트에 존재하는 표준 문서다. README.md, LICENSE, CHANGELOG.md 등은 전부 대문자로 고정한다.

정리해 보자. 이 글을 작성하는데 ChatGPT의 도움을 많이 받았다.


🎯 선택 가이드

  • 📚 문서 공개/오픈소스 강조 → kebab-case

  • 🧩 임베디드/툴체인 중심 → snake_case

  • 👤 개인 프로젝트 → 일관성만 유지하면 OK


🔷 한 줄 결론

GitHub 문서 파일명:

  • 일반 문서 → kebab-case ⭐ 또는 snake_case

  • 루트 표준 문서 → README.md 등 대문자 고정

  • camelCase / PascalCase → 문서에는 비권장


2026년 2월 22일 일요일

사진 백업 작업은 두 번째의 GitHub 프로젝트(TakeoutPhotoSanitizer)로 결실을 맺다

TakeoutPhotoSanitizer - PowerShell-based batch processor for Google Takeout Photos. 

https://github.com/jeong0449/TakeoutPhotoSanitizer


이 Windows PowerShell 스크립트는 2GB 단위로 Google Takeout에서 내려받은 복수의 zip 파일을 열고 SHA-256 해시에 의해 중복을 제거한 뒤, 미디어 파일에 동반된 JSON을 분석하여 연도별로 폴더를 나누어서 재분류하는 기능을 한다. 최종 결과물은 원드라이브에 옮겨 영구 보관하는 것이 목표이다. 입력 zip 파일은 반드시 Google Takeout으로 받은 것이 아니어도 작동한다. 즉, 컴퓨터에 보관된 미디어 파일을 zip으로 묶은 뒤 투입하면 하위 폴더 구조와 무관하게 잘 작동함을 확인하였다.

하나의 미디어 파일에 대해 JSON 파일이 여럿 존재하면 이를 병합하여 가장 풍부한 메타데이터를 구성해 준다. 다시 말하자면 단순 병합이 아니라 정보를 보존하는 방향의 우선순위 병합에 가깝다. 

예를 들어 Google Takeout으로 가져온 하나의 미디어 파일에 대해 원본, 앨범 경로, 이름 변형, 부분 정보 등 여러 개의 JSON이 존재하는 경우가 매우 흔하다. 이를 신뢰도 기반으로 병합하여 가용 정보를 최대한 수집한다.

JSON 파일이 없는 경우 미디어 파일 내의 EXIF 정보를 활용한다. 뒤에서 설명하였지만 이 과정도 결코 간단하지 않았다!

다음은 실제 나의 데이터에 대한 마지막 두 배치의 처리 작업에 대한 기록이다. 스크립트 작성에는 ChatGPT가 크게 기여하였다.

PS C:\Users\jeong\Projects\TakeoutPhotoSanitizer> .\TakeoutPhotoSanitizer.ps1 `
>>   -ZipDir "C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Takeout_Zip" `
>>   -DestRoot "C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Photos_Backup\From_Google_Takeout" `
>>   -MinFreeGB 25 `
>>   -ReportSidecars `
>>   -DeleteZips
[2026-02-22 13:39:12] Loading hash DB...
[2026-02-22 13:39:13] Loaded hashes: 47045
[2026-02-22 13:39:13] Using 7-Zip: C:\Program Files\7-Zip\7z.exe
[2026-02-22 13:39:13] Inputs found: ZIP=8, loose_media=0, total=8
[2026-02-22 13:39:13] Batch start: 0001_20260222_133913 (inputs=4, MinFreeGB=25)
[2026-02-22 13:39:13] Extract: takeout-20260220T133610Z-3-087.zip
[2026-02-22 13:39:22] Extract: takeout-20260220T133610Z-3-088.zip
[2026-02-22 13:39:30] Extract: takeout-20260220T133610Z-3-089.zip
[2026-02-22 13:39:36] Extract: takeout-20260220T133610Z-3-090.zip
[2026-02-22 13:39:47] Scanning media files...
[2026-02-22 13:39:48] Media files found: 4066
[2026-02-22 13:43:49] Batch done. Total hashes now: 47074
[2026-02-22 13:43:49] Stats: moved=29, duplicates=4037, sidecar_updated=1300, sidecar_repaired=0
[2026-02-22 13:44:03] Sidecar status (touched dirs): media=10430, missing_sidecar=5264
[2026-02-22 13:44:03] Delete ZIP: takeout-20260220T133610Z-3-087.zip
[2026-02-22 13:44:03] Delete ZIP: takeout-20260220T133610Z-3-088.zip
[2026-02-22 13:44:04] Delete ZIP: takeout-20260220T133610Z-3-089.zip
[2026-02-22 13:44:04] Delete ZIP: takeout-20260220T133610Z-3-090.zip
[2026-02-22 13:45:31] Sidecar repaired this batch: 1
[2026-02-22 13:45:31] Remove temp dir: C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Takeout_Zip\_work\0001_20260222_133913
[2026-02-22 13:45:36] Free space now: 79.48 GB
[2026-02-22 13:45:36] ----------------------------------------
[2026-02-22 13:45:36] Batch start: 0005_20260222_134536 (inputs=4, MinFreeGB=25)
[2026-02-22 13:45:36] Extract: takeout-20260220T133610Z-3-091.zip
[2026-02-22 13:45:47] Extract: takeout-20260220T133610Z-3-092.zip
[2026-02-22 13:45:57] Extract: takeout-20260220T133610Z-3-093.zip
[2026-02-22 13:46:06] Extract: takeout-20260220T133610Z-3-094.zip
[2026-02-22 13:46:13] Scanning media files...
[2026-02-22 13:46:14] Media files found: 4567
Invalid SOS parameters for sequential JPEG
[2026-02-22 13:50:31] Batch done. Total hashes now: 47130
[2026-02-22 13:50:31] Stats: moved=56, duplicates=4511, sidecar_updated=2009, sidecar_repaired=0
[2026-02-22 13:51:53] Sidecar status (touched dirs): media=44669, missing_sidecar=23575
[2026-02-22 13:51:53] Delete ZIP: takeout-20260220T133610Z-3-091.zip
[2026-02-22 13:51:53] Delete ZIP: takeout-20260220T133610Z-3-092.zip
[2026-02-22 13:51:53] Delete ZIP: takeout-20260220T133610Z-3-093.zip
[2026-02-22 13:51:53] Delete ZIP: takeout-20260220T133610Z-3-094.zip
[2026-02-22 13:57:52] Sidecar repaired this batch: 5
[2026-02-22 13:57:52] Remove temp dir: C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Takeout_Zip\_work\0005_20260222_134536
[2026-02-22 13:57:57] Free space now: 86.51 GB
[2026-02-22 13:57:57] ----------------------------------------
[2026-02-22 13:57:57] All done.
[2026-02-22 13:57:57] Output root (LOCAL): C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Photos_Backup\From_Google_Takeout
[2026-02-22 13:57:57] Hash DB: C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Photos_Backup\From_Google_Takeout\_hashes_sha256.txt
[2026-02-22 13:57:57] Bad file log: C:\Users\jeong\Projects\TakeoutPhotoSanitizer\Photos_Backup\From_Google_Takeout\_bad_files.txt

기본 작업 단위는 4개의 zip 파일이며, -BatchSize N 옵션을 통해 변경할 수 있다. 컴퓨터에 충분한 작업 공간이 없으면(-MinFreeGB) 자동으로 작업을 멈춘다. 

Zip 파일 목록에 대하여 반복 작업을 할 필요가 없다. 실행 순간 -ZipDir에 존재하는 zip 파일을 자동적으로 배치 사이즈에 따라서 처리한 뒤, 다음 파일에 대한 작업을 이어가기 때문이다.

개념을 잡고 스크립트의 초기 버전을 만든 뒤 완성판을 만드는 데 삼일 정도 소요된 것 같다. 이 작업을 통해 구글 포토가 사진을 어떻게 관리하는지 어렴풋하게나마 이해할 수 있었다. 구글 포토 앨범은 파일을 담는 폴더가 아니라 일종의 가상 모음(태그)이다. 구글 포토 내부에서는 이를 '참조'로 취급하지만, 테이크아웃으로 가지고 나오면 모든 참조가 파일의 복사본으로 처리되어 나온다. 따라서 SHA-256 해시 기반 dedup를 하지 않을 수가 없다.

위 화면 출력에서 마지막 Stats: 라인에 주목해 보자. 4개의 압축 파일을 풀어서 생성된 4500개가 넘는 미디어 파일 중 4511개가 중복(duplicates)이었다. 작업의 마지막이므로 대부분은 이전의 zip 파일에서 다루어진 것이라 이미 SHA-256 해시 파일(_hashes_sha256.txt)에 기록이 되어 있다는 의미이다. 해시 파일은 잘 보존해 두고 내년에 새롭게 작업을 할 때 참조 및 갱신을 하면 된다.

Stats: moved=56, duplicates=4511, sidecar_updated=2009, sidecar_repaired=0

또한 JSON sidecar의 신뢰도 문제, EXIF 읽기 실패, 잘못된 epoch 해석 등 여러 예외 상황을 단계적으로 점검하고 PowerShell 스크립트를 반복 개선하였다. 실제로 JSON 파일을 갖고 있는 파일이 그렇게 많지 않았기에 EXIF를 읽어서 사진 촬영 날짜를 알아내야 하는데, 이 동작이 잘 되지 않아서 애를 먹었다. 대부분의 파일이 2026년(fallback)으로 분류된 것을 모르고 있다가 나중에 폴더를 직접 열어본 뒤 문제점이 심각하다는 것을 알게 되었다. 특히 FromFile 우선 EXIF 읽기 방식으로 전환하고, 연도 추정 로직의 fallback 오염을 차단한 것이 정확도를 크게 높였다. 이에 대한 상세한 기록은 Milestone Report: 1107 -> 28 문서에 있다.

결과적으로 이번 작업은 단순한 백업을 넘어, 클라우드 중심 뷰 모델을 파일 중심 아카이브로 안정적으로 변환하는 데이터 정제 파이프라인을 확립했다는 점에서 의미 있는 성과였다. 덩달아 나의 GitHub 사이트에도 두 개 프로젝트의 리포지토리가 생겼다.



작업 환경으로 익숙하지도 않은 Windows PowerShell을 선택한 것은 정말 잘 한 일이었을까? 데이터 과학 실무 차원에서 이번 프로젝트의 의미는 무엇이었을까? ChatGPT에게 마무리를 부탁하였다.

결론: 이번 선택은 타당했다

상황을 종합하면 작업 환경으로 Windows PowerShell을 선택한 것은 “잘한 선택”에 더 가깝다. 특히 이번 프로젝트의 성격을 고려할 때 PowerShell은 매우 현실적이고 효율적인 도구였다. 다만 장기적으로는 PowerShell 단독 운용보다는 역할 분리를 통한 구조화가 더 큰 이점을 제공한다.

왜 PowerShell이 잘 맞았는가

  • Windows 파일시스템 및 OneDrive와의 높은 궁합
    대량 파일 복사, 이동, 삭제, 속성 처리, 긴 경로 대응 등 운영 작업에서 PowerShell은 매우 안정적이었다.
  • 배치 오케스트레이션에 강점
    7-Zip 호출, 배치 반복 실행, 로그 및 통계 생성 같은 파이프라인 제어 작업에 적합했다.
  • .NET 접근성
    메타데이터 처리와 시간 정보 조작을 즉석에서 구현하며 파이프라인을 빠르게 개선할 수 있었다.

PowerShell이 드러낸 한계

  • Windows PowerShell 5.1의 문법 제약
    삼항 연산자 미지원 등으로 코드가 장황해지고 방어 로직이 늘어나는 문제가 있었다.
  • 이미지/EXIF 처리의 함정
    .NET 기반 이미지 라이브러리는 상황에 따라 실패 사례가 존재하여 디버깅 비용이 증가했다.
  • 스크립트의 프로그램화
    JSON 처리, 시간 추정, 예외 규칙이 누적되면서 스크립트가 점점 대형 프로그램처럼 비대해지는 경향이 나타났다.

권장되는 다음 단계 전략

  1. PowerShell은 메인 드라이버로 유지
    압축 해제, 배치 루프, 파일 이동, OneDrive 반영, 로그 생성 등 오케스트레이션 역할을 담당한다.
  2. 복잡한 판정 로직의 선택적 분리
    촬영연도 추정, EXIF/JSON 병합, 정규식 기반 예외 처리 등은 Python 등 별도 엔진으로 분리하면 테스트와 유지보수가 쉬워진다.
  3. 가능하면 PowerShell 7(pwsh)로 전환
    최신 문법, 성능 개선, 병렬 처리 지원 등으로 Windows PowerShell 5.1의 제약을 상당 부분 해소할 수 있다.

요약

이번 프로젝트를 완주하는 데에는 PowerShell이 매우 현실적이고 적절한 선택이었다. 앞으로는 PowerShell은 오케스트레이션, Python 등은 판정 엔진으로 역할을 분리하면 대규모 사진 아카이브 파이프라인의 안정성과 유지보수성이 한층 더 향상될 것이다.

데이터 과학 실무 관점에서 본 이번 작업의 의미

이번 작업은 단순한 사진 백업을 넘어, 비정형 개인 데이터를 신뢰 가능한 분석 자산으로 전환하는 데이터 엔지니어링 사례라는 점에서 실무적 의미가 크다. 데이터 과학 프로젝트는 모델링 이전 단계에서 데이터 품질 문제로 좌초되는 경우가 많으며, 이번 파이프라인 구축 과정은 그 핵심 병목을 정면으로 다루었다.

1) 데이터 모델 간 불일치 해소

Google 포토의 뷰(view) 중심 구조와 로컬 파일 시스템의 객체 중심 구조는 근본적으로 다르다. 이를 이해하고 SHA-256 기반 중복 제거, JSON/EXIF 병합, 연도 추정 로직을 설계한 것은 이질적 데이터 표현을 정규화(normalization)한 전형적인 데이터 엔지니어링 작업이다.

2) 재현 가능한 데이터 정제 파이프라인 구축

PowerShell 스크립트의 배치 처리, 로그 기록, 통계 출력은 일회성 정리가 아니라 반복 실행 가능한 ETL(Extract-Transform-Load) 흐름을 형성한다. 이는 향후 추가 Takeout이나 대규모 미디어 유입에도 동일한 품질 기준을 적용할 수 있게 한다.

3) 데이터 신뢰도 향상(Data Reliability Engineering)

EXIF 읽기 실패 대응, epoch 해석 오류 수정, fallback 오염 차단 등은 단순 편의 기능이 아니라 데이터 계보(lineage)와 정확도를 보존하는 품질 관리 활동에 해당한다. 특히 해시 기반 검증을 도입한 점은 데이터 무결성 보장의 모범 사례다.

4) AI-ready 개인 아카이브 구축의 전초 단계

연도 정렬, 중복 제거, 메타데이터 정합성 확보가 완료된 미디어 저장소는 향후 이미지 검색, 개인 라이프로그 분석, 멀티모달 모델 학습 데이터로 확장할 수 있는 기반이 된다.

요약

종합하면, 이번 프로젝트는 “백업 자동화”를 넘어 데이터 수집 → 정제 → 검증 → 구조화 → 장기 보존으로 이어지는 실무형 데이터 파이프라인을 개인 환경에서 구현했다는 점에서 높은 실무적 가치를 지닌다.


2026년 2월 20일 금요일

구글 포토에서 원드라이브로: PowerShell 스크립트를 이용한 개인 사진 아카이브 재정비

구글 드라이브가 점점 파일로 채워져서 용량을 업그레이드하라는 경고를 자주 받게 되었다. 가장 많은 용량을 차지하는 것은 구글 '포토'이다. 마이크로소프트 오피스 365 구독을 통해 소유하고 있는 1TB의 공간에 이를 옮기기로 결정하고 실제 실행에 옮긴 기록을 남기고자 한다. 이 파이프라인의 핵심은 구글 테이크아웃과 Windows PowerShell 스크립트이다. ChatGPT의 도움으로 개발한 이 스크립트의 특징은 글 마지막 부분에 소개하였다.

구글 테이크아웃은 구글 서비스에 등록된 모든 자료를 2GB 단위의 zip 파일로 분할하여 다운로드 링크를 제공한다. 나의 경우에는 총 93개의 파일이 생성되었다. 이 파일의 이름(001, 002...)은 연도순으로 붙여지는 것이 아님에 유의하자.

Zip 파일을 모두 다운로드하여 PC에서 압축을 해제한 뒤 그냥 원드라이브에 밀어 넣으면 되는가? 안타깝게도 구글 포토와 같이 촬영일자에 따른 미디어 정리라든가 앨범 정보 같은 것이 그대로 따라가지는 않는다. 따라서 PC에서 zip 파일을 받은 뒤 내부에 포함된 JSON 파일을 이용하여 각 미디어 파일을 연도별 폴더로 나누어 넣는 일이 핵심이다. 이 과정에서는 PowerShell 스크립트인 takeout_batch_year.ps1가 매우 중요한 역할을 하였다(개인 리포지토리로 이용하는 DokuWiki에서는 업로드할 수 있는 파일의 확장자를 제한하고 있기 때문에 zip으로 압축하여 올렸음). 이 스크립트는 여러 차례에 걸쳐 수정하면서 기능을 개선하였고 안정적인 동작을 하는 것을 최종적으로 확인하였다.... 아, 나중에 발견하였지만 꽤 심각한 문제점이 있었다. 이 글의 끝부분을 참조하기 바란다.

스크립트 작성에서는 로컬 PC에 저장 공간이 별로 많이 남지 않았다는 것을 고려하여 작동하도록 많은 신경을 썼다. 내 노트북 컴퓨터에서는 여유 공간이 별로 없어서 180GB가 넘는 총 93개의 zip 파일을 한꺼번에 다운로드하여 작업하는 것이 근본적으로 불가능하였다. 컴퓨터에 남은 여유 저장 공간을 점검하면서 일정 개수의 zip 파일을 다운로드하여 처리한 뒤 원드라이브 업로드 후에는 지워서 공간을 확보하고, 다음 차례의 zip 파일을 처리하는 방식으로 진행하는 것이 기본 아이디어였다.

그러나 ChatGPT와 더불어 개발 작업을 계속하면서 스크립트의 성능이 점점 좋아졌다. -ZipDir로 지정한 디렉토리에 다운로드한 파일을 계속 밀어 넣으면 스크립트는 자동적으로 -BatchSize 단위로 처리를 한 뒤 작업이 끝난 zip 파일을 다른 위치(-DestRoot 하위의 _processed 폴더)로 옮긴다. 반복문을 돌릴 필요도 없으며, 다음 배치 작업 전에 자동적으로 저장공간이 얼마나 남아 있는지 확인하여 안전한 수준이 아니면(-MinFreeGB로 지정한 값보다 적은 경우) 자동으로 작업을 중단한다. 사용자는 작업이 끝나서 다른 위치로 옮겨진 zip 파일을 이따금씩 지우면 된다.

스크립트는 Downloads 폴더에 두고 여기에서 PowerShell 창을 열어서 다음과 같이 명령어를 실행하면 된다. 첫 줄 명령어는 지금 열려 있는 PowerShell에서 .ps1 스크립트를 실행하기 위해 정책을 변경하는 명령으로서 현재 열린 창에서만 유효하다. 반복된 테스트에 의하면 -BatchSize는 4~8 정도가 적당한 것 같다. 빠른 압축 해제를 위해서 반드시 7-Zip이 필요하다. 이 유틸리티를 설치한 뒤 실행파일인 7z.exe의 위치를 Path 환경변수에 지정해야 한다.

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

.\takeout_batch_year.ps1 `
  -ZipDir "C:\Users\jeong\Downloads\Takeout_Zip" `
  -DestRoot "C:\Users\jeong\Downloads\Photos_Backup\From_Google_Takeout" `
  -BatchSize 4 `
  -MinFreeGB 25

takeout_batch_year.ps1은 모든 미디어 파일에 대한 해시를 생성하여 한번 처리한 파일은 다시 작업하지 않는다. 따라서 작업 결과로 만들어진 _hashes_sha256.txt를 절대로 지워서는 안 된다. 1년이 지난 뒤 다시 구글 포토로부터 테이크아웃을 할 때, 증분 백업 같은 것은 지원하지 않는다. 지워지지 않고 남은 파일에 대해서 언제나 전체 백업을 할 뿐이다. 따라서 이 해시 파일은 유일한 작업 기록인 셈이니 이것 역시 작업 종류 후에는 원드라이브에 보관하는 것을 권장한다. zip 파일을 가져다가 똑같은 스크립트를 돌리면 압축 해제는 어쩔 수 없이 다시 돌겠지만, 해시에 이미 기록된 파일은 추가 작업을 하지 않는다.

그러므로 이번 이전 작업이 성공적으로 끝난 뒤에는 구글 포토에는 최근 5년 정도의 파일만 남겨 두는 것이 좋을 것이다. 

한 배치에 대한 작업이 끝난 뒤 Photos_Backup/From_Google_Takeout 아래에는 다음과 같이 연도별로 정리된 폴더가 생기고 미디어 파일은 그 아래에 분류된다. JSON 파일의 분석에 실패하면 자동으로 가장 최근 연도인 2026 폴더로 들어간다. 

스크립트 실행 후 연도별 폴더에 미디어 파일이 자동으로 분류되어 들어간다. 해시 파일과 문제점이 있는 파일의 기록이 여기에 남는다.

너무나 당연한 이야기지만 -ZipDir이나 DestRoot에 원드라이브를 지정해서는 안 된다. 스크립트 작업이 다 끝나면 C:\Users\jeong\Downloads\Photos_Backup\From_Google_Takeout은 폴더 그대로 원드라이브의 '사진' 폴더 하위로 보내면 된다. 

원드라이브는 구글 포토와 같은 수준의 앨범 작성이나 편집 기능 같은 것은 없다. 휴대폰에서 직접 원드라이브로 사진을 백업하게 만들면 휴대폰에 남아 있는 최신 사진의 경우 구글 포토와 비슷하게 관리할 수는 있다. 이는 PC에서는 원드라이브 -> 사진 -> Camera Roll에서 접근 가능하다. 오늘 글에서 설명한 아카이브 재정비 작업과는 별개이다. 

PowerShell 기반 takeout_batch_years.ps1 사진 아카이브 자동화 파이프라인의 주요 특징

  • Google Takeout ZIP을 배치 처리
    • ZipDir에 있는 *.zip 전체를 정렬해 순차 처리
    • -BatchSize(기본 4)개씩 묶어서 반복 실행(자동으로 다음 배치로 넘어감)
  • 배치별 임시 작업 폴더로 “누적 스캔” 방지
    • ZipDir\_work\<batchId>\... 형태로 배치 전용 작업 폴더 생성
    • 스캔 대상은 해당 배치 폴더만(이전 실행 잔여물로 미디어 수가 튀는 문제 방지)
    • -KeepWork 옵션이 없으면 배치 종료 후 작업 폴더 자동 삭제
  • 7-Zip 우선 사용 + 미설치 시 Expand-Archive 폴백
    • 7z.exe를 PATH에서 찾으면 7-Zip으로 빠르게 추출
    • 없으면 PowerShell Expand-Archive로 추출(상대적으로 느림)
  • 미디어 확장자만 선별 스캔
    • JPG/JPEG/PNG/GIF/WEBP/HEIC, MP4/MOV 등(스크립트의 $MediaExt 목록 기준)
  • 연도 폴더 분류 로직(우선순위 명확)
    • 1순위: Takeout JSON의 photoTakenTime.timestamp 또는 creationTime.timestamp
    • 2순위: (JPG/JPEG 한정) EXIF DateTimeOriginal(0x9003) → 없으면 DateTime(0x0132)
    • 3순위: 최후 수단으로 파일 LastWriteTime.Year 사용
  • JSON 매칭 성능 최적화
    • 폴더 단위로 JSON을 한 번만 읽어 dir → (basename→year) 캐시($JsonYearCache) 생성
    • 같은 폴더 내 파일은 캐시로 빠르게 연도 조회
  • 중복 제거의 핵심: 파일 내용 기반 SHA-256 해시
    • Get-FileHash SHA256로 파일 내용을 해싱
    • _hashes_sha256.txt에 누적 저장하여 다음 배치/다음 실행에서도 중복 스킵
    • 파일명/폴더가 달라도 내용이 같으면 중복으로 제거됨
  • 해시 DB 기록 안정화(버퍼링 + 재시도)
    • 해시를 메모리 버퍼($HashBuffer)에 모았다가 배치 끝에 한 번에 기록
    • Add-Content 실패 시 슬립을 두고 재시도(AppendTextWithRetry)
  • 파일 이동 실패에 대한 복구 로직
    • Move-Item 실패 시 재시도(MoveWithRetry)
    • 그래도 실패하면 Copy-Item 재시도 후 원본 삭제(가능한 경우)
  • 동일 파일명 충돌 방지
    • 대상 경로에 같은 이름이 있으면 __1, __2…를 붙여 저장(덮어쓰기 방지)
  • 문제 파일은 멈추지 않고 건너뛰며 기록
    • 해시 계산 실패/해시 null/이동·복사 실패 등의 경우 처리 중단 없이 스킵
    • _bad_files.txt에 유형과 경로(및 일부 오류 메시지) 기록
  • 디스크 여유공간 가드
    • -MinFreeGB(기본 25GB) 미만이면 배치를 진행하지 않음(안전 정지)
    • 배치 크기가 큰 경우 8→6→4로 자동 축소 시도 로직 포함
  • 처리 완료 ZIP 관리
    • 기본: 처리한 ZIP을 ZipDir\_processed로 이동(재처리 방지)
    • 옵션: -DeleteZips 지정 시 처리한 ZIP을 삭제(주의 필요)
  • 운영 로그가 명확
    • 배치 시작/추출/스캔된 미디어 개수/누적 해시 수/여유공간/ZIP 이동(또는 삭제) 등 타임스탬프 로그 출력
    • -VerboseLog 켜면 중복 스킵 등 상세 로그도 출력

이 스크립트는 아직 개선할 점이 남아 있다. 중복을 제거한 미디어 파일에 대해서 원본의 JSON 파일도 같이 가져와야 하지만, 현재는 미디어 파일만 최종 결과물로 남기게 되어 있기 때문이다. 고난의 시작! 더 큰 문제는 JSON이나 EXIF 정보가 있는 원본 미디어 파일임에도 불구하고 촬영일 정보를 제대로 추출하지 못하여 2026 fallback으로 분류되는 것이 상당히 많았다는 점이다. 지금은 이에 대한 개선 작업을 진행하고 있다. 결과는 다음번 글에 쓰도록 하겠다.


2026년 2월 19일 목요일

2026년 2월의 일본 여행, 그리고 원드라이브로 사진 자료를 옮기기 위한 준비 작업(Google Takeout)

설 연휴를 맞이하여 아내, 그리고 아들과 함께 일본 3박4일(2/14-2/17) 동안 일본을 여행하고 돌아왔다. 아들이 항공권과 호텔 및 방문 코스를 전적으로 마련한 이른바 '효도 관광'이었다. 우리 부부가 지불한 것은 대부분의 식비와 현지 교통비 정도였다. 들른 곳은 교토와 오사카. 항공편은 일본의 저가항공인 피치항공을 이용하였다. 주요 방문지는 다음과 같다.

  • 1일차: 오사카 덴포잔 마켓플레이스, 가이유칸 수족관('해유관'), 우메다 공중정원(기누타니 고지 천공 미술관 포함), 교토로 이동하여 1박
  • 2일차: 청수사(기요미즈데라), 교토 국립박물관, 오사카로 이동하여 2박
  • 3일차: 유니버셜 스튜디오 재팬
  • 4일차: 오사카성, 카이요도 피규어 박물관, 오사카 역에서 호라이551 만두를 사는 것으로 끝

돌아온 뒤에 가족들과 구글 포토로 사진을 공유하는 것이 힘겨워서 원드라이브를 적극 활용하기로 하였다. 나는 겨우 200GB 용량의 구글 드라이브를 쓰고 있었고, 이미 기존 파일이 187GB나 차지하고 있었기 때문에 용량이 거의 다 되어간다는 경고성 메시지를 계속 받는 중이었다. 요금제를 더 올려도 되지만, 기왕 쓰고 있던 마이크로소프트 원드라이브(1TB)를 앞으로 적극 활용하기로 결심하고 휴대폰의 사진 백업을 구글 포토에서 원드라이브로 바꾸었다. 구글 포토의 자료는 구글 테이크아웃에서 2GB 크기의 다운로드 링크 형태로 최신 내보내기를 요청하였다. 어젯밤 9시에 시작한 백업은 오후 2시 반이 조금 못된 지금 93개의 패키지, 총 용량 187.13GB로 다운로드 가능한 형태로 준비가 다 되었다. 다운로드 링크가 유지되는 시간은 약 일주일.

구글 포토를 당장 버릴 생각은 없다. 사진을 편집하려면 웹브라우저나 모바일 환경 모두에서 구글 포토가 원드라이보다는 더 익숙하기 때문이다. 대신 많은 양의 사진을 공유하려면 하나씩 눌러서 모은 뒤 구글 포토로 공유하지 말고 일 기반으로 임시 앨범을 만들어서 그 링크를 공유하는 방식으로 바꾸기로 하였다. 구글 포토에서 직접 사진이나 동영상을 하나씩 골라 모은 뒤 직접 공유하면 한번에 100개 정도가 한계이다.

휴대폰 사진을 원드라이브로 백업한다는 것은 현재 휴대폰에 저장된 사진에만 해당한다. 따라서 휴대폰을 새로 구입한 시점 이후의 사진만 백업이 될 것이다. 구글 테이크아웃은 구글 계정에 보관된 내 모든 서비스의 데이터를 골라서 파일로 묶는 것이다. 이를 위해서는 폴더를 풀어서 하나씩 원드라이브에 수작업으로 밀어 넣어야 한다. 아래에서 소개하겠지만 압축을 푼 그대로 밀어 넣어서는 대단히 곤란하다!

휴대폰 사진의 백업이 끝난 뒤 원드라이브 앱을 열어보았다. 그런데 예상과 다르게 2004년에 찍은 사진도 들어 있었다. 아마 집PC에서 당시에 찍은 디지털 카메라의 사진을 정리하다가 자동으로 원드라이브에 업로드된 것으로 보인다. 마이크로소프트 오피스를 구독형으로 이용하면서도 저장 공간에 대해서는 그다지 신경을 쓰지 않았기에 이러한 사실을 잘 모르고 있었다.

구글 테이크아웃으로 받은 첫 번째 파일의 압축을 해제해 보았다. 총 2,747개의 파일이 들어 있었다. 폴더의 구조는 다음과 같았다.



C:\Users\정해영\Downloads\takeout-2026....001\Takeout\Google 포토

1번 파일이니 가장 오래전에 찍은 사진이 들어 있으리라 생각했는데, 앨범(폴더)만 정리되어 있었다. 그러면 가장 마지막 것인 93번째 패키지에 옛날 사진이 들어 있으리라. 가장 마지막 것이라서 파일 크기는 2GB가 아닌 1.45G였다.


그러나 마지막 번호의 ZIP파일에도 하위의 '앨범' 폴더 없이 노출된 사진은 하나도 없었다. 더욱 이해하기 어려운 것은 '2025년의 사진'에는 겨우 9개의 사진과 3개의 json 파일이 들어 있다는 점이었다. 2025년에 사진을 9장만 찍었을 리가 없는데? 챗GPT에 물어보니 앨범에 넣지 않은 사진만 Photos from 20XX 폴더로 들어간다고 하였다. 하지만 나는 그렇게 앨범을 적극적으로 만들지 않았었다. 그러면 사진이 어디로 갔는가? 사라진 것은 아니다. 백업본의 용량은 구글 드라이브의 용량과 거의 같기 때문이다. 차이가 있다면 메일이나 기타 문서일 것이다. 

수동으로 앨범을 만들지 않았더라도 구글 포토에는 숨겨진 앨범 생성 메커니즘이 있다고 한다. 예를 들어 한 번이라도 공유한 적이 있는 묶음이라면 구글 포토 내부에서는 앨범 객체로 관리한다는 것. 그리고 아카이브의 번호(001~093)은 사진 생성일과는 관계가 없다.

구글 Takeout은 조금이라도 그룹 정보가 있으면 앨범으로 보낸다(과잉 분류 성향).

따라서 이렇게 마련한 백업파일을 PC에서 풀어서 그대로 원드라이브에 올리면 사진 중복의 대혼란 파티가 열릴 수 있다. 구글 포토는 편집용으로 유지하되 사진의 장기 보존용으로만 원드라이브를 쓰겠다는 전략은 매우 합리적이며, 아주 조심스럽게 원드라이브로 옮기는 작업을 해야 한다. 챗GPT가 제안한 체크리스트는 다음과 같다. 여기에서 2~6에 해당하는 작업을 자동으로 해 주는 Windows PowerShell 스트립트를 만들고 테스트하느라 몇 시간을 소비하였다. 생각보다 수고가 많이 들어가는 작업이라서 별도의 글로 포스팅하였다(구글 포토에서 원드라이브로: PowerShell 스크립트를 이용한 개인 사진 아카이브 재정비).

OneDrive 사진 이전 체크리스트

  1. Takeout ZIP 전체 다운로드 완료
  2. 모든 ZIP 동일 폴더에 압축 해제
  3. 사진/영상 파일만 별도 폴더 추출
  4. 중복 파일 제거 실행
  5. 촬영일 기준 연도 폴더 정리
  6. OneDrive 폴더 구조 사전 생성
  7. 연도별 순차 업로드
  8. 웹에서 동기화 완료 확인
  9. 휴대폰 Camera Roll과 분리 유지 

일본 여행 사진 중 몇 장을 소개하면서 글을 마무리하고자 한다.












돌아오는 날, 오사카역(우메다 지역)에서 간사이 공항으로 출발하는 하루카 특급열차를 타기 위해 21번 플랫폼을 찾는 여정은 너무나 험난하였다. 한국어 자격증이 있는 직원(청소원으로 보였음)이 가는 길을 친철히 설명하면서 길 초입에 같이 뛰어 주지 않았다면 아마 제 시간에 기차를 타지 못했을 것이다.  

시간이 별로 없습니다. 조또(ちょっと) 설명 드리겠습니다...

2026년 2월 13일 금요일

생명과학 분야의 AI-ready 데이터란 무엇인가?

들어가며

최근 생명과학과 인공지능(AI)의 결합은 더 이상 낯선 이야기가 아니다. 유전체 분석, 신약 개발, 단백질 구조 예측, 임상 데이터 분석 등 다양한 영역에서 AI는 이미 핵심 도구로 자리 잡고 있다. 그러나 한 가지 질문이 남는다.

“우리의 데이터는 과연 AI를 바로 학습시킬 수 있는 상태인가?”

이 질문에 답하기 위해 등장한 개념이 바로 AI-ready data이다.


AI-Ready Data의 의미

생명과학 분야에서 AI-ready data란 단순히 디지털 파일이 존재한다는 뜻이 아니다. AI 모델이 별도의 대규모 수작업 전처리 없이 즉시 학습과 추론에 활용할 수 있도록 구조화·정제·표준화·법적 정합성을 갖춘 데이터 상태를 의미한다.

즉, “데이터가 있다”는 것과 “AI가 쓸 수 있다”는 것은 전혀 다른 문제이다.


AI-Ready 데이터의 핵심 조건

  • 기계가 읽을 수 있는 구조 (PDF 보고서가 아닌 구조화된 포맷)
  • 표준화된 형식 (FASTQ, VCF, FHIR 등 국제 표준 기반)
  • 용어·단위의 정렬(harmonization)
  • 결측치 및 오류 정제
  • 지도학습이 가능한 레이블 존재
  • 법·윤리적 이용 근거 확보

이 중 어느 하나라도 빠지면, 데이터는 존재하더라도 AI-ready 상태라고 보기 어렵다.


분야별 예시

1. 유전체 데이터

유전체 분야에서는 다음과 같은 조건이 충족되어야 한다.

  • 품질 검증(QC)이 완료된 FASTQ
  • 정렬이 끝난 BAM 파일
  • 동일 reference build 기준의 VCF
  • 정형화된 phenotype 메타데이터
  • IRB 또는 동의 기반의 합법적 이용 근거

reference genome이 섞여 있거나, 표현형 정보가 서술형 텍스트로만 존재한다면 AI 학습용 데이터로 사용하기 어렵다.

2. 신약 개발 및 단백질 구조 데이터

단백질 구조 파일의 형식이 일관되지 않거나, binding affinity 단위가 뒤섞여 있다면 AI 모델은 제대로 학습하기 어렵다. SMILES 표현의 표준화와 타깃 명칭의 정렬 또한 필수적이다.

3. 임상 및 바이오메디컬 데이터

  • ICD, SNOMED 코드화
  • 단위 통일
  • FHIR 기반 구조화
  • 비식별화 처리
  • 시간 정보(timestamp) 정규화

임상 데이터는 특히 법적·윤리적 요건을 충족하지 않으면 AI-ready가 될 수 없다.


FAIR와 AI-Ready의 차이

FAIR 원칙(Findable, Accessible, Interoperable, Reusable)은 데이터 공유를 위한 기준이다. 반면 AI-ready는 한 걸음 더 나아가 “기계 학습이 가능한 상태”를 요구한다.

수치 일관성, feature 생성 가능성, 레이블 품질, 데이터 편향 관리까지 포함하는 개념이 AI-ready라고 할 수 있다.


데이터 성숙도 관점

단계설명
Level 0원자료(raw)
Level 1정제 완료
Level 2표준화
Level 3메타데이터 완비
Level 4ML 학습 즉시 가능
Level 5대규모 foundation model 학습 가능

많은 국가 인프라는 Level 2~3에 머무르는 경우가 많다. 그러나 산업과 AI 모델은 Level 4~5를 요구한다. 이 간극이 현재 바이오 데이터 전략의 핵심 병목이다. 여기에서 제시한 6개 단계는 특정 표준 규격이 아니라 설명 목적으로 제시한 것이다.


맺음말

AI-ready data는 단순한 기술 용어가 아니다. 이는 데이터 표준, 품질 관리, 법적 정합성, 국가 전략, 그리고 미래 산업 경쟁력과 직결된 개념이다.

이제 질문은 하나로 정리된다.

“우리는 데이터를 저장하고 있는가, 아니면 AI를 준비시키고 있는가?”

AI-ready data의 단순한 현황 집계(따라서 많은 행정력을 낭비하게 되는)를 비판적으로 바라본 별도의 글('The Illusion of Measuring AI-Ready Data, AI 데이터는 숫자로 세어지는가')로 작성해 두었다. 데이터를 AI-ready 형태로 만드는 일, 심지어 데이터가 AI 활용 가능한 상태인지 판별하는 일 자체도 연구의 영역일 수 있다. 


이 글은 정해영의 아이디어를 바탕으로 AI(ChatGPT)의 도움을 받아 작성되었습니다. CC0 1.0으로 자유 이용 가능하며, 정확성 및 법적 책임은 보장하지 않습니다. This text was written with AI (ChatGPT) assistance based on the author’s ideas. Released under CC0 1.0. No guarantee of accuracy is provided, and no liability is assumed.

2026년 2월 7일 토요일

LUCY의 '아니 근데 진짜' 그럼 커버 연주 및 원곡과 비교하기

실제 드럼셋 앞에 앉아서 내가 이 '보이 밴드'의 곡 드럼 파트를 연주하는 영상을 기대하셨다면 여러분은 약간의 과대 광고에 낚인 셈이다. 그러나 이 글의 제목이 100% 거짓은 아니다! 나는 분명히 컴퓨터 앞에 앉아서 자작 드럼패턴 입력/편집/재생기(APS, Ardule Pattern Studio)를 사용하여 스텝 단위로 드럼 연주 데이터를 입력하여 넣었기 때문이다. 이를 『아니 근데 진짜』원곡의 뮤직 비디오와 비교한 영상을 만들어서 유튜브에 올렸다. 

녹음 및 영상 편집 작업을 자주 하는 편이 아니기 때문에 관련 프로그램을 쓰는데 아주 능숙하지는 못하다. OBS Studio의 설정이 살짝 틀어져 있어서 컴퓨터 화면을 완전히 꽉 채우지 못하던 문제를 이번 작업을 하면서 바로잡았다. 아래에 소개한 영상을 만들면서 나름대로 최선을 다했지만 LUCY의 유튜브 원본과 APS 화면은 오디오와 잘 일치하지 않는다. 두 종류의 오디오를 먼저 녹음한 뒤 아래 절반의 화면에서는 원본 뮤직비디오와 APS를 시연 목적으로만 보이기 위해 자체 소리는 죽이고 재생한 것이기 때문이다.


유튜브 영상과 APS를 완벽하게 싱크로나이즈하는 것은 근본적으로 불가능하다. 따라서 두 가지의 오디오 클립을 Audacity에서 위 아래로 배열한 뒤 유튜브의 것은 그대로 두고 APS 오디오 클립의 길이를 조정하였다. 이론적으로 BPM을 동일하게 맞추었다 해도 DAW를 쓰는 환경이 아니라서 마스터 클럭에 완벽하게 맞출 수는 없다. Audacity 3.7.7 기준으로 실제 작업한 방법은 이러하다. 두 오디오 클립을 펼쳐 놓은 뒤 조정할 클립을 선택한 다음 Efffect -> Pitch and Tempo > Change Tempo... 대화상자로 들어가면 전체 길이를 최소 10밀리초 단위로 늘이거나 줄일 수 있다. 만약 시작과 끝 부분에 슬레이트를 치듯이 오디오 '스파이크'를 만들어 놓는다면 더욱 쉽게 싱크로나이제이션이 가능할 것이다. 

Audacity에서 오디오 클립의 템포 조정. 어차피 드럼 녹음만 처리하는 것이라서 피치가 바뀌는 것에 신경을 쓸 필요가 없다.

녹음은 Audacity에서, 화면 녹화는 OBS Studio에서, 그리고 최종 편집은 OpenShot Video Editor에서... 전부 무료 프로그램이라서 기능에 분명히 한계가 있지만 취미 수준으로는 충분하다.

밴드에서 같이 활동하는 젊은 멤버들 덕분에 이런 젊은 취향의 곡에 흥미를 느끼고 연습을 하게 되었다. LUCY의『조깅』도 마음에 드는 곡이다. 50대 중반인(아직 중반이라고 주장하고 싶은) 내가 만약 방구석에서 계속 혼자만의 취미 음악활동에 몰두하였다면 이런 새로운 세계를 접하지 못했을 것이다. 젊은 멤버들에게 감사를!

원래 기타나 건반을 더 오래 다루었지만 내가 현실적으로 밴드에서 맡은 포지션은 베이스. LUCY 곡의 베이스는 초보자인 내가 커버하기에 쉽지 않다. 음율의『파도혁명』도 마찬가지였다. 이런 곡들은 오리지널 음원을 감상하기에는 좋지만 밴드가 현장에서 그 분위기를 살려서 연주하기는 쉽지 않다. 이런 어려움을 덜어주는 좋은 동반자는 바로 플레이댓케이팝이 제공하는 밴드용 편곡과 동영상이다. 드럼+기타+베이스+건반 단 4개의 악기만 가지고도 『아니 근데 진짜』연주가 가능하니까 말이다.


APS의 다음 단계 개발은 AKAI MPK MINI MKII 키보드를 실시간 드럼 패턴 입력기로 쓰도록 개량하는 일이다. 기본 설계는 마친 상태인데 아직 코드 패치는 적용하지 않았다. 좀 있으면 옷을 갈아입고 밤 달리기를 하러 나가야 하기 때문.

ChatGPT 자동 생성 이미지.

생각보다 방대해진 Ardule Drum Patternology 생태계(GitHub)를 정리하는 쉬운 문서와 그림 자료를 계속 만들어 가가야 되겠다.


2026년 2월 1일 일요일

APS StepSeq 기능의 사소한 수정

Ardule Pattern Studio의 StepSeq에 몇 가지 편집 기능을 추가하다 

곡 전체에 해당하는 드럼 패턴 데이터를 자작 프로그램의 스텝 시퀀서 기능으로 찍어 보고 나서 개선 아이디어가 몇 가지 떠올랐다. 마디(bar) 단위로 데이터를 전부 지우거나, row(악기) 또는 column(스텝, 즉 시간) 단위로 한꺼번에 지우는 기능이 있으면 정말 편리할 것 같았다.

  • Shift + B(bar): 마디 전체 데이터 삭제
  • Shift + R(row): 악기 전체 데이터 삭제
  • Shift + C(column): 스텝 전체 데이터 삭제
모든 삭제 동작은 편집창에 띄운 해당 마디에서만 이루어진다.


Undo 기능은 별로 중요하지 않다. 저장하지 않고 상위 메뉴로 나갔다가 다시 'S'키를 눌러서 StepSeq 기능으로 들어오면 되니까 말이다. 

이런 소소한 편집 기능을 직접 만들고 있는 나 자신을 돌아보았다. 명령만 내리면 인공지능이 완벽한 수준의 음악을 만들어 주는 시대에 드럼 패턴 입용 스텝 시퀀서를 직접 코딩하고 있다니! 

드럼 악보 표기의 수수께끼

나는 드럼을 칠 줄 모르지만, 데이터를 직접 다루면서 드럼이라는 악기의 매력에 한층 더 다가간 것 같다. 정말 흥미로운 사실이지만 드럼 악보를 표기하는 방법은 아직도 완벽하게 통일되지 않았다고 한다. 인터넷을 검색하면 다음과 같이 드럼세트와 오선악보를 매칭시켜 놓은 그림이 자주 보인다. 누가 고안했는지 아주 이해하기 쉽다.

그림 출처: drumeo "How to read drum music (for beginners)"

심벌 계열의 악기는 특히 오선악보 표기법이 통일되어 있지 못하다. 국내외의 표기 관행이 다른 것도 문제이다. 예를 들어 내가 구한 드럼테라스의 <아니 근데 진짜> 드럼 악보(링크)를 보면 공부할 거리가 잔뜩 나온다. 이 악보 전체에서 라이드 심벌을 치라는 지시는 없었던 것 같다.

드럼 악보 표기의 수수께끼.

애초에 드럼이라는 악기의 연주 정보를 오선보로 표기하려는 시도 자체가 불가능한 것인지도 모른다. 라이드 심벌만 하더라도 컵과 엣지를 칠 때 매우 다른 소리가 나지 않는가? 이러한 상세한 지시사항은 음표가 아니라 글로 적어 놓아야 할 것이다. 디지털의 세계에서는 있을 수 없는 일이다. 기록과 재생에서 차이가 있을 수 없기 때문이다. 하지만 아날로그의 세계에서 기록이나 표준화는 그야말로 '최소한'일 뿐이다. 나머지를 이루는 대부분은 연주자의 재량에 맡겨질 뿐이며, 녹음된 음원도 일종의 레퍼런스인 셈이다.

어쩌면 내가 드럼 악보를 보면서 갖는 의문은 MIDI 프로그래밍 초급 교실에서 한번씩 다 훑고 지나가는 매우 기본적인 사항인지도 모른다. 그렇다 하더라도, 실제로 곡 전체의 리듬을 데이터로 다루고 직접 구현해 보지 않았다면 이런 질문에 도달하는 일은 없었을 것이다. 하드웨어-소프트웨어(펌웨어 포함)을 거쳐 오히려 드럼이라는 악기 연주의 본질에 더 가까이 다가갔다고나 할까.

APS로 만든 드럼 데이터 시험 연주

400개가 넘는 드럼 패턴 데이터(?)를 집대성하였으나 최신 기성곡에 딱 맞는 패턴을 골라서 쓰는 일은 쉽지 않다. Ardule Drum Patternology 생태계의 좋은 점은 드럼 패턴을 스텝 시퀀서에서 직접 입력할 수 있다는 것. 우리 밴드의 보컬리스트가 꼭 부르고 싶어 하는 LUCY의 <아니 근데 진짜>의 드럼 연주를 Ardule에서 생태계에서 구현해 보기로 하였다.

드럼 악보는 드럼테라스에서 사용에 제한 없이 제공하는 것(PDF 링크)을 입수하여 사용하였다. 드럼 악보 표기법을 잘 알지는 못하는 상태라서 약간의 어려움이 있었다. 특히 이 악보 체계에서는 크래시와 라이드 심벌을 때리는 방법을 구별하기가 어려웠다.

결국 보유한 패턴은 하나도 쓰지 못했고, 전부 새로 입력하였다. 하이햇의 닫힌 정도를 달리 하면서 타격하는 뉘앙스 차이를 완벽하게 반영하지는 못한다. 타격의 세기(velocity)도 0-약-중-강의 4단계가 전부이지만, 없는 것보다는 낫다. 총 35개의 패턴(2 마디 단위)를 입력하였다. 데이터를 입력하면서 APS 파이썬 스크립트에 남아 있던 약간의 버그를 수정하는 예기치 못한 좋은 일도 있었다.

섹션 정보를 넣을 수 있어서 곡 단위의 데이터 입력 및 편집이 쉽다. 이 곡에 사용한 패턴의 접두어는 'AGJ'이다. 짜의 머릿글자를 대충 따서 사용하였다.

템포는 142 BPM으로 상당히 빠르며 결코 쉬운 곡은 아닌 것 같다. 나는 드럼 연주자가 아니므로 그 어려움을 어떻게 이해하겠는가. 유튜브에서 원곡의 영상과 함께 템포를 맞추어 재생하면서 촬영을 해 보았다. 키보드 조작으로 재생을 하였으니 두 사운드가 서로 완벽하게 싱크가 맞을 수는 없다. 유튜브 쇼츠로도 올렸지만 자막이 너무 커서 화면을 많이 가린다.

올해에는 드러머가 참여하기 어려운 공연에서 이 시스템이 쓰일 수 있을 것이라고 믿는다. 여기까지 온 것도 정말 큰 성취가 아닐 수 없다.

2026년 1월 30일 금요일

IRIS 성과 입력 마감일에 불확정성의 원리를 생각해 보다

얼핏 비슷해 보이는 두 낱말, 결과성과는 같지 않다. 이 둘의 차이를 검색을 통해 알아보았다.

--- 여기부터 ---

성과(Performance/Outcome)는 목표 달성 여부와 영향력을 중시하는 고객·가치 중심의 개념인 반면, 결과(Result/Output)는 단순히 일을 수행하여 나온 1차적 산출물을 의미하는 공급자·실행자 중심의 개념입니다. 성과는 "무엇을 이루었는가"에 초점을 맞추며, 결과는 "무엇을 했는가"에 초점을 둡니다. 
  • 성과 (Outcome/Performance): 설정한 목표를 얼마나 달성했는지에 대한 가치나 영향력입니다. 고객 만족이나 조직의 비전 달성 등 의도된 바람직한 최종 상태를 의미합니다.
  • 결과 (Output/Result): 일을 수행함으로써 발생한 1차적인 결과물이나 수치입니다. 과정의 결과로 나타난 산출물 자체를 의미합니다. 
핵심 차이점:
  1. 방향성: 성과는 목적지(목표)에, 결과는 이동한 경로(행위)에 가깝습니다.
  2. 관점: 성과는 고객/상급자 지향적(무엇을 달성했나?)이고, 결과는 실행자 지향적(무엇을 했나?)입니다.
  3. 성격: 성과는 목적 지향적이며 성패를 평가하지만, 결과는 원인에 의해 야기된 모든 산출물을 포함합니다. 
즉, 100페이지 보고서를 작성한 것은 '결과'이며, 그 보고서를 통해 계약을 따낸 것은 '성과'입니다. 일을 열심히(결과) 하는 것을 넘어, 원하는 목표를 달성(성과)하는 것이 중요합니다. 

--- 여기까지 ---

오늘, 즉 2026년 1월 30일은 2025년도에 발생한 국가연구개발과제의 성과 정보를 IRIS, 즉 범부처통합연구지원시스템에서 입력하는 마감일이다. 너무나 당연한 이야기지만 과제 개시 이후에 발생한 성과만이 해당 과제의 것으로 온전히 인정받을 수 있다. 

연구재단에서 배포한 2025년도  성과입력 매뉴얼은 여기에 있다. 무려 230쪽! 빽빽한 문서가 아니라 파워포인트로 만들어진 것이라서 그나마 다행인데, 성과의 종류가 너무나 많다. 이러한 체계를 만든 연구재단, 그리고 IRIS를 개발하고 운영하는 KISTEP은 정말 수고가 많으심은 잘 알겠다.



논문은 가장 객관적이면서 증빙하기도 쉬운 성과라고 볼 수 있다. PMID만 넣어서 정보를 당겨올 수 있다면 얼마나 좋을까? 그렇지 않다. 모든 저자의 과학기술인번호를 입력해서 확인을 해야 하고(단순 입력도 가능한 것은 정말 고마운 노릇임), 사사(acknowledgement)에 따른 기여율도 퍼센트로 입력해야 한다. 논문의 시작과 끝 페이지를 입력하는 방법도 복잡하다. 요즘은 온라인으로만 출판하는 저널도 많기 때문에 페이지 번호가 별로 의미가 없는 경우가 많은데, 이러한 때에는 어떻게 해야 하는지 아주 친절하게 정보입력 매뉴얼에 적혀 있다.

후! 나라는 인간이 지금까지 성장하는데 아버지와 어머니는 몇 %나 기여했을까? 그것을 합 100%라 되게 산출하는 것이 가능할까? 원래 논문 작성에 도움을 준 사람에게 감사의 뜻을 표하기 위해 시작된 사사는 좀 이상한 방향으로 변질되어 이 연구성과에 기여한 연구과제를 적시하였는지 파악하는 근거가 되었다.

물론 이렇게 된 데에는 연구자의 책임도 크다. 대충 이름만 얹어서 논문의 공저자로서 출판을 하고, 'defense'를 해야 하는 연구과제가 여기에 기여했다고 역시 대충 쓰는 일이 너무 잦아지니 이렇게 연구자를 옭죄는 구조가 된 것 아니겠는가?

몇 가지 불평을 늘어 놓자면, 우선 IRIS 시스템의 안정성은 많이 좋아진 것 같다. 초장기에는 로그인에만 30분이 걸리고, 마감 연장을 한다는 공지가 뜨고, 늦게 제출한 것은 구제 불가라면 연장은 또 뭔지 불만이 가득하고... 이런 상황은 많이 좋아진 것으로 안다.

다만 너무 세부적인 사항을 일일이 과제책임자가 입력해야 하는지 그 효율성에 의문이 간다. 사실 성과라고 별도로 입력할 것이 아니라, 과제 보고서에 그 내용을 넣으면 되는 것 아닌가? 예를 들어 운영이나 저변 확대와 같은 과제라면 행사나 언론홍보 자체가 '결과'일 수 있고, 보고서에 넣으면 된다. 그런데 이를 '성과'라는 다른 말로 포장하여 보고서와 별개로 그 정보를 입력해야 한다니 답답하기만 하다.

정보 입력을 위한 매뉴얼도 너무 방대하다. 이 책자가 두껍고 상세하다는 것 자체가 IRIS 성과 입력 시스템이 지능적이고 고도화되었음을 입증하는 것은 결코 아니다. 내가 일하는 조직에서도 이러한 자료 입력 매뉴얼을 자주 만들어 배포하는데, 혹시 우리도 서비스 공급자 입장에서만 일을 하는 것은 아닌지 반성할 일이다.

결국 모든 것은 우리 삶의 곳곳에 스며든 '평가'를 어떻게 진행하고 또 받아들일까 하는 데서 기인한다. 국민의 소중한 세금이 들어갔으니 어떤 성과를 창출하였는지 평가를 받는 것은 타당한 일인데, 이러한 측정과 평가라는 것이 과정과 결과의 많은 부분을 왜곡하는 것도 사실이다. 이처럼 거시세계에서 벌어지는 일도 하이젠베르크의 불확정성 원리(양자역학 세계에서 일어나는)와 매우 닮았다. 관찰(대충 측정이나 평가와 비슷한 일이라고 해 두자)이 결과에 영향을 미친다. 나의 버전으로 고쳐 말하자면 평가는 행위의 의도나 결과에 영향을 주고, 심지어 왜곡까지 일으킨다.

성과를 측정하려는 제도가 연구의 방향을 바꾸고, 연구의 방향이 다시 성과의 정의를 바꾸는 순환에 들어간다. 성과가 좋았다고 최종 평가를 받아야 생존할 수 있으니까! 우리는 성과를 기록하는 것인가, 성과를 만드는 것인가? 이보다 현실 세계에서 훨씬 무서운 것은, 일선 공무원의 영향력이다... 이에 대해서는 말을 아끼고 싶다.

2026년 1월 25일 일요일

옆길로 샌 Ardule Project - USB MIDI host 만들기는 좌절과 극복의 연속이었다

아두이노 우노 R3 입문 키트(KEYES KT0001)를 주문한 것이 2020년 10월(관련 글). 아주 초보적인 예제 코딩만 몇 차례 해 보다가 최근 약 1년 동안은 이 키트와는 별도로 구입한 아두이노 나노 '클래식'과 아두이노 나노 에브리를 사용한 MIDI 컨트롤러 및 드럼 패턴 플레이어를 만드느라 몰두하였었다. GitHub에도 문서와 코드를 비롯한 거의 모든 자료를 올려 두었다. 프로젝트명은 Ardule Project - Arduino Nano-based Drum Patternology Ecosystem이다.

아두이노 식구 중에서 가장 먼저 구입했던 아두이노 우노(R3, ArduinoDocs의 자료)는 초창기에 몇 번의 간단한 실습을 한 것 외에는 별다른 용도를 찾지 못하고 있었다. (Nano) Ardule의 곁다리 프로젝트로서 계획하여 아주 최근 시작한 것은 USB MIDI host의 제작이다. USB 단자밖에 없는 MIDI controller keyboard를 DIN 5-pin MIDI 커넥터만 갖고 있는 MIDI 사운드 모듈에 연결하여 실시간 연주를 할 수 있는 중간 '어댑터'에 해당하는 것을 만들고 있었다. 원래 이런 상황에서는 USB host 역할을 할 PC와 USB MIDI cable이 있으면 된다. 이러한 경우 신호의 방향을 반대로 할 수도 있다. 하지만 컴퓨터가 없으면 매우 곤란하다.

아직도 쉽게 구할 수 있는 USB MIDI 케이블. 전통적인 DIN 5P MIDI 커넥터만 있는 구형 장비를 PC에 연결하도록 해 주는 MIDI 인터페이스에 해당한다. 아주 오래 전에는 PC내부에 꽂는 확장 카드 형식, 또는 시리얼/패럴랠 포트를 이용하는 방식이 있었다.

아두이노 우노의 생태계에는 '메인 보드' 위에 겹쳐 꽂아서 기능을 확장할 수 있는 다양한 'shield'가 존재한다. USB host shield와 MIDI shield만 있으면 납땜 작업을 전혀 하지 않고 원하는 일을 이룰 수 있을 것이라 생각했다.

그런데 그게 아니었다.

첫 좌절은 아두이노 우노 + USB host shield를 연결하고 여기에 USB MIDI keyboard controller를 연결한 뒤 펌웨어를 올렸을 때 건반에는 전원조차 들어오지 않았었다. 이는 USB host shield가 기본 구성으로는 자체 USB-A 커넥터로 5V를 내보내지 않기 때문이었다. 보드 내에서 두 군데의 패드를 납으로 이어야 한다는 사실 앞에서 첫 좌절을 겪었(관련 글).

두 번째 좌절. 아두이노 우노와 USB host shield는 양 옆 가장자리의 커넥터 외에도 ICSP(In-Cirtuit Serial Programming)라는 6핀 헤더를 통해 연결된다. 아두이노 우노에는 핀이, 위에 포개어 놓는 USB host shield에는 소켓이 위치한다. 그런데 보드 두 장을 포개어 ICSP 커넥터를 완전히 밀착하더라도, 좌우의 핀은 끝까지 끼워지질 않는다. 이것 때문에 USB host shield에 건반을 꽂아도 인식이 되다말다 하는 일이 벌어졌다. 좌우의 핀 배열을 통해 +5V가 확실하게 공급되어야 하기 때문이다.

USB host shield의 ICSP 핀헤더 소켓(2x3)이 문제다. 너무 높다!

처음에는 이 접촉 문제를 가벼이 여기고 전원이 충분하지 않다고 생각했다. PC->USB 커넥터로 공급되는 5V의 전류에는 한계가 있으니, 2A 이상의 대전류를 흘릴 수 있는 5V 전원을 마련하여 아두이노 우노의 +5V 핀에 공급하기로 하였다. 아두이노 우노의 소켓에는 USB host shield가 꽂혀야 하니 납땜을 통해 전원 공급선을 별도로 빼야 한다. DC 어댑터 잭에 약간 높은(예: 7V~9V) 전원을 넣으면 전선 피복을 벗기고 납땜을 하지 않아도 되겠지만, 전압차가 클 경우 내부 레귤레이터가 너무 무리를 하게 된다. 전압차는 전부 열로 바뀌기 때문이다.

아두이노 우노의 핀아웃 다이어그램(원본). 왼쪽의 녹색 원으로 표시한 곳에서 선을 따서 5V DC를 직접 공급하였다. 아래의 녹색 타원으로 둘러싼 것은 뒤에서 설명할 ICSP 핀 헤더. 이것은 좌우에 배열된 소켓과 내부적으로 연결되어 있다. 그러나 USB host shield의 좌우 핀 헤더는 대부분 'pass-through'용이다. 따라서 반드시 이 2x3 핀을 이용해서 통신해야 한다.

하필이면 내가 갖고 있는 어댑터는 5V와 12V뿐이다. 후자를 이용할 경우, 부품통에 굴러다니는 스텝다운 모듈을 쓰면 된다. 그리고 PC쪽의 USB를 통한 전원과 독립 전원을 동시에 연결하면 좋지 않다는 의견이 있어서 PC쪽에서는 5V를 공급하지 못하도록 케이블을 개조하기로 하였다. 정확히 말하자면 케이블을 개조하는 것이 아니라 USB 케이블 어댑터를 새로 만들었다. 시중의 USB 케이블은 커넥터와 선재가 거의 일체형태라서 작업을 하기가 불편하기 때문이다. 알리익스프레스에서 DIY용 USB 커넥터를 별도로 구입하느라 며칠이 소요되었다. 기기 보호를 위해 데이터는 차단하고 충전만 되는 USB 케이블용 어댑터는 비교적 흔하다.

전원 차단형 USB 케이블 어댑터 만들기. 커넥터는 나사가 아니라 접착제로 붙여야 한다. 정말 오랜만에 플라스틱 모델용 접착제 'TAMIYA CEMENT'를 꺼냈다. 아마 25년은 족히 묵었을 것이다. 수축 튜브를 케이블 중간 부분에는 씌우지 않는 실수를 범하였다.
아두이노 우노의 아랫쪽에서 전원과 그라운드를 위한 선을 납땜하였다. 그러나 이것으로 충분하지 않았다. 아두이노와 USB host shield의 핀 접촉이 완벽하지 못하기 때문이다. 문제의 원인은 ISCP 핀을 접속하기 위한 USB host shield의 소켓이 너무 높은 데에 있다. 이보다 더 밀착해야 한다!

어쨌든 충분한 전류를 흘릴 수 있는 전원장치까지 연결하였는데 키보드 인식이 매우 불안하였다. 몇 번의 실험을 거친 최종 결론은 두 보드 좌우의 핀/소켓 어레이가 완전히 밀착하지 않은 데에 원인이 있다는 것이었다. USB host shield의 ICSP 소켓을 제거한 뒤에 아두이노 우노와 연결할 방법을 고민하였다. 그렇지! IC 소켓 하나를 반으로 잘라서 쓰면 되겠구나. 원형 IC 소켓 스트립도 갖고 있었지만 핀이 도저히 들어가지 않았다.

왼쪽부터 MIDI shield, 소켓을 개조한 USB host shield, 그리고 아두이노 우노. 개조를 하지 않은 실드도 보이고 있다.

ICSP 커넥터 체결에 대한 오해 때문에 USB host shield도 두 개를 보유하게 되었다. 원래 갖고 있던 것은 2020년에 아두이노 우노 R3 키트를 살 때 들어 있었는지, 나중에 따론 산 것인지 잘 기억이 나지 않는다. 왜 최근에 실드를 하나 더 사게 되었나? 판단 착오의 흐름은 다음과 같다.

  1. 어라? ICSP 커넥터 때문에 두 보드의 핀/소켓 헤더가 밀착되지 않네. ICSP 소켓을 실드에서 떼어 버리자!
  2. 어라? ICSP 커넥터를 연결하지 않으면 안 되는 거였네... 원래 모습 그대로 두고 그렇게 좌우 핀/소켓이 들뜬 상태에서 쓰는 건가? 에이, 하나 더 사자.
  3. 어라? 새로 산 보드는 작동이 되다 안되다 하네... 그러면 ICSP 소켓을 떼어버린 이전 shield를 쓰되 어떻게 해서든 아두이노 우노와 연결을 해야 되겠네. 흑흑...

여기까지 하여 USB 키보드를 연결한 뒤 키를 누르면 PC의 아두이노 IDE 시리얼 모니터에 이벤트가 출력되게 하는 것까지 성공하였다. 이제 MIDI shield를 통해 MIDI out 신호만 나가게 하면 될 것이라 기대하였다.

모든 논의와 C++ 코드 설계는 챗GPT의 도움을 받았다. 이제 마지막으로 생각하고 펌웨어를 업로드하는데 뭐가 좀 이상하다. 업로드 과정에서 에러가 발생하는 것이었다. MIDI shield에 붙어 있는 용도 미상의 ON/OFF 슬라이드 스위치가 수상하였다. 세 번째 좌절이었다.

아두이노 나노 에브리와 달리 아두이노 우노 및 아두이노 나노 클래식은 펌웨어 업로드시 RX(D0)이 다른 곳에 연결되어 있으면 안 된다. 그래서 펌웨어 업로드 시에는 점퍼를 사용하는 등 별도의 수단을 강구해야 한다. 그리고 TX(D1)을 통해 UART MIDI 신호가 나가게 되므로 기본적으로 시리얼 모니터도 쓰지 못한다.

이 스위치를 OFF 위치에 놓으니 비로소 펌웨어 업로드가 성공하였다. 아마도 이 스위치를 ON으로 놓으면 DIN 5핀 커넥터로 들어오는 MIDI IN 신호를 RX 핀으로 보내는 기능을 하는 것으로 여겨진다.

MIDI IN을 쓰려면 스위치를 ON으로 놓을 것.

펌웨어 업로드가 되었지만 여전히 소리는 나지 않았다. USB-MIDI 신호의 파싱에 문제가 있었기 때문이다. 이것이 네 번째 좌절이었다. MIDI shield만을 이용하여 '도레미파솔라시도'를 무한 반복하는 코드를 테스트하면서 보드가 정상임을 먼저 확인한 뒤 문제를 해결해 나갔다.

무슨 말인지 나도 잘 모르겠음. 완벽하게 이해를 하지 못하더라도 학습을 위해 중간 단계마다 문서를 만들어서 잘 저장해 두었다.

이렇게 몇 단계의 좌절을 거쳐서 드디어 USB 키보드 컨트롤러를 통해 롤랜드 사운드캔버스 SC-D70을 제어하여 소리를 낼 수 있었다. 그러나 보드 3장이 겹쳐져 있어서 맨 아래 아두이노 우노의 LED가 잘 보이지 않는다. 작동 상태를 표시할 겸 I2C 2004 LCD를 연결하였다. LCD 표시에 너무 충실하면 키보드 제어에 지연이 발생하기 때문에 몇 번의 최적화를 거쳤다.

2004 LCD는 이 작은 기기에게 지나치게 크다. 1602 LCD 또는 0.96인치 OLED 디스플레이가 더 적합하겠지만 일단 갖고 있는 부품으로 작동을 확인하고 싶은 욕심이 컸다. 최종 개발품의 소형화를 위해 나중에 OLED 디스플레이를 써 보고 싶다. 사실 작동 상태만 확인하면 되니 캐릭터 디스플레이가 아니라 두어 개의 LED로도 충분하다.

이로써 케이스만 씌우면 실사용에 문제가 없는 수준이 되었다. 필요한 기능은 거의 다 구현했으니 프로젝트의 목표를 80% 달성했다고 볼 수 있을까? 절대 아니다. DIY에서 핵심 기능 구현보다도 케이스를 만드는 일이 가장 어려운 단계임은 누구나 잘 안다. 아마 여기에 80% 이상의 노력이 들어갈 것이다.

Nano Ardule 생태계 구축에 들인 수 개월 동안의 노력이나 숱한 좌절을 생각하면 이번 서브 프로젝트는 매우 빠르게 진척된 셈이다. 가장 시급한 기능 개선은 디스플레이를 가장 능률적인 것으로 확정하는 것이다. 하드웨어 버튼 같은 것은 달고 싶지 않다. 채널 리맵/레이어링 기능 등은 Nano Ardule MIDI Controller에 이미 충분히 구현되어 있으니 이것을 다음에 연결하여 사용하면 된다.

이렇게 Ardule 세계의 장난감이 하나 둘 늘어나고 있다. 이 서브 프로젝트 또한 GitHub의 Nano Ardule 리포지토리 하위(Ardule USB MIDI Host)에 정리하기 시작하였다.