← 기술 블로그 목록으로 돌아가기
#980 • Process Governance & AI Lifecycle

온디바이스 AI 백그라운드 프로세스 라이프사이클: ZeliProc 포트 충돌 진단과 CPython 좀비 프로세스 원천 차단 아키텍처

"프로그램 창을 껐는데 왜 GPU 팬이 계속 돌고 포트(8000, 11434)가 잠겨 있을까?" WMI 부하 없는 2단계 CPU 델타 샘플링, netstat 기반 PID 역추적, CPython JSON-RPC 세션 desync 자동 복구, 그리고 좀비 프로세스를 원천 차단하는 데스크톱 프로세스 거버넌스 백서.

"온디바이스 AI 도구를 사용한 뒤 교사가 가장 흔하게 호소하는 불만은 '컴퓨터가 갑자기 뜨거워지고 다른 프로그램이 안 켜져요'입니다. 창은 닫혔지만 백그라운드에 살아남은 고아(Orphan) 파이썬 프로세스가 GPU VRAM과 로컬 포트(8000, 11434)를 영구 점유하고 있기 때문입니다. 눈에 보이지 않는 백그라운드 프로세스의 라이프사이클을 철저하게 감시하고 통제하는 기술이야말로 안정적인 엔터프라이즈 데스크톱의 필수 조건입니다."

1. 교실과 연구실의 유령 프로세스 재앙: "AI 창을 닫았는데 컴퓨터가 100% 굉음을 냅니다"

학교 컴퓨터실이나 교무실에서 로컬 AI 이미지 생성(ZeliGen), sLM 추론(sLMdown), 오피스 COM 자동화(ZeliOffice)를 사용하다 보면 겪게 되는 전형적인 현상이 있습니다:

컴퓨터에 익숙하지 않은 교사와 공직자는 결국 원인을 찾지 못해 PC 전원 버튼을 길게 눌러 강제 재부팅을 반복하게 됩니다.

2. 고아(Orphan) 및 좀비 프로세스의 구조적 원인: 비정상 종료와 소켓 포트 잠금

이 문제의 근본 원인은 부모 프로세스(UI)와 자식 프로세스(AI/COM 백엔드) 간의 수명주기 불일치에 있습니다:

  1. 파이썬 서브프로세스의 고아화: UI 창이 예기치 않게 닫히거나 강제 종료될 때, Process.Start로 띄워둔 python.exe나 llama-server.exe는 부모의 소멸을 감지하지 못하고 독립적인 백그라운드 프로세스로 잔류합니다.
  2. 소켓 TIME_WAIT 및 바인딩 고착: 백엔드 프로세스가 TCP 루프백 포트(127.0.0.1:8000 등)를 리슨(Listen)하고 있는 상태에서 종료되지 않으면 운영체제는 해당 포트를 잠근 채 유지합니다.
  3. 표준 입출력(Stdio) 파이프 블로킹: 자식 프로세스가 표준 입력(stdin)을 무한 대기(Block)하고 있으면 운영체제의 가비지 컬렉터도 이를 정리할 수 없습니다.

3. WMI 부하를 없앤 2단계 CPU 델타 샘플링: 네이티브 틱 계산과 재진입 가드

많은 시스템 모니터링 도구들이 CPU 사용률을 측정하기 위해 WMI(Win32_PerfFormattedData)를 조회하지만, WMI는 쿼리 한 번에 1~2초가 소요되고 그 자체로 CPU를 15% 이상 소모하는 주객전도의 문제를 낳습니다.

ZeliDesk의 시스템 관리 도구 `ZeliProc`은 WMI를 완전히 배제하고, 순수 .NET 네이티브 틱(Tick)을 이용한 초경량 2단계 CPU 델타 샘플링을 구현했습니다:

C# — ZeliProc 2단계 CPU 델타 샘플링 & 재진입 큐 가드 ZeliProcWindow.xaml.cs
// 재진입(Re-entrancy) 방지 및 최신 요청 보류 큐
if (_isRefreshing) { _pendingRefresh = true; return; }
_isRefreshing = true;

try {
    do {
        _pendingRefresh = false;
        var procs = await Task.Run(async () => {
            var processes = Process.GetProcesses();
            int coreCount = Environment.ProcessorCount;

            // 1단계 샘플: 프로세스별 누적 TotalProcessorTime 캡처
            var firstCpu = new Dictionary<int, TimeSpan>();
            foreach (var proc in processes) {
                try { firstCpu[proc.Id] = proc.TotalProcessorTime; } catch { }
            }

            // 500ms 정밀 델타 구간 대기
            var sw = Stopwatch.StartNew();
            await Task.Delay(500);
            sw.Stop();
            double elapsedMs = sw.Elapsed.TotalMilliseconds;

            // 2단계 샘플: 실제 연산 델타 / (경과시간 * 논리코어수) -> 0~100% 계산
            var list = new List<ProcItem>();
            foreach (var proc in processes) {
                try {
                    double cpu = 0;
                    if (firstCpu.TryGetValue(proc.Id, out var t0)) {
                        double deltaMs = (proc.TotalProcessorTime - t0).TotalMilliseconds;
                        cpu = Math.Clamp(deltaMs / (elapsedMs * coreCount) * 100.0, 0, 100);
                    }
                    list.Add(new ProcItem {
                        Pid = proc.Id, Name = proc.ProcessName,
                        MemoryMB = proc.WorkingSet64 / (1024 * 1024), CpuPercent = cpu
                    });
                } catch { }
            }
            return list;
        });
        _allProcs = procs;
    } while (_pendingRefresh); // 샘플 도중 들어온 새로고침 요청 1회 추가 실행
} finally { _isRefreshing = false; }

이 알고리즘은 전체 시스템 프로세스(200~300개)의 CPU 점유율을 시스템 부하 0.1% 미만으로 완벽하게 실시간 계측하며, 빈번한 새로고침 클릭에도 스레드 풀이 고갈되지 않도록 보류 큐(Pending Queue)로 원활하게 제어합니다.

4. 포트 충돌 원클릭 해소: Netstat 역추적 기반 PID 자동 바인딩 및 정밀 격리

로컬 AI 추론 서버나 웹 서비스가 충돌할 때, 사용자가 명령 프롬프트를 열어 netstat -ano | findstr :8000을 치고 작업 관리자에서 수작업으로 PID를 찾아 종료하는 것은 일반 사용자에게 불가능에 가깝습니다.

ZeliProc은 포트 번호 기반 PID 역추적 엔진을 탑재하여 이 과정을 1초 만에 자동화했습니다:

C# — netstat -ano 출력 비동기 파싱 및 포트 점유 PID 자동 탐색 ZeliProcWindow.xaml.cs
// 1. 포트 번호(예: "8000" 또는 "11434") 입력 시 백그라운드 netstat 조회
var psi = new ProcessStartInfo("netstat", "-ano") {
    RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true
};
using var proc = Process.Start(psi);
string output = await proc.StandardOutput.ReadToEndAsync();
await proc.WaitForExitAsync();

// 2. TCP 리스닝 상태 및 바인딩 PID 정규식/토큰 매칭
foreach (var line in output.Split('\n')) {
    var parts = line.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries);
    if (parts.Length >= 5 && parts[1].EndsWith($":{portStr}")) {
        if (int.TryParse(parts[4], out int matchedPid)) {
            // 3. 해당 프로세스를 프로세스 목록에서 즉시 하이라이트 & 원클릭 종료 다이얼로그 연계
            SelectAndHighlightProcess(matchedPid);
            break;
        }
    }
}

사용자는 포트 번호 8000만 입력하면, 배후에서 포트를 쥐고 있던 python.exe를 즉시 찾아내어 확인 팝업창과 함께 0.1초 만에 안전하게 정리할 수 있습니다.

5. CPython JSON-RPC 세션의 무중단 자가 복구: 파이프 Desync 감지와 원자적 재생성

온디바이스 이미지 생성 엔진 ZeliGen은 매번 파이썬을 새로 띄우는 오버헤드(3~5초)를 없애기 위해 CPython 상주 프로세스와 표준 입출력(JSON-RPC)으로 통신합니다. 그러나 AI 모델 로딩이 5분 이상 걸리거나 예기치 않은 메모리 부족으로 파이썬이 멈추면 파이프 동기화(Desync)가 깨집니다.

장애 상황 일반 래퍼 프로그램의 반응 ZeliDesk AI 런타임 자가 복구 파이프라인
모델 로드 타임아웃 (5분 초과) 무한 로딩 휠, UI 영구 프리징 CancellationTokenSource 만료 즉시 감지 ➔ 프로세스 폐기 및 스트림 리셋
파이프 동기화 깨짐 (Desync) 이전 요청의 응답이 다음 요청과 섞여 파서 크래시 서버 세션 즉시 무효화 ➔ 다음 요청 시 0.5초 클린 재시작(Restart)
부모 윈도우 강제 종료 백그라운드에 2.6GB 점유 파이썬 영구 잔류 윈도우 Closed 이벤트 및 Process.Kill 연쇄 파괴 핸들러 가동
오류 로그 분석 콘솔 창이 숨겨져 있어 원인 파악 불가능 _stderrBuffer 링버퍼(최신 200줄) 자동 저장 ➔ 진단 창 즉시 확인

타임아웃 발생 시 멈춘 서버를 억지로 재사용하지 않고 "고장 난 세션은 즉각 파기하고 다음 호출을 위해 새 프로세스를 깨끗하게 원자적 준비"하는 원칙을 철저히 지킴으로써 연쇄 타임아웃을 원천 봉쇄합니다.

6. 일반 작업 관리자 vs 오픈소스 프로세스 툴 vs ZeliDesk 프로세스 거버넌스 비교

비교 항목 Windows 기본 작업 관리자 Process Explorer (Sysinternals) ZeliDesk (ZeliProc & AI 거버넌스)
포트 점유 PID 역추적 지원 안 함 (리소스 모니터 별도 실행) 수동 TCP 탭 검색 (복잡함) 포트 번호 입력 시 1초 만에 PID 자동 적출
CPU 부하 측정 방식 시스템 전역 서비스 부하 유발 상세하지만 초보자에게 너무 무거움 WMI 없는 2단계 네이티브 델타 틱 초경량 연산
AI 서브프로세스 연쇄 회수 개별 수동 종료 필요 Kill Process Tree 지원 UI 종료 시 CPython / COM 인스턴스 자동 연쇄 소멸
진입 장벽 및 UX 수백 개 프로세스 나열로 초보자 당혹 전문가용 인터페이스 단일 검색창, 직관적 MB/CPU 정렬, 한글 안내

7. 결론: "백그라운드에서 단 하나의 찌꺼기도 남기지 않는 클린 온디바이스 생태계"

사용자가 프로그램을 닫았을 때, 컴퓨터는 그 프로그램이 실행되기 전과 완전히 동일한 깨끗한 상태로 돌아가야 합니다. 그것이 소프트웨어 개발자가 사용자의 하드웨어에 대해 지켜야 할 가장 기본적인 '엔지니어링 윤리'입니다.

ZeliDesk의 ZeliProc과 AI 프로세스 라이프사이클 거버넌스는 눈에 띄는 화려한 기능은 아니지만, 학교 컴퓨터실 40대의 PC가 온종일 AI 수업을 진행해도 발열과 멈춤 없이 쾌적하게 유지되도록 지탱해 주는 가장 견고한 주춧돌입니다.

📊 ZeliDesk ZeliProc 프로세스 관리자 체험하기
복잡한 포트 충돌과 멈춰버린 백그라운드 프로세스를 단 1초 만에 추적하고 정리해 보세요.
72종 유틸리티 전체 둘러보기 →