← 기술 백서 목록으로 돌아가기

컴퓨터실 40대 PC의 스토리지 고갈과 중복 파일 0초 정리: ZeliMatch의 3단계 계층형 해시(4KB Partial & Full MD5) 스캐닝 아키텍처

"수십만 개의 파일을 검사하기 위해 모든 디스크 블록을 읽는 것은 엔지니어링이 아니라 무차별 대입입니다. 크기가 다른 95%의 파일을 0초 만에 거르고, 4KB의 헤더만으로 불일치를 증명하며, 오직 0.1%의 의심군에만 정밀 해시를 수행하는 계층형 아키텍처—ZeliMatch가 SSD의 수명을 지키고 스토리지 낭비를 원천 제거하는 비결입니다."

1. 전산실 40대 PC의 침묵하는 병목: 중복 파일 난립과 단순 해시 스캐너의 I/O 스래싱

전국 초·중·고등학교 컴퓨터실의 40대 PC와 AI 디지털교과서(AIDT) 실습실, 국방 전산 교육장에서는 학기 말이 다가올수록 "디스크 공간 부족(Low Disk Space)" 경고가 속출합니다. 학생들이 수업 중 내려받은 동일한 이미지·동영상 실습 자료, 과제물 복사본("과제_최종.zip", "과제_진짜최종.zip"), 백업 압축 파일들이 수십 GB 규모로 누적되기 때문입니다.

그러나 이 중복 파일들을 찾아내기 위해 시중의 단순 중복 검색기나 스크립트를 실행하면 더 큰 재앙이 시작됩니다:

비교 항목 전통적 단순 해시 스캐너 시중 클라우드 클리너 (CCleaner 등) ZeliMatch 3단계 계층형 스캐너
해시 계산 대상 발견된 모든 파일 전체 (100%) 서버 업로드 분석 위주 1단계 크기 탈락(95%) ➔ 2단계 4KB 헤더 ➔ 3단계 풀해시(0.1%)
디스크 I/O 부하 수십~수백 GB 풀 리딩 (I/O 병목) 백그라운드 에이전트 상주 오버헤드 최소한의 4KB 청크 읽기로 I/O 98% 절감
개발/시스템 폴더 처리 node_modules 등 수만 파일 오탐 블라인드 삭제로 프로젝트 파괴 위험 11대 시스템·빌드 디렉터리 자동 바이패스
스마트 원본 보존 수동 하나씩 클릭 (휴먼 에러) 불명확한 삭제 기준 0번째 원본 보존, 1번째부터 자동 마킹
외부 통신량 0바이트 텔레메트리/광고 트래픽 지속 발생 완전 0바이트 (Air-Gap 완전 격리)

ZeliMatch는 이러한 I/O 비효율과 보안 리스크를 완전히 극복하기 위해 설계된 WinUI 3 네이티브 초고속 중복 파일 탐색 및 스토리지 거버넌스 도구입니다.

2. 3단계 계층형 필터링(3-Tier Hierarchical Hash Pipeline)의 수학적 원리

ZeliMatch의 압도적인 속도는 "중복이 아닌 파일은 절대 전체 해시를 계산하지 않는다"는 계층형 파이프라인에서 나옵니다.

C# (3-Tier Hierarchical Duplicate Elimination Engine) ZeliMatch/Services/DuplicateScanner.cs
// ═══════════════════════════════════════════════════════
//  ZeliMatch 3단계 계층형 중복 파일 탐색 파이프라인
// ═══════════════════════════════════════════════════════
public async Task<List<MatchGroup>> ScanAsync(string rootPath, CancellationToken token)
{
    return await Task.Run(() =>
    {
        var filesBySize = new ConcurrentDictionary<long, List<string>>();

        // [1단계] 재귀 디렉토리 순회 & 바이트 크기(Size) 1차 그룹핑
        // 크기가 고유한 파일은 중복일 가능성이 0%이므로 즉시 탈락 (95% 이상 필터링)
        ScanDirectory(rootPath);

        var sizeCandidates = filesBySize.Values.Where(list => list.Count > 1).ToList();
        var finalGroups = new List<MatchGroup>();

        // [2단계] 크기가 동일한 후보군 대상 앞부분 4KB 부분 해시 검증
        foreach (var group in sizeCandidates)
        {
            token.ThrowIfCancellationRequested();
            var partialGroups = new Dictionary<string, List<string>>();

            foreach (var file in group)
            {
                string partialHash = ComputeHash(file, 4096); // 4,096바이트만 초고속 읽기
                if (partialHash == null) continue;

                if (!partialGroups.ContainsKey(partialHash))
                    partialGroups[partialHash] = new List<string>();
                partialGroups[partialHash].Add(file);
            }

            // [3단계] 4KB 부분 해시까지 일치한 0.1% 의심군만 스트림 전체(Full) 해시 검증
            foreach (var partialGroup in partialGroups.Values.Where(l => l.Count > 1))
            {
                token.ThrowIfCancellationRequested();
                var fullGroups = new Dictionary<string, List<string>>();

                foreach (var file in partialGroup)
                {
                    string fullHash = ComputeHash(file, -1); // 전체 스트림 MD5 검증
                    if (fullHash == null) continue;

                    if (!fullGroups.ContainsKey(fullHash))
                        fullGroups[fullHash] = new List<string>();
                    fullGroups[fullHash].Add(file);
                }

                // 비트 단위 100% 동일한 최종 중복 그룹(MatchGroup) 구축
                foreach (var kvp in fullGroups.Where(kv => kv.Value.Count > 1))
                {
                    var matchGroup = new MatchGroup { Hash = kvp.Key };
                    long size = new FileInfo(kvp.Value[0]).Length;

                    for (int i = 0; i < kvp.Value.Count; i++)
                    {
                        matchGroup.Items.Add(new MatchItem
                        {
                            FilePath = kvp.Value[i],
                            SizeBytes = size,
                            // 스마트 선택: 0번째 원본 유지, 1번째부터 자동 삭제 체크!
                            IsMarkedForDeletion = i > 0
                        });
                    }
                    finalGroups.Add(matchGroup);
                }
            }
        }

        // 낭비 공간이 가장 큰 그룹부터 내림차순 정렬
        return finalGroups.OrderByDescending(g => g.WastedSpaceBytes).ToList();
    }, token);
}

수학적으로 두 파일의 내용이 동일하려면 반드시 파일 크기가 같아야 합니다. 1단계에서 고유 크기를 가진 파일 95% 이상을 0바이트 I/O로 즉시 제외하고, 2단계에서 동일 크기 후보들의 파일 헤더(4KB)만 빠르게 비교함으로써 디스크 I/O를 98% 이상 절감합니다.

3. 시스템 및 빌드 폴더 자동 바이패스와 50ms 틱 디바운스 프로그레스

컴퓨터실 PC에는 Node.js, 파이썬, C# 등의 프로그래밍 수업 결과물이 보관되어 있습니다. 이때 node_modules나 .git, bin/obj 내부의 수만 개 라이브러리 파일이 중복으로 검색되면 정작 사용자가 정리해야 할 대용량 동영상이나 문서 파일이 묻히게 됩니다.

C# (Smart Directory Exclusion & Debounced Progress) ZeliMatch/Services/DuplicateScanner.cs
// 11대 개발 환경 및 시스템 폴더 중복 검사 자동 제외
string lowerName = di.Name.ToLowerInvariant();
if (lowerName == "node_modules" || lowerName == ".git"    || 
    lowerName == ".svn"         || lowerName == ".venv"   || 
    lowerName == "venv"         || lowerName == "env"     || 
    lowerName == "__pycache__"  || lowerName == ".idea"   || 
    lowerName == ".vscode"      || lowerName == "bin"     || 
    lowerName == "obj")
{
    continue; // 하위 트리 스캔 완전 생략
}

// ── 50ms 디바운스 UI 프로그레스 리포팅 ──
private void ReportProgress(string msg)
{
    long now = DateTime.UtcNow.Ticks;
    if (now - _lastReportTicks > TimeSpan.TicksPerMillisecond * 50)
    {
        _lastReportTicks = now;
        ProgressChanged?.Invoke(msg);
    }
}

11대 임시/라이브러리 디렉터리를 지능적으로 건너뜀으로써 스캔 속도를 10배 이상 향상시키며, UI 갱신 주기를 50ms로 디바운싱하여 수십만 개 파일을 탐색하는 도중에도 UI 스레드가 부드럽게 반응하도록 보장합니다.

4. 스마트 원본 보존(Smart Selection)과 원자적 파일 삭제 거버넌스

중복 파일 탐색 후 가장 위험한 단계는 "어떤 파일을 지울 것인가"의 문제입니다. 사용자가 수백 개의 체크박스를 일일이 누르다 실수로 원본까지 지워버리는 사고를 방지하기 위해, ZeliMatch는 스마트 자동 선택(Smart Selection) 알고리즘을 적용했습니다.

C# (Smart Selection & Safe File Deletion) ZeliMatch/Views/ZeliMatchWindow.xaml.cs
// ── 낭비 공간 계산 모델 (원본 1개를 뺀 나머지 중복 파일 용량) ──
public long WastedSpaceBytes => Count > 1 ? Items[0].SizeBytes * (Count - 1) : 0;

// ── 안전한 영구 삭제 파이프라인 ──
foreach (var item in itemsToDelete)
{
    try
    {
        var fi = new System.IO.FileInfo(item.FilePath);
        if (fi.Exists && fi.IsReadOnly)
        {
            fi.IsReadOnly = false; // 강제 삭제를 위해 읽기 전용 속성 자동 해제
        }
        System.IO.File.Delete(item.FilePath);
        freedSpace += item.SizeBytes;
        deleteCount++;
    }
    catch (Exception ex)
    {
        failCount++;
        lastFailMessage = ex.Message;
    }
}

중복 그룹 내에서 첫 번째 파일(인덱스 0)은 원본으로 간주하여 체크를 해제하고, 두 번째 파일부터만 IsMarkedForDeletion = true로 자동 지정합니다. 또한 삭제 대상 파일이 읽기 전용(ReadOnly) 속성으로 잠겨 있어도 fi.IsReadOnly = false를 통해 안전하게 해제 후 정리하며, 영구 삭제 전 사용자 확인 다이얼로그를 제공하여 데이터 유실을 2중으로 차단합니다.

5. 폐쇄망(Air-Gap) 제로 텔레메트리 스토리지 거버넌스

ZeliMatch는 파일의 해시를 계산할 때 파일 내용을 클라우드로 전송하거나 외부 API를 호출하지 않습니다. 모든 연산은 로컬 CPU의 인라인 메모리와 Windows 파일 핸들만을 사용하여 수행되므로, 외부 인터넷이 물리적으로 단절된 국방망이나 시험 출제 본부에서도 0바이트 외부 트래픽을 완벽하게 유지하며 안전하게 스토리지를 최적화할 수 있습니다.

6. 결론: 낭비 없는 지속 가능한 전산실과 차세대 스토리지 거버넌스

ZeliMatch는 한정된 하드웨어 리소스를 소프트웨어 엔지니어링의 정밀함으로 극복할 수 있음을 증명합니다.

  1. ZeliTree(#951) 디스크 시각화와의 결합: ZeliTree로 용량 과점 디렉터리를 탐지한 뒤, 즉시 ZeliMatch로 연계하여 해당 폴더 내 중복 파일을 0초 만에 색출하는 연합 파이프라인.
  2. ZeliSweep(#976) 다운로드 정리 도구와의 결합: 난장판이 된 다운로드 폴더에서 동일 파일의 중복 수신본을 1단계로 정리하여 디스크 여유 공간 즉시 확보.
  3. 차세대 파일 시스템 하드링크(Hardlink) 치환 로드맵: 삭제 대신 NTFS 하드링크로 중복 파일을 대체하여, 소프트웨어 참조는 유지하면서 물리적 디스크 점유율을 0MB로 줄이는 차세대 중복 제거(Deduplication) 기술 예고.

스토리지 증설 비용을 0원으로 만들고, 컴퓨터실 40대 PC의 쾌적한 실습 환경을 영구히 유지하는 것—ZeliDesk가 온디바이스 유틸리티 아키텍처를 통해 제시하는 지속 가능한 엔지니어링 표준입니다.

← 이전 기술 백서 #921 국방·공공 전산망 전자서명과 MSIX 배포 무결성 0초 검증: ZeliCert의 X.509 인증서 체인 감사 및 자체 서명 대시보드 거버넌스 아키텍처 다음 기술 백서 → #919 컴퓨터실 40대 PC의 파일 난립과 작업 경로 파편화 0초 해결: ZeliFolder의 워크스페이스 디렉터리 거버넌스 및 드래그앤드롭 오케스트레이션 아키텍처
⚡ ZeliDesk ZeliMatch 초고속 중복 파일 정리기 체험하기

SSD 수명 단축 없는 3단계 계층형 해시 스캔으로 낭비된 저장 공간을 0초 만에 회수하세요. 스마트 원본 보존과 100% 오프라인 완전 격리 거버넌스를 경험할 수 있습니다.

ZeliDesk Suite 무료 다운로드