
개발자에게 있어 몰입(Flow)이 깨지는 순간의 비용은 단순히 '잠시 멈춤'이 아닙니다. 다시 그 맥락(Context)을 로딩하기 위해 뇌는 최소 15분에서 20분의 램프업(Ramp-up) 시간을 소모합니다. 재택근무 중 방문을 벌컥 여는 가족이나 룸메이트는, 비유하자면 잘 돌아가는 분산 학습 클러스터의 전원 케이블을 뽑는 것과 같습니다.
저는 이 인터럽트(Interrupt) 비용을 줄여보겠다고 아주 거창한 프로젝트를 시작했습니다. 문 앞에 현재 내 상태를 알리는 'Do Not Disturb' 장치를 만드는 것이었습니다. 단순한 빨간 불이 아니라, 회의 종료 시간과 남은 시간, 가능하다면 주가까지 보여주는 대시보드를 상상했습니다.
소프트웨어 엔지니어로서의 오만함이 하늘을 찌르던 시기였습니다. "서버 수천 대도 관리하는데, ESP32 하나 컨트롤 못 하겠어?"라는 안일한 생각이 화근이었습니다.

소프트웨어 구현은 나름 흥미로웠습니다. 맥북의 카메라 상태를 실시간으로 감지하는 API가 없다는 사실에 잠시 당황했지만, 오히려 투지가 생겼습니다. 무거운 라이브러리를 덕지덕지 바르는 대신, 시스템 로그 스트림(log stream)을 직접 파싱하기로 했습니다.
AVCaptureSessionDidStartRunningNotification
이 로그 하나를 건지기 위해 커널 레벨의 메시지를 훑는 과정은 꽤나 즐거웠습니다. 문제는 통신 방식이었습니다. 처음엔 500ms마다 상태를 체크하는 폴링(Polling) 방식을 썼는데, 불필요한 트래픽과 전력 소모를 보며 죄책감이 들더군요. 결국 mDNS를 적용하고 실시간성을 확보했습니다. Latency(지연 시간)를 줄이고 리소스 효율을 높이는 것, 여기까지는 제 전문 분야였습니다.
하지만 진짜 지옥은 모니터 밖, 물리 세계(Physical World)에 있었습니다.
회로가 드러난 기판을 방문에 테이프로 붙여놓는 건 제 미학이 허락하지 않았습니다. 3D 프린터로 케이스를 만들기로 결심했습니다. Fusion 360을 켰을 때만 해도 자신만만했습니다. 좌표는 정확하고, 수치는 거짓말을 하지 않으니까요. 소프트웨어 세계에서 1mm는 영원히 1mm입니다.
그러나 하드웨어의 세계는 달랐습니다.
3D 프린팅의 결과물은 제 설계도와 미묘하게 달랐습니다. 노즐의 두께, 필라멘트의 수축, 적층 될 때의 오차. 이 모든 변수를 '허용오차(Tolerance)'라는 개념으로 받아들여야 했습니다. 저는 스냅핏(Snap-fit) 구조를 설계하면서 "혹시 모르니 여유를 주자"며 넉넉하게 간격을 뒀습니다.
결과는 처참했습니다. '딸깍'하고 기분 좋게 맞물려야 할 케이스는 헐거워서 덜그럭거렸습니다. 반면 ESP32 보드가 들어갈 자리는 너무 빡빡해서 보드가 휘어질 지경이었습니다.

소프트웨어는 배포 후에 버그가 발견되면 핫픽스(Hotfix)를 내보내면 그만입니다. 롤백(Rollback)도 쉽습니다. 하지만 하드웨어는 한번 출력하면 끝입니다. 되돌리기엔 시간과 재료라는 매몰 비용(Sunk Cost)이 발생합니다.
결국 저는 헐거운 케이스를 고정하기 위해 투명 테이프를 잘라 붙였습니다. 수백 줄의 최적화된 코드, 커널 로그를 파싱하는 정교한 로직, mDNS를 통한 우아한 네트워킹. 그 모든 기술의 결정체가 결국은 문방구표 투명 테이프에 의존해 문에 매달려 있는 꼴이라니.
제 '오버 엔지니어링'의 끝은 초라했습니다. 하지만 그 투명 테이프를 볼 때마다 저는 겸손을 배웁니다. 모니터 안의 논리가 현실 세계의 물리 법칙을 이길 수는 없다는 사실을요. 그리고 완벽한 설계보다 중요한 건, 어쨌든 '돌아가는(Working)' 결과물을 만들어내는 것임을 뼈저리게 느꼈습니다.
지금도 그 장치는 제 방문 앞에 붙어 있습니다. 물론, 테이프는 시간이 지나 누렇게 변해가고 있습니다. 가끔 어머니가 그 장치를 무시하고 들어와 "밥 먹어라" 하실 때면, TCO(총 소유 비용) 측면에서 이 프로젝트가 과연 이득이었는지 다시 계산기를 두드려보게 됩니다.
완벽하지 않아도 괜찮습니다. 엔지니어링의 본질은 우아한 코드가 아니라, 문제를 해결하는 그 과정 자체에 있으니까요. 비록 마무리가 테이프일지라도 말입니다.


