[vibe coding]Port Manager Desktop을 바이브 코딩으로 만든 이야기
https://github.com/katanazero86/port-manager-desktop
[vibe coding]Port Manager Desktop을 바이브 코딩으로 만든 이야기
https://github.com/katanazero86/port-manager-desktop
개발하다 보면 꼭 한 번씩 이런 순간이 찾아옵니다.
“지금 내 맥이나 윈도우에서 어떤 포트가 열려 있는지, 누가 잡고 있는지, 바로 죽일 수 있으면 좋겠는데?”
lsof, netstat, taskkill, kill -9를 번갈아 쓰는 건 익숙하지만, 매번 명령어를 떠올리고 결과를 읽는 과정은 생각보다 피로합니다. 특히 여러 프로젝트를 동시에 띄우는 개발 환경이라면 더 그렇죠.
그래서 이번에는 그 불편함을 줄이기 위해 작은 데스크톱 앱을 하나 만들었습니다. 이름은 Port Manager Desktop입니다.
그런데 이 프로젝트에서 더 흥미로웠던 건 결과물 자체보다, 그것을 만들어 가는 방식이었어요. 이번 작업은 전형적인 “정교한 설계 후 구현”보다는, 아이디어를 빠르게 붙이고 다듬어 가는 바이브 코딩(Vibe Coding) 에 가까웠습니다.
이 글은 그 과정을 정리한 기록입니다.
왜 이 앱을 만들었나
제가 원했던 건 복잡한 네트워크 분석 도구가 아니었어요. 개발자가 자주 필요한 만큼만, 빠르게 볼 수 있는 포트 관리자였습니다.
필요했던 기능은 단순했어요.
- 현재 열려 있는 TCP, UDP 포트 보기
- 어떤 PID와 프로세스가 점유 중인지 확인
- 특정 포트를 점유하는 프로세스 종료
- Node, Python, Java, Docker 같은 개발용 프로세스 빠른 정리
- 관리자 권한 상태 확인
- macOS와 Windows에서 모두 동작
한마디로 “운영툴”보다는 “개발자용 데스크톱 유틸리티” 에 가까운 성격이었습니다.
왜 바이브 코딩이 잘 맞았나
이 프로젝트는 명확한 기획 문서에서 출발하지 않았습니다. 오히려 작업하면서 필요한 흐름이 계속 보였어요.
처음엔 “포트 목록만 보이게 하자”에서 시작했는데, 실제로 써보니 금방 이런 생각이 따라왔습니다.
- 검색은 있어야겠다
- 개발 포트만 빠르게 걸러보면 좋겠다
- 포트를 하나씩 죽이는 것보다 Quick Kill이 더 편하겠다
- 관리자 권한 상태가 보여야 사용자가 덜 헷갈리겠다
- macOS와 Windows는 수집 방식이 다르니 서비스 레이어를 나눠야겠다
기능이 기획서에서 내려온 게 아니라, 사용 장면을 상상하면서 자연스럽게 붙었습니다. 이게 이번 프로젝트에서 말하는 바이브 코딩의 핵심이었어요.
바이브 코딩은 무계획하게 만든다는 뜻이 아닙니다.
오히려 작은 단위로 빠르게 만들고, 바로 확인하고, 계속 조정하는 방식에 가깝습니다. 어느 날 아침 일어나자마자 “아, 이런 도구 있으면 좋겠는데”라는 생각 하나로 시작해서, 그날 바로 코드를 열었어요. 문제 자체가 작고 선명했고, 피드백 루프도 짧았기 때문에 이 방식과 특히 잘 맞았습니다.
기술 스택
Electron, React, Vite, Tailwind CSS, i18next, Node.js(child_process)
Electron을 선택한 이유는 분명했어요. macOS와 Windows에서 동일한 UI를 유지하면서, lsof나 netstat 같은 시스템 명령어를 직접 호출해야 했기 때문입니다.
렌더러는 React로 구성했고, Vite를 붙여 개발 서버와 HMR(Hot Module Replacement) 속도를 최대한 가볍게 가져갔습니다. 스타일은 Tailwind CSS로 빠르게 잡았고, 한국어·영어 전환은 i18next로 처리했습니다.
구조적으로는 크게 세 부분으로 나뉩니다.
- Electron main process — IPC 요청을 받아 OS 명령 실행
- preload bridge — 필요한 기능만 renderer에 안전하게 노출
- React renderer — UI 렌더링과 상태 관리에 집중
이 정도 분리만 해도, 적어도 이번 같은 작은 유틸리티 앱에서는 충분히 안정적으로 느껴졌습니다.
실행 흐름
개발 모드에서 앱이 실행되는 흐름은 이렇습니다.
npm run dev를 실행한다.- Vite 개발 서버가
127.0.0.1:5173에서 렌더러를 띄운다. - Electron이 해당 URL을 로드한다.
- React 앱이
window.portManager.listPorts()를 호출한다. - Electron main process가 포트 수집 서비스를 실행한다.
- macOS →
lsof+ps기반 파싱 - Windows →
netstat+ PowerShell 기반 파싱
- 결과를 renderer로 돌려주고, 사용자는 목록 조회 / 검색 / 종료를 수행한다.
복잡한 아키텍처는 아니지만, “포트를 보고 관리한다”는 목적에는 충분했습니다.
처음 써본 Electron
사실 이번에 Electron을 처음 써봤습니다.
막연하게 “어렵지 않을까?”라고 생각했는데, 실제로 시작해보니 생각보다 진입 장벽이 낮았어요. 핵심 개념만 이해하면 웹 개발 경험이 그대로 연결되거든요.(물론 Codex가 엄청 잘 작성을 해주기도 했지만요.)
Electron을 한 줄로 설명하면, Chromium(브라우저 엔진) + Node.js를 하나의 데스크톱 앱으로 묶어주는 프레임워크입니다. 즉, HTML/CSS/JS로 UI를 만들고, Node.js로 파일 시스템이나 시스템 명령어 같은 OS 기능을 직접 다룰 수 있어요. VS Code나 Figma, Slack 등 Electron으로 만들어져 있습니다.
구조적으로는 두 개의 프로세스가 분리되어 있어요.
- Main process — Node.js 환경. OS 명령 실행, 파일 접근, 창 관리 등 실제 시스템 작업을 담당합니다.
- Renderer process — Chromium 환경. React 같은 웹 기술로 UI를 그립니다.
이 둘은 직접 함수를 호출하듯 통신할 수 없고, IPC(Inter-Process Communication) 라는 메시지 방식으로 주고받습니다. 처음엔 왜 이렇게 복잡하게 나눠놨나 싶었는데, 보안 때문이에요. renderer가 OS에 직접 접근하면 위험하니까, main이 중간에서 검문하는 구조입니다.
그리고 그 사이를 연결하는 게 preload 스크립트입니다. renderer에 노출할 기능만 골라서 안전하게 내려주는 역할이에요. 이번 앱에서는 window.portManager.listPorts() 같은 API를 여기서 정의했습니다.
// preload
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("portManager", {
listPorts: () => ipcRenderer.invoke("ports:list"),
killProcess: (pid) => ipcRenderer.invoke("ports:kill", pid),
runQuickKill: (presetKey) => ipcRenderer.invoke("quick-kill:run", presetKey),
getAdminStatus: () => ipcRenderer.invoke("admin:status"),
requestElevation: () => ipcRenderer.invoke("admin:elevate")
});
처음엔 이 세 레이어가 낯설었지만, 한 번 흐름을 잡고 나니 오히려 역할이 명확하게 나뉘어서 편했어요. 웹 개발에서 프론트엔드와 백엔드를 나누는 감각이랑 비슷하다고 생각하면 꽤 자연스럽게 느껴집니다.
구현하면서 재밌었던 지점
이런 유틸리티 앱은 화면보다 시스템 차이에서 진짜 난이도가 나옵니다.
예를 들어 Windows에서는 netstat 기반으로 비교적 익숙하게 포트를 가져올 수 있었지만, macOS에서는 lsof 출력 포맷과 권한 이슈를 더 섬세하게 다뤄야 했어요. 실제로 개발 중에 "분명 포트는 열려 있는데 앱에는 안 보이는" 상황이 있었는데, 원인을 추적해 보니 macOS용 lsof 파싱 과정에서 주소 필드를 잘못 읽고 있던 문제였습니다.
이 경험이 재밌었던 이유는, 단순히 코드를 짜는 것보다 앱이 각 운영체제의 현실과 맞물리는 방식을 직접 확인할 수 있었기 때문이에요.
또 하나 인상적이었던 건 권한 문제였습니다. 개발자는 포트를 보고 프로세스를 죽이는 걸 당연하게 여기기 쉽지만, 운영체제는 그렇게 쉽게 허용하지 않아요. 그래서 이 앱에는 관리자 권한 상태를 표시하고, 필요할 경우 권한 상승을 요청하는 흐름도 넣었습니다. 기능이 안 되는 것처럼 보이는 순간, 사실은 권한 부족인 경우가 많으니까요.
바이브 코딩의 장점
이번 프로젝트에서 바이브 코딩이 특히 좋았던 점은 세 가지였어요.
첫째, 시작 비용이 낮았습니다. 처음부터 모든 걸 완벽히 정의하지 않아도, 가장 작은 기능부터 바로 만들 수 있었어요.
둘째, 피드백이 빨랐습니다. Electron + Vite 조합 덕분에 수정 후 확인까지의 시간이 짧아서, 화면과 기능을 빠르게 다듬을 수 있었습니다.
셋째, 도구의 성격과 잘 맞았습니다. 이 앱은 거대한 도메인 모델이 필요한 서비스가 아니라, 문제를 빠르게 해결하는 데 집중한 로컬 유틸리티입니다. 이런 성격의 프로젝트는 바이브 코딩과 궁합이 좋아요.
바이브 코딩의 한계도 분명했다
물론 장점만 있었던 건 아닙니다.
바이브 코딩은 흐름이 좋을 때 엄청 빠르지만, 구조를 의식적으로 정리하지 않으면 코드가 금방 퍼질 수 있어요. 특히 OS별 분기, IPC 이벤트, 권한 처리, 프로세스 파싱 로직이 섞이기 시작하면 작은 앱도 금방 복잡해집니다.
그래서 이번에는 몇 가지 원칙을 의식적으로 지키려 했어요.
- OS별 포트 조회 로직은 서비스 레이어에 모으기
- renderer는 IPC 호출과 UI 상태에 집중시키기
- preload에서 필요한 API만 노출하기
- 기능 추가보다 먼저 흐름을 단순하게 유지하기
바이브 코딩은 즉흥적일 수 있어도, 무질서하면 오래 못 갑니다. 빠르게 만들수록 작은 경계를 잘 나눠야 한다는 걸 다시 느꼈어요.
결과적으로 얻은 것
Port Manager Desktop은 거창한 제품이 아닙니다. 그냥 개발하다가 불편해서 만든 작은 도구예요.
그래도 직접 쓰다 보니, 만들길 잘했다는 생각이 듭니다.
마무리
아침에 일어나자마자 떠오른 아이디어 하나로 시작한 프로젝트였습니다. 거창한 계획 없이, 그냥 만들고 싶어서 만들었어요.
그게 바이브 코딩과 잘 맞았고, 생각보다 빠르게 손에 잡히는 결과물이 나왔습니다.
이번 프로젝트를 하면서 느낀 건, AI를 활용한 코딩이 단순히 빠르다는 것 이상이라는 점이에요. 막히는 지점을 바로 뚫어주고, 아이디어를 검증하는 속도 자체가 달라집니다. 앞으로는 이 흐름을 좀 더 의식적으로, 잘 쓰고 싶다는 생각이 들었어요.

메타데이터
- post_id
- 0c2ede171f7e
- slug
- port-manager-desktop을-바이브-코딩으로-만든-이야기-0c2ede171f7e
- url
- https://medium.com/@zero86/port-manager-desktop%EC%9D%84-%EB%B0%94%EC%9D%B4%EB%B8%8C-%EC%BD%94%EB%94%A9%EC%9C%BC%EB%A1%9C-%EB%A7%8C%EB%93%A0-%EC%9D%B4%EC%95%BC%EA%B8%B0-0c2ede171f7e
- canonical_url
- https://medium.com/@zero86/port-manager-desktop%EC%9D%84-%EB%B0%94%EC%9D%B4%EB%B8%8C-%EC%BD%94%EB%94%A9%EC%9C%BC%EB%A1%9C-%EB%A7%8C%EB%93%A0-%EC%9D%B4%EC%95%BC%EA%B8%B0-0c2ede171f7e
- author_url
- https://medium.com/@zero86
- status
- ok
- fetched_at
- 2026-06-12 07:40:50