본문으로 건너뛰기
피드

윈도우 95 시절 쉘 API로 만든 명령줄 도구, WinUtils 회고

open-source 약 6분
vote
0
댓글
북마크

글쓴이가 1996~1997년에 만든 WinUtils는 윈도우 95의 쉘 API를 감싼 얇은 명령줄 도구 모음이었다. 직접 파일 입출력을 구현하는 대신 탐색기와 같은 복사, 이동, 삭제, 휴지통, 확인창 동작을 그대로 활용한 점이 핵심이다.

  • 1

    WinUtils는 SHFileOperation을 호출해 복사, 이동, 삭제, 이름 변경을 처리했다

  • 2

    휴지통 기반 되돌리기는 FOF_ALLOWUNDO 플래그 덕분에 가능했다

  • 3

    도움말 파일은 RTF, HPJ, CNT, Help Compiler를 거쳐 만드는 꽤 번거로운 작업이었다

  • 4

    글쓴이는 비효율적인 시행착오가 오히려 오래 남는 학습 경험이었다고 회고한다

  • WinUtils는 1996~1997년쯤 글쓴이가 윈도우 95 쉘 API를 공부하면서 만든 명령줄 도구 모음임

    • 목표는 직접 파일 입출력을 구현하는 게 아니라, 윈도우 쉘이 이미 제공하는 파일 작업 함수를 명령줄에서 부르는 것이었음
    • 덕분에 탐색기에서 보던 확인창, 진행창, 휴지통 동작을 거의 그대로 가져올 수 있었음
  • 핵심은 “내가 다 만들지 않고 운영체제가 잘하는 걸 얇게 감싼다”는 설계였음

    • SHFileOperation이 복사, 이동, 삭제, 이름 변경의 중심 API였음
    • SHFILEOPSTRUCT로 원본과 대상 경로, 플래그를 넘겼음
    • FO_COPY, FO_DELETE, FO_MOVE, FO_RENAME 같은 작업 코드가 각 유틸리티에 대응됨
    • SHGetFileInfo는 탐색기와 맞는 아이콘이나 표시 이름을 가져올 때 썼음

💡

> 작은 도구라도 운영체제 기본 동작에 올라타면 사용자가 기대하는 안전장치와 사용자 경험을 같이 얻을 수 있음.

  • 가장 실용적인 장점은 되돌리기였음

    • windel로 지운 파일은 FOF_ALLOWUNDO 플래그 덕분에 휴지통으로 들어감
    • winmove를 잘못 실행해도 탐색기에서 일반 파일 작업처럼 되돌릴 수 있었음
    • 명령줄 도구인데도 윈도우 사용자에게 익숙한 안전망을 제공했다는 게 꽤 맛있는 포인트임
  • 도구 구성은 단순했지만 스위치는 쉘 플래그와 거의 1대1로 이어졌음

    • wincopy와 winmove는 원본과 대상, 그리고 여러 단일 문자 스위치를 받음
    • windel은 삭제 도구라 충돌 이름 변경 스위치가 빠짐
    • winren은 이름 변경에 필요한 /a, /h, /r, /u 정도만 남김
    • /n은 확인 없이 진행, /r은 충돌 시 이름 변경, /s는 진행창 없이 조용히 실행, /u는 휴지통 기반 되돌리기를 의미함
  • 당시에는 실행 파일에 커스텀 아이콘을 붙이는 것만으로도 프로젝트가 완성된 느낌이었다고 함

    • 글쓴이는 기존 윈도우 아이콘 조각을 편집기로 이어 붙여 각 유틸리티 아이콘을 만들었음
    • 완전히 독창적인 아트는 아니었지만, 각 실행 파일에 정체성을 부여하는 작업이었음
  • 도움말 파일 만들기는 작은 유틸리티치고 꽤 빡센 별도 프로젝트였음

    • /h 스위치는 winutils.hlp를 열었음
    • 당시 윈도우 도움말은 RTF로 토픽을 쓰고, HPJ 프로젝트 파일과 CNT 목차 파일을 만들고, Help Compiler로 HLP 바이너리를 생성해야 했음
    • 교차 참조와 팝업 정의는 RTF 안의 각주 코드로 달았고, 잘못 맞추면 엉뚱한 도움말 토픽이 열리기도 했음
  • 배포도 지금과 완전히 다른 세계였음

    • 앱스토어, 깃허브 릴리스, 패키지 배포 같은 건 없었음
    • 실행 파일과 도움말을 압축해서 Tucows, Download.com, WinSite, ZDNet 같은 셰어웨어 사이트에 올리는 식이었음
    • 피드백은 각 사이트에 다시 접속해서 다운로드 카운터가 올라갔는지 보는 정도였고, 그 숫자 하나가 꽤 큰 보상이었다고 함
  • 글쓴이는 지금이라면 대규모 언어 모델(LLM)이 WinUtils 전체를 몇 분 만에 재현할 수 있을 거라고 인정함

    • 소스, 스위치, 도움말, 아이콘까지 자동으로 만들 수 있는 시대라는 것
    • 하지만 당시의 비효율적인 고생, 종이 문서로 API를 읽고 플래그를 추측하고 도움말 컴파일러와 싸우던 경험이 진짜 학습이었다고 말함
    • 결론은 살짝 아재 개발 회고인데, 꽤 공감됨. 빨리 만드는 것과 몸에 남는 것은 다른 문제임

기술 맥락

  • WinUtils의 선택은 파일 작업을 직접 구현하지 않고 윈도우 쉘 API를 호출하는 거였어요. 복사와 삭제를 직접 짜면 예외 처리가 많아지는데, 쉘을 타면 탐색기와 같은 확인창, 진행창, 휴지통 동작을 그대로 얻을 수 있거든요.

  • 특히 FOF_ALLOWUNDO가 중요한 이유는 명령줄 도구에 되돌리기 감각을 넣어줬기 때문이에요. 일반적인 삭제 명령은 실수하면 끝이라는 느낌이 강한데, 이 방식은 사용자가 탐색기에서 복구할 수 있는 여지를 남겨요.

  • 도움말 시스템도 당시 윈도우 앱 배포의 일부였어요. RTF와 HPJ, CNT를 맞춰 컴파일해야 했기 때문에 지금의 README 하나보다 훨씬 번거로웠고, 작은 도구라도 문서화와 배포 포맷을 신경 써야 했어요.

  • 이 글이 지금도 재미있는 건 자동화가 낮춘 진입장벽과 직접 부딪히며 얻는 이해를 같이 보여주기 때문이에요. 대규모 언어 모델이 코드를 빨리 만들어줘도, 운영체제 API가 왜 그런 모양인지 이해하는 경험은 여전히 따로 필요해요.

요즘이라면 대규모 언어 모델이 몇 분 만에 비슷한 코드를 뽑아낼 수 있겠지만, 이 글의 재미는 ‘고생이 학습의 일부였다’는 대목이다. 얇은 래퍼라도 운영체제의 사용자 경험을 존중하면 꽤 쓸모 있는 도구가 된다는 교훈도 있다.

댓글

댓글

댓글을 불러오는 중...

open-source

러스트로 다시 만든 로컬 코딩 에이전트 ‘파이’, 자동화까지 노린다

파이는 기존 pi 코딩 에이전트를 러스트로 다시 만든 터미널 기반 AI 코딩 에이전트다. 프로젝트 안에서 파일을 읽고 수정하고, 셸 명령을 실행하고, 세션을 이어가며, 로컬 모델과 여러 모델 제공자를 쓸 수 있다. 단순 채팅 UI가 아니라 트리거, 크론, MCP 알림, 에이전트 간 허브 메시징까지 넣은 로컬 에이전트 런타임을 지향한다.

open-source

Paseo, 여러 코딩 에이전트를 한 화면에서 돌리는 오픈소스 인터페이스 공개

Paseo는 Claude Code, Codex, Copilot, OpenCode, Pi 같은 코딩 에이전트를 한 인터페이스에서 실행하고 관리하는 오픈소스 도구다. 로컬 daemon이 에이전트 프로세스를 관리하고, 데스크톱·모바일·웹·CLI 클라이언트가 여기에 연결되는 구조라 자기 개발 환경 위에서 병렬 작업을 돌릴 수 있다.

open-source

줄리아 반응형 노트북 Pluto가 6년 만에 1.0을 찍었다

줄리아용 반응형 노트북 환경 Pluto.jl이 6년 개발 끝에 1.0을 공개했다. 이번 1.0 자체는 제거된 deprecated 기능 정도로 조용하지만, 재현성, 공유, 반응형 실행, 교육용 기능, 접근성, 편집기 도구까지 지난 몇 년의 누적 개선을 정리한 릴리스에 가깝다.

open-source

리눅스에서 놀고 있는 엔비디아 VRAM을 스왑 공간으로 쓰는 오픈소스 프로젝트

하이브리드 그래픽 노트북에서 유휴 엔비디아 GPU의 VRAM을 리눅스 스왑 공간으로 활용하는 프로젝트가 공개됐다. CUDA 드라이버 API로 VRAM을 할당하고, 이를 NBD 블록 디바이스로 노출해 일반 스왑처럼 쓰는 방식이다. 순차 처리량은 NVMe보다 느리지만, 드문드문 발생하는 스왑 접근에서는 평균 지연 시간이 335마이크로초로 NVMe의 9.05밀리초보다 27배 빠르다는 결과가 흥미롭다.

open-source

괄호가 싫어도 한 번은 봐야 할 작은 리스프, 재닛

글쓴이는 취미 프로젝트용 언어로 작은 리스프 계열 언어인 재닛을 몇 년째 쓰고 있고, 무료 책까지 쓸 정도로 꽂혔다. 핵심은 문법 장난이 아니라 작은 런타임, 네이티브 실행 파일 배포, 파싱 표현 문법, 셸 스크립팅, 매크로, 컴파일 타임 실행이 한데 묶인 실용성이다.