
창고 바닥에서 Microsoft Store까지 - PC Workman Marcin Firmuga
요약
열악한 환경에서 개발한 Windows 모니터링 소프트웨어 'PC Workman'이 Microsoft Store에 정식 출시된 과정을 담은 회고록입니다. 개인적인 역경과 기술적 도전, 그리고 실제 제품으로 완성해가는 개발자의 여정을 보여줍니다.
핵심 포인트
- 저사양 노트북 환경에서의 극한 개발 경험
- 개인 프로젝트를 Microsoft Store 정식 제품으로 출시
- 시스템 모니터링 및 AI 어시스턴트 기능 포함
- 개발 과정에서의 심리적 회복과 기술적 성취
원문은 pcworkman.dev에 처음 게시되었습니다.
저를 고용하세요! - LinkedIn :)
저렴한 노트북이 포기하기 직전에 도달하는 온도가 있습니다. 제 노트북은 94°C에 도달합니다. 팬들이 비명을 지릅니다.
작년 대부분의 시간 동안, 그 비명 소리는 제 밤의 배경음악이었습니다.
저는 열정 때문에 그 밤들을 지새우며 코딩한 것이 아닙니다.
제가 움직임을 멈추면 사라져 버릴 것 같다는 두려움 때문에 코딩했습니다.
이 프로젝트 이전의 죽은 12개의 프로젝트들이 사라졌던 것과 똑같이 조용하게, 그리고 제가 스물두 살 때 거의 그랬던 것과 똑같이 조용하게 말입니다.
오늘 아침, 그 두려움은 제가 상상할 수 있는 가장 기묘한 답변을 얻었습니다.
그 비명을 지르는 노트북으로, 혼자서, 교대 근무 시간 사이에, 부서져 가며 만든 Windows 모니터인 PC Workman이 Microsoft Store에 출시되었습니다.
이것은 어떤 포럼에 올라온 ZIP 파일도 아니고, 클론(clone)해야 하는 리포지토리(repo)도 아닙니다.
이것은 제가 자라면서 오직 기업들만이 만들 수 있다고 생각했던 소프트웨어와 같은 스토어에 등록된 실제 제품입니다.
바코드 스캐너가 어떻게 그곳에 가게 되었는지 말씀드리겠습니다. 좋은 부분과 절박했던 부분들을 모두 보여드릴 것이며, 실제 코드도 보여드리겠습니다. 왜냐하면 코드는 그 두 가지가 모두 맞닿아 있는 지점이기 때문입니다.

PC Workman 1.8.0. 모든 기능이 라이브 상태이며, 실제로 설명해 주는 AI가 포함되어 있습니다.
당신이 선을 넘는 것을 결코 보지 못하는 숫자
제가 열일곱 살 때 아버지가 돌아가셨습니다.
저는 그 주에 무너지지 않았습니다. 저는 2~3년에 걸쳐 서서히 무너졌고, 그것이 아무도 경고해주지 않는 부분입니다. 어떤 순간이 있는 것이 아닙니다. 자신이 선을 넘고 있다는 것을 깨닫는 지점도 없습니다.
그것은 전원 레일 (power rail)이 처지는 것과 같습니다. 12볼트가 11.9가 되고, 그다음엔 11.8가 됩니다. 모든 측정값이 여전히 "사양 범위 내 (within spec)"에 있기 때문에 아무런 경고도 울리지 않습니다. 그러다 어느 날 숫자를 확인해보면 단순히 잘못되어 있고, 그것이 언제 일어났는지 말할 수 없게 됩니다. 22일쯤이었을 겁니다, 제가 그랬습니다. 거의 모든 사람이 그러하듯, 저는 조용히 자신을 포기했습니다.
그 레일을 기억하세요. 그것은 나중에 코드 (code) 속에서 다시 나타납니다. 문자 그대로의 의미입니다.
창고
네덜란드의 한 창고에서 보낸 9개월. 하루에 15km를 걷고, 바코드를 스캔하며, 공제 후 시급 15즈워티(złoty)가 된 19즈워티를 받았습니다.
그걸 3.5유로라고 합시다.
한번은 휴식 시간에 계산을 해보았습니다:
9시간 풀 근무를 하면 제가 꿈꾸던 가장 저렴한 서버 호스팅 (server hosting) 한 달 치를 살 수 있었지만, 저는 결코 그것을 빌리지 않았습니다. 저 자신을 위한 임대료가 우선이었기 때문입니다.
리듬은 고정되어 있었습니다. 아침부터 저녁까지의 교대 근무, 팬(pan)에 조리한 저녁 식사, 그러고 나서 밤에는 무언가를 두 번 연속으로 컴파일 (compile)하기만 해도 열로 인해 스로틀링 (thermal throttling)이 걸리는 2014년형 노트북으로 6시간을 보냈습니다.
사람들은 프로젝트가 얼마나 걸렸냐고 묻지만, 정직한 단위는 '개월'이 아닙니다.
그것은 '밤'입니다.
그러다 크리스마스 사흘 전, 몇 주 동안 저에게 미소 지어주던 바로 그 사람들이 다시 미소 지으며 말했습니다:
"수습 기간을 통과하지 못했습니다. 내일은 작별입니다. 그리고 아파트에서도 나가세요."
12월 22일. 문장을 다 이해하기도 전에 문 앞에는 여행 가방들이 놓여 있었습니다. 다른 나라에는 두 마리의 개가 저를 기다리고 있었고, 저에게 남은 돈은 아마 한 달 치 정도였습니다.

12월 22일. 크리스마스 사흘 전, 제 모국어도 아닌 언어로 복도에 서서 제가 테러리스트가 아니라고 소리쳤습니다. 긴 이야기입니다. 다른 포스트에서 다루겠습니다.
그날 밤 저는 구직 사이트를 열지도 않았고, 똑같이 생긴 백 번째 이력서를 쓰지도 않았습니다. 대신 에디터를 열고 모니터의 네 번째 재구축 작업을 시작했습니다. 3주 후, 저는 첫 번째 .exe 파일을 출시했습니다.
그전까지 열두 개의 프로젝트가 실패했습니다.
저는 이것이 실패를 거부할 바로 그 프로젝트가 될 줄은 아직 알지 못했습니다.
그해 제가 가진 가장 진실된 문장: 무언가를 만들고, 무언가를 커밋(commit)하고, 진행 표시줄(progress bar)이 움직이는 것을 지켜보며, 자신이 존재한다고 느끼는 것. 아무도 그것을 벽에 액자로 걸어두지는 않습니다. 그해 그것은 생존이었습니다.
제가 실제로 만든 것
PC Workman은 다른 모니터들이 회피하는 질문에 답합니다:
당신의 PC가 느린지 아닌지가 아니라(그건 이미 알고 있으니까요), '왜' 느린지에 대해서 말이죠.
당신은 완전히 로컬 머신(machine)에서 실행되는 어시스턴트인 hck_GPT를 통해 일상적인 언어로 질문할 수 있습니다. 내부 구조는 하이브리드 방식입니다:
90개의 의도(intents)를 가진 규칙 엔진(rule engine)과 다층 라우터(multi-layer router), 그리고 개방형 질문을 위한 선택적 로컬 모델(local model)로 구성됩니다.
클라우드도, API 키도 없으며, 당신이 입력하는 그 어떤 것도 컴퓨터를 떠나지 않습니다.
라우팅 과정은 화려하지 않으며, 이는 의도된 것입니다.
메시지는 토큰화(tokenized)되고, 악센트 폴딩(accent-folded, 폴란드 사용자는
저는 단 하루 만에도 pip install openai를 출시할 수 있었습니다.
하지만 그렇게 하지 않기로 결정했으며, 이는 기술적인 결정이 아닌 제품(product) 차원의 결정이었습니다.
사용자의 기기를 읽어 들인 다음, 그 내용을 설명하기 위해 낯선 서버로 전화를 거는 모니터링 도구는 모순입니다. 따라서 전체 지능 계층(intelligence layer)은 차트를 그리는 것과 동일한 프로세스 내에서 실행되며, 개인정보 보호 페이지에는 변호사 대신 단 한 문장만 있으면 됩니다.

hck_GPT. 인터넷 없음, 키(key) 없음, 어디로도 아무것도 전송되지 않음. 사용자의 실시간 기기를 읽고 평이한 언어로 답변합니다.
기억력을 가진 모니터
제가 실제로 잠을 설치며 고민하는 부분은 메모리(memory)입니다.
지구상의 모든 모니터링 도구는 사용자가 창을 닫는 순간 사용자를 잊어버립니다. HWiNFO, Afterburner: 내일 그것들을 다시 열면, 이전에 존재했던 모든 기기에 대해 그렸던 것과 정확히 똑같은 선 위에 당신의 78°C를 그려낼 것입니다.
모니터링 도구가 제공할 수 있는 가장 유용한 수치는 온도가 아닙니다.
그것은 바로 지금 이 온도가 당신에게, 그리고 당신의 기기에서, _지금 당신이 하고 있는 작업_에 비추어 볼 때 정상인지 여부입니다.
따라서 모든 측정값은 다섯 가지 워크로드(workload) 버킷 중 하나에 할당됩니다:
idle(유휴), light(가벼움), medium(중간), heavy(무거움), gaming(게이밍).
각 버킷은 Welford 누산기(Welford accumulator)를 통해 앞으로 접어두어(folded forward) 학습된 고유의 정상 범위를 유지합니다. 버킷당 세 개의 숫자가 포함되며, 이는 상수 시간(constant time) 내에 업데이트되고 처음부터 다시 계산되지 않습니다:
def _welford_add(acc, x):
"""하나의 샘플을 실행 중인 누산기에 접어 넣습니다 (Welford, 1962)."""
n = acc["n"] + 1
...
그 보상은 단순한 수치가 아닌 판결입니다. 똑같은 82°C라도 게임 세션 중에는 괜찮지만, 유휴 (idle) 상태의 데스크톱에서는 경고 신호가 됩니다.
같은 숫자이지만 의미는 정반대이며, 그 차이는 전적으로 학습된 이력 (history)에 달려 있습니다.
제 개인 기기에서 12일 동안 측정한 결과, 유휴 (idle) 버킷은 613개의 샘플로 보정되었고 게임 버킷은 115개의 샘플로 학습되었습니다. 따라서 무언가가 저의 정상 범위를 14% 초과하면, 앱은 정확히 그렇게 말할 수 있습니다.
프로젝트에서 가장 오래된 수학
전압은 제 부모님보다 더 오래된 통계치를 가집니다. 각 레일 (rail)에 대해 분석기 (analyzer)는 중앙값 (median)과 MAD (median absolute deviation, 중앙값 절대 편차)를 학습한 다음, 수정된 z-점수 (modified z-score)를 사용하여 모든 새로운 샘플을 판단합니다.
이것은 스케치(sketch)가 아닌 voltage_analyzer.py의 실제 코드입니다:
def modified_z(self, value: float) -> float:
"""Modified z-score: M = 0.6745 * (x - median) / MAD.
MAD가 사실상 0인 경우 (상수 신호) 0.0을 반환합니다."""
...
그 위에 1984년의 넬슨 규칙 (Nelson rules)이 얹혀 있습니다: 중앙값의 같은 쪽에 9개의 점이 있거나, 한 방향으로 6개의 점이 추세(trending)를 보이는 경우입니다.
이 규칙들은 임계값 (threshold)이 절대 잡아낼 수 없는 단 한 가지를 포착하기 위해 존재합니다:
바로 느린 전압 강하 (slow sag)입니다. 몇 주에 걸쳐 12.05V에서 11.88V로 서서히 변하는 레일은 개별 측정값은 모두 허용 범위 내에 있기 때문에 한계치 (limit)를 넘지 않습니다. 하지만 그 패턴 자체가 경보가 됩니다.
이제 아까 말한 그 레일에 대해 이야기해 보죠. 3년 동안 사양 (spec) 범위 내에서 서서히 전압이 떨어졌던 것은 바로 저였습니다. 저를 포함한 모든 사람이 아무 문제 없다고 장담하는 동안 말이죠.
저는 제가 갖지 못했던 그 경보 장치를 직접 만들었습니다. 그것은 전원 공급 장치 (power supply)를 돌보는 60년대의 통계학이며, 지루하고 예측 가능합니다. 그리고 바로 그 점 때문에 저는 그것을 신뢰합니다. 통계는 절대 환각 (hallucinate)을 일으키지 않습니다. 사람은 일으키죠.
사람들은 저를 똑바로 쳐다보며 시간당 3.5유로를 주면서 임금이 오를 것이라고 말했습니다. 하지만 결코 오르지 않았습니다. 적어도 수학은 저에게 거짓말을 하지 않았습니다.
릴리스로 측정된 1년
여러분은 고된 작업 과정을 보지 못합니다. 여러분은 버전 번호만을 봅니다.
여기 영수증이 있습니다. 처음에는 그래프조차 겨우 그릴 수 있는 프로토타입 (prototype)으로 시작했습니다. 그다음은 첫 번째 안정적인 .exe 파일이었습니다.
그다음은 분 단위에서 월 단위로 집계하는 SQLite 통계 엔진 (stats engine)이었습니다.
그다음은 하이브리드 AI (hybrid AI), 스타트업 매니저 (Startup manager), 서비스 매니저 (Services manager)였습니다.
이 프로젝트가 겪은 가장 큰 품질의 도약이 있었고, 그다음은 스마트 러닝 (Smart Learning)이었습니다. 모니터가 마침내 메모리 (memory)를 갖게 된 릴리스 (release)였습니다.
11번의 릴리스, 800개 이상의 커밋 (commits), 인터페이스의 4번의 완전한 재구축. 그 모든 것들은 교대 근무가 끝난 후, 똑같이 뜨거운 노트북 위에서 작성되었습니다.

요즘 낮에는 용접기 (welding gun)를 잡습니다. 뜨거운 공기로 녹은 플라스틱을 다시 붙입니다. 용접은 학습 엔진 (learning engine)에 필요한 한 가지를 가르쳐 주었습니다. 뜨거운 금속을 보는 눈은 매뉴얼을 통해 얻을 수 없다는 것입니다. 체리 레드 (Cherry red), 스트로 (straw), 그리고 너무 멀리 왔음을 의미하는 블루 (blue). 그것은 축적됩니다. 스스로 터득하는 것입니다.
Microsoft는 안 된다고 했습니다. 그러다 Microsoft는 된다고 했습니다.
2주 전 저는 _"Microsoft는 안 된다고 했습니다."_라는 제목의 글을 게시했습니다.
저의 첫 .msix는 거절당했습니다. 코드 때문이 아니었습니다.
차단 요인은 흐릿한 타일 아이콘 (tile icon)과, 개인정보 처리방침 (privacy-policy) 링크가 대신 보안 정책 (security policy)을 가리키고 있었다는 점이었습니다.
1년간의 전압 이상 (voltage-anomaly) 수학과 오프라인 AI (offline AI) 작업 끝에, 저를 문턱에서 막아선 것은 흐릿한 PNG 파일이었습니다. 검토자는 옳았습니다. 그럼에도 쓰라렸습니다.
그래서 저는 두 가지 모두 수정했습니다. 선명한 아이콘을 그렸고, 개인정보 처리방침이 있어야 할 곳에 위치한 진짜 개인정보 처리방침을 작성했으며, 기다리는 동안 테스터들이 찾아낸 13개의 추가 수정 사항을 포함시켰습니다.
그 후 다시 제출하고 업무로 복귀했습니다. 앱을 다른 창에 열어둔 채 기다린다고 해서 인증 (certification)이 빨라지지는 않기 때문입니다.
오늘 아침 상태가 승인 (approved)으로 변경되었습니다.
"이 두 가지를 수정하고 다시 제출하세요"라고 말하는 거절은 결코 '안 된다'는 뜻이 아니었습니다.
그것은 스토어 (Store)가 제가 얼마나 근접했는지를 알려주는 방식이었습니다.
스토어 (Store)는 또한 여러분의 화면 측면에서도 문제를 해결해 줍니다.
이제 더 이상 낯선 사람이 보낸 ZIP 파일을 신뢰할 필요가 없습니다.
모든 빌드는 Sigstore로 서명되었고, VirusTotal에서 깨끗함이 확인되었으며, 모든 커밋마다 CodeQL에 의해 검사됩니다. 그러한 편집증적인 철저함은 첫 출시부터 프로젝트에 적용되어 있었습니다. 스토어 등록은 단지 이를 가시화할 뿐입니다.
스토어에서의 첫 몇 주가 내게 가르쳐준 것
등록 (Listing)은 약속이며, 약속은 빠르게 시험대에 오릅니다.
며칠 지나지 않아 한 테스터가 프로젝트 역사상 최악의 버그를 발견했습니다: 길고 무거운 세션이 지속될 때 앱이 컴퓨터 전체를 멈추게 할 수 있다는 점이었습니다.
화면은 하얗게 변하고, 데스크톱은 먹통이 되며, 복구하려면 재부팅해야 합니다.
모니터링하는 기계 자체를 멈추게 할 수 있는 모니터는 모니터가 아니기에, 이 문제가 해결될 때까지 다른 모든 작업이 중단되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기