데스크탑 앱·CLI
3823747 기준입니다.
Filee는 내 컴퓨터에서 여러 변환 엔진을 조합해 파일 형식을 바꾸는 무료 오픈소스 데스크탑 앱입니다. Windows에서는 기본적으로 Ctrl, macOS에서는 Option을 누른 채 파일을 끌면 커서 옆에 원형 메뉴가 나타납니다. 메뉴의 한 조각에 파일을 놓으면 그 조각에 연결된 프리셋으로 변환합니다. 홈 화면의 드롭 영역과 CLI도 제공합니다.
이 저장소에서 배울 핵심은 변환 알고리즘 하나보다, 서로 다른 변환기를 같은 규칙으로 연결하고 실행하는 설계입니다.
주문은 “이 HWPX를 PNG로 만들어 주세요”입니다. 한 기계로 끝나지 않으면
HWPX를 PDF로 만드는 기계와 PDF를 그림으로 만드는 기계를 차례로 배치합니다.
RoutePlanner가 공정표를 만들고 JobQueue가 기계 사용 순서와 결과물을 관리합니다.
주문판을 CLI로 바꾸어도 공장 자체는 같습니다. 화면과 핵심 로직을 나눈 효과를 눈으로 확인할 수 있는 예입니다.
| 사용자가 보는 것 | 코드 속 대응물 | 역할 |
|---|---|---|
| 원본의 확장자 | FormatRegistry | 지원 형식과 확장자 별칭을 조회 |
| 도넛 메뉴의 한 조각 | Preset | 목표 형식·품질·저장 규칙을 묶음 |
| 여러 파일을 한 번에 놓기 | ConversionJob | 한 번의 요청과 파일별 상태를 관리 |
| 실제 변환 작업 | IConverter.ConvertAsync() | 한 단계의 변환을 수행 |
| 완료·실패·진행률 | JobViewModel | 작업 상태를 화면에 표시할 값으로 변환 |
README는 이미지, PDF, Office 문서, HWP/HWPX, 미디어, 전자책, 압축 파일 등을 포함한
255가지 형식을 소개합니다. 커밋 3823747의 FormatRegistry.Known에는
262개 ID가 있습니다. 실제 파일 형식 261개와 폴더 출력용 가상 ID 1개를 합친 수이며,
모든 형식 사이의 변환이 가능하다는 뜻은 아닙니다.
src/Filee.Cli/Help.cs에서 확인할 수 있는 사용 문법입니다.
아래는 설치된 CLI를 사용할 때의 예시입니다.
# JPG에서 가능한 출력 형식 살펴보기
filee formats jpg
# 이미지 한 장을 품질 80의 WebP로 변환하여 converted 폴더에 저장
filee convert photo.jpg --to webp --quality 80 -o converted
화면에서 클릭하던 목표 형식과 품질을 인자로 전달했을 뿐입니다.
CliHost.Create()가 같은 엔진 목록과 작업 큐를 구성하므로 핵심 로직을 다시 만들지 않습니다.
이 글의 경로는 모두 저장소 루트 기준입니다. 제품 코드는 src/ 아래에 있으므로
경로는 src/Filee.Core/Conversion/RoutePlanner.cs처럼 표시합니다.
테스트 코드는 tests/ 아래에 있습니다.
선정 근거는 TrendShift Daily #25(2026-10-23)입니다. 2026-10-23 GitHub 기준 저장소는 2026-09-29 생성되어, 2026-10-23 기준 스타 10,465개와 포크 683개를 기록했습니다. 2026-10-21에는 v2.0.0이 출시되었습니다. 다만 이 숫자만으로 실제 사용자 수나 인기의 원인을 증명할 수는 없습니다.
제품과 코드를 보고 추론할 수 있는 매력은 분명합니다. 파일 변환은 반복해서 겪는 문제이고, 도넛 메뉴는 결과를 짧은 시연으로 전달하기 좋습니다. 국내 사용자에게는 HWP/HWPX가, 개발자에게는 CLI와 감시 폴더가 진입점이 됩니다. 다음 비교는 그런 사용 방식의 차이를 설명합니다.
| 선택지 | 잘 맞는 상황 | Filee의 상대적 장점과 조건 |
|---|---|---|
| 업로드형 웹 변환기 | 설치 없이 가끔 파일 변환 | 로컬 파일 변환에 업로드가 필요 없음. 대신 앱과 필요한 엔진을 준비해야 함 |
| FFmpeg 직접 사용 | 미디어 옵션을 세밀하게 제어 | 문서·이미지까지 같은 프리셋 방식으로 처리. 모든 FFmpeg 옵션을 노출하는 것은 아님 |
| ImageMagick 직접 사용 | 이미지 변환을 명령으로 자동화 | 전역 드래그 UI와 문서 엔진 연결 제공. 이미지 처리 기반은 해당 라이브러리에 의존 |
| Office류 앱의 내보내기 | 문서를 편집하며 결과를 검토 | Microsoft Office·한컴오피스 없이 여러 파일 처리. 편집 기능과 원본 재현 품질은 별도 문제 |
| Filee | 여러 파일 종류를 같은 흐름으로 변환 | GUI·CLI·감시 폴더가 공통 Core와 Engines를 사용 |
Filee의 강점은 지원 형식의 숫자와 함께, 여러 전문 도구를 하나의 짧은 작업 흐름으로 묶었다는 데 있습니다.
| 소개 문구·문서 | 소스에서 확인한 사실 | 읽는 방법 |
|---|---|---|
| README 기준 255가지 형식 | FormatRegistry.Known 262개(파일 형식 261개 + 폴더용 가상 ID 1개), 그중 Writable: false 85개 | 형식 ID·확장자 수·출력 가능 수·변환 조합 수를 구별 |
| 오프라인, 업로드 없음 | UpdateService, EngineInstaller, WebDownloader에 네트워크 코드 존재 | 로컬 변환과 업데이트·엔진 확보·웹 원본 다운로드를 구별 |
| Office가 필요 없음 | 자체 문서 읽기·쓰기와 rhwp를 사용하며, 일부 형식에는 선택 엔진이 필요 | 모든 형식이 추가 엔진 없이 된다는 뜻은 아님 |
| 시스템 엔진을 쓰지 않는다는 기여 문서 | LibreOfficeConverter는 사용자 지정 → Filee 사본 → 시스템 사본 순으로 조회 | 오래된 문서보다 실제 조회 코드를 우선 |
마지막 항목은 docs/ADDING-A-CONVERTER.md의 설명과
src/Filee.Engines/Infrastructure/EngineEnvironment.cs, src/Filee.Engines/Office/LibreOfficeConverter.cs의 구현이
다른 사례입니다. src/Filee.Engines/EngineRegistry.cs에도 시스템 소프트웨어를 쓰지 않는다는 오래된 주석이 남아 있습니다.
CHANGELOG.md의 2.0.0 항목은 전용 Windows 설치 프로그램,
브라우저의 이미지·파일 링크 드래그, 도넛 뒷면, 새 자르기 UI 등을 설명합니다.
현재 코드에는 이를 위한 src/Filee.Setup/, src/Filee.Core/Web/,
DonutMenu.Flip.cs, CropCanvas.cs가 있습니다.
단, 현재 HEAD에는 릴리스 이후 수정도 포함될 수 있어 모든 코드를 v2.0.0 배포물과 동일시하면 안 됩니다.
이 저장소의 중심은 .NET 10과 Avalonia입니다. 웹 앱처럼 프론트엔드와 서버 API가 따로 있는 구조가 아닙니다.
여기서 백엔드에 해당하는 것은 같은 컴퓨터의 Filee.Core와 Filee.Engines입니다.
데이터베이스 서버나 Supabase는 이 변환 흐름에 필요하지 않습니다.
| 근거 파일 | 실제 설정 | 초보자가 볼 점 |
|---|---|---|
global.json | SDK 10.0.100, rollForward: latestFeature | 지정 버전을 출발점으로 이후 SDK 기능 밴드 선택을 허용 |
Directory.Build.props | TargetFramework=net10.0, LangVersion=latest | 모든 C# 프로젝트에 공통 설정 적용 |
| 같은 파일 | Nullable=enable, ImplicitUsings=enable | null 가능성을 타입에 표현하고 공통 using을 줄임 |
Directory.Packages.props | ManagePackageVersionsCentrally=true | NuGet 패키지 버전을 한 파일에서 관리 |
Filee.slnx | 앱·Core·엔진·CLI·플랫폼·설치기와 테스트 프로젝트 | 솔루션은 여러 프로젝트를 함께 다루는 묶음 |
| 의존성 | 선언 버전 | Filee에서 하는 일 |
|---|---|---|
| Avalonia 계열 | 12.1.3 | Desktop, Fluent 테마, ColorPicker, Headless 테스트 |
| CommunityToolkit.Mvvm | 8.4.2 | 관찰 가능한 속성과 명령 코드 생성 |
| SharpHook | 8.0.1 | 전역 키보드·마우스 입력 수신 |
| AvaloniaUI.DiagnosticsSupport | 2.2.3 | Debug에서 UI 진단, 비 Debug 구성에서는 자산 제외 설정 |
| Microsoft.Extensions.DependencyInjection | 10.0.12 | 장기 서비스 생성과 연결 |
| Microsoft.Extensions.Logging 계열 | 10.0.12 | 로컬 로그와 엔진 오류 기록 |
화면은 .axaml, 상태와 동작은 C#로 작성합니다. 예를 들어
src/Filee.App/Views/MainWindow.axaml이 MainWindowViewModel의 값을 바인딩합니다.
앱 프로젝트에는 AvaloniaUseCompiledBindingsByDefault=true가 설정되어 있습니다.
x:DataType으로 데이터의 타입을 알려 주면 잘못된 속성 이름을 더 일찍 발견할 수 있습니다.다음 버전은 모두 Directory.Packages.props에 선언된 패키지 버전입니다.
| 분야 | 패키지와 버전 | 역할 |
|---|---|---|
| 이미지 | Magick.NET-Q8-AnyCPU 14.17.2 | ImageMagick을 C#에서 사용 |
| 그리기·SVG | SkiaSharp 3.119.4, Svg.Skia 5.1.1 | 그래픽 렌더링과 SVG 처리 |
PDFsharp 6.2.4, PDFtoImage 5.2.1, PdfPig 0.1.16 | PDF 작성·페이지 그림화·텍스트 읽기 | |
| 한글·마크다운 | Unhwp 0.13.0, Markdig 1.4.0 | HWP 처리와 Markdown 해석 |
| 스프레드시트 | ExcelDataReader 3.9.0, ExcelNumberFormat 1.1.0 | 시트 읽기와 숫자 표시 형식 |
| 이메일·HTML | MimeKitLite 4.18.1, MsgReader 6.2.0, AngleSharp 1.8.2 | 이메일과 HTML 문서 읽기 |
| 구조화 데이터 | YamlDotNet 18.1.0, Tomlyn 2.10.1 | YAML·TOML 해석 |
| CAD·3D | ACadSharp 3.8.0, SharpGLTF.Core 1.0.7 | CAD와 glTF 관련 처리 |
| 압축·호환성 | SharpCompress 1.0.0, System.Security.Cryptography.Pkcs 10.0.13 | 압축 처리와 PDFsharp 관련 보완 의존성 |
의존성 버전은 숫자를 외우는 대상이 아니라, 여러 라이브러리가 함께 돌아갈 수 있는 조건을 기록한 설계 자료입니다.
실제로 패키지 파일의 주석은 PDFtoImage 5.3 이상과 Svg.Skia 5.2 이상이 SkiaSharp 4를 요구하여 Avalonia 12.1 계열과 충돌한다고 설명합니다. 그래서 각각 5.2.1과 5.1.1을 선택했습니다. 이 설명은 저장소의 선택 근거이며, 모든 미래 버전에 대한 일반적인 호환성 판단은 아닙니다.
다음은 src/Filee.Engines/Infrastructure/engines.json의 기본 Windows 구성입니다.
플랫폼별 항목은 별도입니다. 버전뿐 아니라 다운로드 주소·SHA-256·크기도 함께 고정합니다.
| 구성 요소 | 버전 | 쓰임새 |
|---|---|---|
| rhwp / 7-Zip | 0.8.7 / 26.03 | HWP·HWPX와 압축, 배포 시 포함되는 작은 엔진 |
| FFmpeg / Pandoc | 9.0.2 / 3.12 | 미디어와 추가 문서 형식 |
| LibreOffice / H2Orestart | 26.2.6 / 0.7.14 | 추가 Office 형식과 한글 관련 확장 |
| calibre / Ghostscript | 9.15.0 / 10.08.0 | 추가 전자책 형식과 PostScript 계열 |
| JRE / C++ 런타임 | 21.0.12.1 / 14.44.35208 | 일부 엔진이 요구하는 실행 환경 |
.github/workflows/ci.yml은 복원, 포맷 확인, Release 빌드, UI 테스트와 나머지 테스트,
설치기 검사를 정의합니다. portable.yml은 Linux x64·ARM64, macOS Intel·Apple Silicon을 다룹니다.
이 설정은 CI의 검사 절차를 정의하며, 개별 실행의 성공 여부는 해당 실행 기록으로 판단해야 합니다.
| 기술 | 근거와 설정 | 배울 점 |
|---|---|---|
| xUnit | xunit.v3 3.2.2, Test SDK 18.10.1 | 순수 로직·실제 엔진·화면 테스트의 역할 분리 |
| Open XML 검증 | DocumentFormat.OpenXml 3.5.1, 테스트 전용 | 생성한 DOCX를 스키마와 대조 |
| Windows 배포 | build/build-installer.ps1, self-contained, ReadyToRun | 런타임 포함과 시작 비용의 선택 |
| Linux·macOS 배포 | build/build-portable.ps1, self-contained, ReadyToRun=false | 같은 앱도 플랫폼별 패키징은 다름 |
| 네이티브 보완 | Explorer 메뉴 C 코드, Zig 0.16.0 도구 체인 | 관리 코드와 OS 확장의 경계 |
저장소에는 package.json, Cargo.toml, pyproject.toml,
go.mod, Dockerfile이 없습니다. Rust는 Linux용 rhwp를 별도로 빌드할 때 등장하며,
앱의 주 구현 언어는 C#입니다. Python과 PowerShell은 주로 빌드·검증을 돕습니다.
그림은 책임을 보여 주는 요약입니다. CLI는 ConversionService를 거치지 않고
CliHost.Create()에서 Core와 Engines를 조립합니다.
앱에서는 src/Filee.App/Services/AppHost.cs의 Build()가 이를 의존성 주입 컨테이너에 등록합니다.
src/Filee.Core/Conversion/IConverter.cs는 엔진이 공통으로 지킬 계약입니다.
엔진마다 API와 실행 방식이 달라도 큐는 아래 속성과 메서드만 알면 됩니다.
다음은 실제 계약에서 핵심 멤버를 추린 코드입니다.
public interface IConverter
{
string Id { get; }
string DisplayName { get; }
IReadOnlyList<ConversionEdge> Edges { get; }
int MaxParallelism { get; }
EngineStatus GetStatus();
Task<IReadOnlyList<string>> ConvertAsync(
ConversionStep step, IProgress<double>? progress,
CancellationToken cancellationToken);
}
EngineRegistry.CreateAll()에는 29개 변환기 생성식이 있습니다.
29개가 전부 외부 실행 파일인 것은 아닙니다. MagickImageConverter는 라이브러리를 감싸고,
RhwpConverter는 별도 명령을 실행하며, DocxWriterConverter는 자체 작성기를 연결합니다.
콘센트 규격을 맞추면 선풍기든 충전기든 연결할 수 있습니다. IConverter가 규격이고,
각 변환기는 서로 다른 도구를 규격에 맞추는 어댑터입니다. 호출자는 도구의 내부 배선을 몰라도 됩니다.
학습할 때는 IConverter → EngineRegistry.CreateAll() →
MagickImageConverter.ConvertAsync() 순으로 읽어 보세요.
인터페이스 선언과 실제 구현을 오가면 “추상화”의 의미가 구체적으로 보입니다.
ConversionEdge는 한 엔진이 직접 수행하는 From → To와 비용을 나타냅니다.
RoutePlanner.Plan()은 PriorityQueue<string, int>를 사용한
다익스트라 방식의 탐색을 수행합니다. MaxSteps=3이며 기본 간선 비용은 10입니다.
// 실제 RhwpConverter의 간선 중 일부
new("hwp", "pdf", Unshaped: true),
new("hwpx", "pdf", Unshaped: true),
new("hwp", "hwpx"),
new("hwpx", "hwp"),
// RoutePlannerTests.Two_step_route_is_found()의 핵심
var rhwp = new FakeConverter("rhwp", new ConversionEdge("hwpx", "pdf"));
var pdfium = new FakeConverter("pdfium", new ConversionEdge("pdf", "png"));
var route = new RoutePlanner([rhwp, pdfium]).Plan("hwpx", "png");
ConverterCatalog.CreatePlanner()는 현재 사용 가능한 엔진만 넣습니다.
사용자 우선순위에 따른 추가 비용은 Math.Min(PriorityIndex(c), 9)입니다.
이 비용은 실측 시간이나 화질 점수가 아니라, 엔진 선호와 변환 특성을 표현하기 위한 상대값입니다.
형식만 연결하면 끝나는 것이 아니라, 그 경로가 사용자의 의도를 보존하는지도 함께 검사해야 합니다.
| 간선의 제약 | 막으려는 문제 |
|---|---|
ImageSourcesOnly | PDF를 PNG로 만든 뒤 사진처럼 벡터 추적하는 우회 경로 |
DirectOnly | 페이지를 그림 슬라이드로 바꾸는 PDF → PPTX를 다른 문서 변환의 중간 단계로 쓰는 경로 |
FrameSequence | 영상의 한 프레임 추출과 모든 프레임 저장을 혼동하는 경로 |
Unshaped | 복잡한 문자 조형이 필요한 문서를 해당 기능 없는 렌더러로 보내는 경로 |
JobQueue.RunFileAsync()는 문자의 특성을 검사한 뒤 필요하면 shaping: true로 경로를 다시 찾습니다.
다만 RhwpConverter.ScanScripts() 주석은 바이너리 HWP를 이 방식으로 검사하지 않는다고 밝힙니다.
경로 제약이 존재한다고 모든 문서의 품질이 보장되는 것은 아닙니다.
JobQueue.Enqueue()는 Channel.CreateUnbounded<ConversionJob>()에 작업을 넣고 즉시 반환합니다.
WorkLoopAsync()는 채널에서 작업을 하나씩 꺼내 실행합니다.
일반 배치에서는 작업 안의 파일들을 CPU 논리 프로세서 수 범위에서 병렬로 처리합니다.
// JobQueue.GateFor()의 실제 제한 계산
var max = converter.MaxParallelism <= 0
? Environment.ProcessorCount : converter.MaxParallelism;
return new SemaphoreSlim(max, max);
// RunFileAsync()의 호출 구조를 축약
await gate.WaitAsync(ct);
try
{
outputs.AddRange(await step.Converter.ConvertAsync(stepInfo, progress, ct));
}
finally
{
gate.Release();
}
MagickImageConverter.MaxParallelism은 0이므로 CPU 수를 따르고,
rhwp는 2, LibreOffice의 Workers도 2입니다.
파일을 많이 받는 것과 특정 엔진을 무제한으로 실행하는 것은 다른 문제입니다.
이 채널은 크기 제한이 없으므로 요청 수에 대한 역압력을 제공하지 않습니다.
또한 세마포어는 JobQueue 인스턴스 안에 있으므로, GUI와 별도로 실행한 CLI까지 묶는 전역 제한은 아닙니다.
코드를 읽을 때 “어느 범위에서 제한되는가”까지 확인해야 합니다.
Filee.Core.csproj는 Avalonia를 참조하지 않습니다.
운영체제 기능은 Core의 IPlatformServices 계약과 Windows·Linux·MacOS 구현으로 나눕니다.
AppHost.Build()가 실행 OS에 맞는 구현을 선택합니다.
화면 쪽의 JobViewModel은 ObservableObject를 상속하며
[ObservableProperty], [RelayCommand]를 사용합니다.
작업 큐의 이벤트는 백그라운드에서 발생하므로 ConversionService.OnJobUpdated()가
Dispatcher.UIThread.Post()로 화면 갱신을 넘깁니다.
JobViewModel, ConversionJob을 비교하면 경계가 드러납니다.FormatRegistry.Detect()가 확장자로 형식을 찾습니다. 전체 파일 내용을 검사하는 함수는 아닙니다.JobQueue.RunFileAsync()가 경로를 고르고, 중간 결과를 작업별 임시 폴더에 둡니다.OutputPathResolver.Resolve()의 규칙으로 이름을 정합니다.photo (2).png처럼 번호를 붙입니다.CompletedWithErrors로 구분하고, 작업 종료 때 임시 파일 정리를 시도합니다.외부 명령에는 ProcessRunner.RunAsync()가 UseShellExecute=false와
ArgumentList.Add()를 사용합니다. 취소·시간 초과 때 프로세스 트리 종료를 시도하고 표준 출력·오류를 수집합니다.
FFmpeg에는 별도의 FfmpegRunner도 있습니다. 이는 셸 인용과 프로세스 관리의 문제를 줄이는 설계이지,
변환 엔진을 운영체제 수준의 샌드박스에 넣는 기능은 아닙니다.
공통 버전 설정 Directory.Build.props는 2.1.0입니다. 당시 고정 소스는 2d562869aee7402a2c3521ecebdb26e042f60364이며, 이 페이지의 기존 코드 규모·형식 개수는 2026-10-23의 관측값으로 남깁니다. 다음 내용은 새로 읽은 코드 경로이며 바이너리 실행 결과는 아닙니다.
| 기능 | 구현과 제한 |
|---|---|
| OCR → 검색 가능한 PDF·문서 | ConversionEdge.Ocr와 PlanWithOcr()가 인식 단계를 먼저 배치합니다. 일반 변환에서는 OCR 간선을 제외합니다. Tesseract는 글자 없는 PDF 페이지만 300dpi로 인식하고 기존 텍스트 페이지는 복사합니다. 인식으로 다시 만든 페이지의 책갈피·양식 보존은 보장되지 않습니다. |
| PDF 표 → XLSX·ODS·CSV | PdfTablesConverter는 선으로 구획된 표를 읽어 시트로 만듭니다. 빈 공간만으로 정렬한 표·스캔은 대상이 아니며 표가 없으면 실패합니다. DirectOnly 간선이어서 이미지 → PDF → 표 계산 경로로 잘못 제시되지 않습니다. |
| 미디어·PDF 편집 | CHANGELOG는 압축·병합·클립 편집과 PDF 페이지 편집·워터마크·번호·암호를 설명합니다. 소스에는 ClipCutter, PdfPageTools, IPdfFinisher 계약이 추가됐습니다. 모든 입력의 품질이나 무손실 처리를 뜻하지 않습니다. |
| Wayland 드래그 | GNOME·Hyprland 경로도 실험 기능으로 문서화됐습니다. 최신 KWin 스크립트는 도넛을 올리기 전에 현재 Activity·desktop에 배치해 작업 공간이 갑자기 바뀌는 문제를 다룹니다. |
TesseractConverter는 파일 하나를 처리하면서 페이지 인식을 CPU 수에 따라 1~4개로 제한하고, 각 Tesseract의 내부 스레드는 하나로 둡니다. 언어 데이터를 작업 폴더에 복사하며 첫 사용 시 다운로드가 필요합니다. Windows는 선택 엔진, Linux·macOS는 시스템 설치본도 찾습니다. macOS의 Apple Vision 경로도 있지만 언어별 가용 조건이 다릅니다.
실습 과제: RoutePlanner.Plan(..., ocr: true)와 일반 호출을 비교해 OCR 간선이 언제 후보가 되는지 그려 보세요. 다음에는 선이 있는 PDF·선 없는 PDF·스캔에 대해 표 변환의 예상 성공/거부를 적습니다. 다운로드 완료와 인식 품질은 별도 검증 항목입니다.
현재 Directory.Build.props의 버전은 2.2.0이며 분석 SHA는 206df593ca0bc5f00f47c3b2bdf8f6aa98e50b1f입니다. README는 현재 270개 형식을 안내합니다. 아래의 초판 규모표는 당시 관측값이며 현재 지원 수와 구분합니다.
ImageEditTool.ConversionOf는 사용자의 크기·회전·품질 선택을 일반 변환 프리셋으로 바꿔 기존 작업 큐·취소·이력 경로를 공유합니다. 원본 형식으로 쓰기 경로가 없으면 PNG로 돌리는 분기도 있습니다.HideService는 EXIF 방향을 적용한 미리보기를 만들고 긴 변을 최대 2560px로 줄입니다. 애니메이션·다중 페이지 이미지는 첫 장에만 가려지는 오류를 막기 위해 거부합니다. 이름·얼굴을 가렸더라도 공유 전 최종 저장 파일에서 가린 범위를 확인해야 합니다.StallWatch는 출력 한 줄을 진행 신호로 갱신하고 일정 시간 침묵한 프로세스를 정지로 판정합니다. 작업이 진행되는 큰 파일을 단지 총시간이 길다는 이유로 끊지 않도록 한 설계입니다.RealPath.Of는 junction·심볼릭 링크·마운트 지점을 따라 실제 경로를 얻어 Windows Installer에 전달합니다. 사용자 AppData 경로를 옮긴 환경의 설치 오류에 대응합니다.실습은 복사한 사진 하나로 편집 → 저장 → 원본과 크기·방향·가림 영역 비교 순서로 시작합니다. 이번 분석은 소스와 변경기록을 읽었으며 다운로드 바이너리나 외부 엔진을 실행하지 않았습니다.
근거: 2.2.0 변경기록 · 가림 미리보기 · 대기 판정
이미지 편집 창에 자유 너비×높이 모드가 추가됐다. ImageEditTool.ResizeModes에 Custom이 들어가고, ViewModel은 픽셀·cm·mm·inch와 DPI를 다룬다. 단위를 바꿀 때 실제 픽셀 크기는 유지하며 처음 선택할 때 비율 잠금을 기본으로 둔다. 실제 프리셋은 Resize=None과 CustomSize로 저장해 기존 표현과 호환시킨다. 물리 단위를 고르면 이미지 DPI에도 반영한다.
FreeMasterText.Read()와 데이터 변환기에 FreeMASTER 오실로스코프 TXT→CSV 경로가 추가됐다. 모든 TXT가 표로 변환되는 기능이 아니다. 첫 행 # Oscilloscope Data, 탭 구분 헤더의 첫 열 # Seconds, 두 열 이상과 최소 한 데이터 행을 요구한다. 데이터 열 수가 헤더와 다르면 거부하고 출력에서는 첫 열을 Seconds로 바꾼다.
# 입력 형식 예시 (열 사이는 탭) # Oscilloscope Data # Seconds Signal 0.0 12.5
Windows의 LibreOffice 탐색은 PATH·통상 폴더 외에 사용자·시스템의 32/64비트 레지스트리 설치 경로도 확인한다. 다른 드라이브에 설치한 LibreOffice를 발견하기 위한 변경이며 엔진을 자동 설치했다는 뜻은 아니다. 앱·설치 프로그램 공유 언어 목록에는 이탈리아어가 추가됐다. 위 기능은 소스 분기로 확인했고 실제 변환·편집을 실행하지 않았다.
현재 CLI의 filee formats --json은 formats 배열을, filee formats pdf --json처럼 형식을 지정한 호출은 해당 형식의 정보와 targets·withEngines 배열을 반환합니다. 각 형식 정보는 id·name·category·extensions·writable을 담습니다. targets는 지금 설치된 엔진으로 가능한 변환, withEngines는 추가 엔진이 있을 때 가능한 변환이므로 둘을 합쳐 현재 즉시 지원한다고 표시하지 않습니다.
# 독자의 별도 설치 환경에서 선택할 예시
filee formats --json
filee formats pdf --jsonREADME는 270개 형식을 안내합니다. 새 입력인 Bink(.bik)는 FFmpeg의 demuxer·decoder로 읽을 뿐 Bink 인코더가 없어 .bik 출력을 만들지 않습니다. Apple Voice Memos .qta 역시 읽기 전용이며, FFmpeg가 해독할 수 있는 첫 오디오 트랙을 변환합니다. iOS 26의 공간 APAC 트랙은 decoder가 없다는 제한이 있습니다. 형식 등록 수와 읽기·쓰기 가능 범위는 별개입니다.
고정 커밋 7fc129f는 앱·CLI·Setup·Explorer 메뉴 DLL과 번들 엔진의 Windows ARM64 패키징 경로를 추가합니다. 추가 다운로드 엔진까지 전부 ARM64라는 뜻은 아닙니다. EngineDownloads.DownloadRuntime는 win-arm64에서 Windows build 22000 이상일 때 win-x64 목록을 선택해 에뮬레이션을 사용합니다. Windows 10 ARM에는 그 x64 다운로드를 제공하지 않습니다. 배포 자산의 실제 제공 여부는 릴리스에서 확인해야 합니다.
엔진 페이지는 하나를 설치하는 동안 다른 행의 설치 요청도 대기열에 넣을 수 있습니다. UI 명령은 동시 요청을 받지만 서비스의 semaphore가 실제 설치를 한 번에 하나로 제한하므로 병렬 설치로 설명하지 않습니다. CLI 도움말에는 filee presets --json이 추가되었고 종료 코드 0은 건너뛴 파일을 포함해 “실패 없음”을 뜻합니다. 코드 1은 일부 실패 또는 취소를 포함하므로 종료 코드만으로 모든 파일이 변환되었다고 판정하면 안 됩니다.
| 프로젝트 | C# 파일 / 물리 줄 수 | 읽을 때의 질문 |
|---|---|---|
| Filee.Engines | 229개 / 63,784줄 | 형식 차이와 호환성 예외를 어디서 처리하는가? |
| Filee.App | 121개 / 20,200줄 | 사용자 동작을 작업 요청으로 어떻게 바꾸는가? |
| Filee.Core | 37개 / 8,368줄 | UI 없이도 검증할 수 있는 규칙은 무엇인가? |
| Filee.Setup | 32개 / 4,996줄 | 설치·업데이트·제거도 왜 별도 제품 로직인가? |
| 플랫폼 3개 합계 | 22개 / 3,263줄 | OS마다 다른 부분을 어떻게 가두는가? |
| Filee.Cli | 6개 / 674줄 | 공통 로직이 있으면 새 진입점이 얼마나 작아지는가? |
엔진 폴더가 가장 큽니다. Filee는 외부 프로그램만 호출하는 얇은 껍데기가 아닙니다.
예를 들어 src/Filee.Engines/Hwp/Hwpx/에는 문서 모델과 읽기·쓰기 코드가 있고,
src/Filee.Engines/Office/에는 내장 DOCX 작성기를 연결하는 변환기가 있습니다.
| 종류 | 파일 수 / 물리 줄 수 | 범위 |
|---|---|---|
| C# 전체 | 649개 / 154,445줄 | 제품·테스트·빌드 도구 포함 |
| C# 제품 구현 | 447개 / 101,285줄 | 저장소의 src/ 아래 |
| C# 테스트 | 199개 / 52,917줄 | tests/ 아래, 테스트용 입력 생성기 포함 |
| C# 빌드 도구 | 3개 / 243줄 | build/tools/ 아래 |
| AXAML | 39개 / 4,444줄 | 화면과 테마 선언 |
| C / JavaScript | 1개 / 515줄, 1개 / 41줄 | Explorer 메뉴와 KWin 통합 |
| PowerShell / Python | 9개 / 1,175줄, 5개 / 716줄 | 빌드·설치·검증 도구 |
| 셸 / YAML | 4개 / 123줄, 11개 / 831줄 | 설치 보조와 CI·저장소 설정 |
집계 대상은 git ls-files에 나오는 추적 파일 852개 중 확장자별 파일이며,
물리 줄 수는 Python의 read_bytes().splitlines() 길이를 합산한 값입니다. 빈 줄·주석을 포함하고,
미추적 빌드 결과나 외부 엔진의 소스는 포함하지 않습니다. 코드의 논리 줄 수와는 다릅니다.
테스트 C# 줄 수는 제품 C# 줄 수의 약 52.2%입니다. 이것은 테스트 코드의 양을 보여 주며 커버리지 52.2%라는 뜻은 아닙니다. 파일 규모만으로 전체 커밋 수·기여자 수·개발 속도를 판단할 수도 없습니다.
FileFormat.cs와 FormatRegistry.cs: 입력과 형식을 먼저 이해합니다.IConverter.cs와 RoutePlannerTests.cs: 작은 계약과 예제로 이동합니다.RoutePlanner.cs와 JobQueue.cs: 계획과 실행을 분리해 읽습니다.ConversionService.cs와 JobViewModel.cs: 결과가 화면에 도착하는 길을 봅니다.ConversionEdge는 readonly record struct,
ConversionStep은 sealed record입니다.
작은 값과 한 단계의 실행 문맥을 구분하고, 이름 있는 인자로 선택 조건을 전달합니다.
CancellationToken과 IProgress<double>도 계약의 일부입니다.
실습 아이디어: ConversionEdge의 필드마다
“이 조건이 없으면 생기는 잘못된 변환”을 한 문장씩 적어 보세요.
문법을 아는 데서 끝내지 않고 타입이 어떤 사고를 막는지 설명하는 연습입니다.
RoutePlanner의 dist는 현재 비용,
prev는 직전 단계, hops는 단계 수를 저장합니다.
출발점과 목표가 같을 때도 재인코딩하려면 자기 자신으로 향하는 간선이 필요합니다.
단순히 “형식이 같으니 끝”이라고 처리하지 않습니다.
환승 경로를 고를 때 운임만 보면 부족합니다. 환승 횟수, 이용 불가 노선, 목적에 맞지 않는 교통수단도 고려합니다. Filee의 그래프 역시 비용표와 통행 규칙이 함께 있어야 쓸 만한 경로를 고릅니다.
실습 아이디어: 가짜 엔진의 A → B 비용을 8, B → C를 8,
A → C를 25로 두고 경로를 손으로 계산합니다. 여기에 B → C의 DirectOnly를 켜면
왜 결과가 달라지는지 RoutePlannerTests와 대조해 보세요.
큐는 UI 호출을 빨리 반환하게 하고, 파일 병렬화는 처리량을 높입니다.
세마포어는 엔진을 동시에 호출하는 수를 제한합니다. async가 자동으로
CPU 작업을 여러 코어에 나누거나 네이티브 엔진을 안전하게 만들지는 않습니다.
실습 아이디어: 10개 파일, CPU 논리 프로세서 8개,
rhwp 제한 2개라는 가정으로 “대기 중인 파일”과 “엔진에 들어간 파일”을 나누어 그려 보세요.
다음에는 취소 요청 시 finally가 왜 필요한지 설명합니다.
src/Filee.Engines/Hwp/Hwpx/HwpxModel.cs의 HDocument를 여러 읽기·쓰기 경로가 공유합니다.
DocumentReaders.ReadAsync()가 입력을 모델로 바꾸고,
DocxWriterConverter.ConvertAsync()가 그 모델을 DOCX로 씁니다.
DocxWriterConverter의 기본 간선 비용은 8이고,
PDF 입력에는 DocumentReaders.PdfPenalty=6을 더합니다.
읽기와 쓰기를 나누면 새 입력을 추가할 때 여러 출력으로 연결할 수 있지만,
중간 모델에 표현되지 않는 원본 기능은 잃을 수 있습니다.
중간 모델은 변환 조합을 늘려 주지만, 모델에 담지 못한 정보까지 보존해 주지는 않습니다.
실습 아이디어: 제목·문단·표·수식·그림이 있는 문서의 각 요소가 모델에서 무엇으로 표현되는지 표를 만드세요. “결과 파일이 열림”과 “의미가 보존됨”을 다른 검증으로 다룹니다.
src/Filee.App/Controls/DonutGeometry.cs의 Span(), AngleOf(),
IndexAt(), HitTest()는 각도·거리로 메뉴 조각을 고릅니다.
도넛을 그리는 코드와 이 계산을 나누어서 경계값을 테스트할 수 있습니다.
실습 아이디어: 네 조각 도넛의 위·오른쪽·아래·왼쪽 점을 종이에 찍고
IndexAt()의 결과를 계산합니다. 12시 방향을 기준으로 시계 방향 각도를 쓰는 이유도 찾아보세요.
대응 테스트는 tests/Filee.App.Tests/DonutGeometryTests.cs입니다.
EngineInstaller는 내려받은 엔진을 SHA-256과 대조한 후 풀고,
준비용 폴더에서 설치를 진행합니다. 일반 웹 파일을 받는 WebDownloader는
쿠키·자격 증명을 보내지 않으며 2 GiB 상한, 리다이렉트 5회, 응답·정체 30초 제한을 둡니다.
실습 아이디어: 엔진 다운로드와 웹 원본 다운로드의 신뢰 근거를 비교하세요. 전자는 저장소가 고정한 해시가 있고, 후자는 원격 사이트의 파일입니다. 일반 파일 다운로드의 HTTPS 하향 이동 금지 규칙을 엔진 설치기에 그대로 있다고 가정하면 안 됩니다. 설치기는 고정 해시 검증을 전제로 일부 HTTP 미러 이동을 허용합니다.
| 환경 | 문서·설정에서 확인한 조건 | 기능상 주의점 |
|---|---|---|
| Windows | README 기준 Windows 10/11, 현재 패키지 빌드 win-x64 | 설치형과 포터블 제공. 탐색기 확장은 네이티브 구성 요소 |
| macOS | README·설치 안내 기준 13 이상, osx-x64·osx-arm64, 미리보기 | 전역 입력에는 손쉬운 사용 권한, 선택 단축키에는 Finder 자동화 권한 필요 |
| Linux | README·설치 안내 기준 x64·ARM64, Ubuntu 22.04 이상 또는 glibc 2.35 이상 | X11 데스크탑 라이브러리와 글꼴 등 네이티브 의존성 필요 |
| Wayland | 기본 안내는 드롭 창·파일 관리자 동작 사용 | KDE Plasma 6과 새 GNOME·Hyprland 경로 모두 실험 기능이며 데스크탑별 준비 필요 |
| 배포판 런타임 | 빌드 스크립트가 .NET 런타임을 포함 | OS 라이브러리나 선택 엔진까지 모두 불필요해지는 것은 아님 |
| 소스 개발 | .NET 10 SDK, 스크립트별 PowerShell·Python·네이티브 도구 | 일반 사용자에게 SDK 전체가 필요한 것은 아님 |
근거는 README.ko.md, installer/linux/INSTALL.txt,
installer/macos/INSTALL.txt, build/build-portable.ps1입니다.
macOS 패키지는 아직 공증 전이라는 안내가 있으며, calibre 다운로드의
minimumMacOS는 14.0입니다. 앱의 최소 OS와 엔진의 최소 OS가 다를 수 있습니다.
README와 설치 안내에는 공식적인 최소 RAM·CPU 코어 수·GPU 사양이 없습니다. 학습용으로는 메모리 8GB 이상과 디스크 여유 공간 수 GB를 초기 예산으로 제안하지만, 이는 학습용 자원 예산 예시이며 벤치마크나 작동 보증이 아닙니다. 첫 예제는 작은 이미지나 짧은 문서로 잡으세요.
| 작업 종류 | 자원이 커지는 이유 | 사전에 생각할 것 |
|---|---|---|
| 큰 이미지·다중 프레임 | 압축 파일보다 디코딩한 픽셀이 훨씬 큼 | 가로 × 세로 × 채널 × 프레임 수 |
| 긴 문서의 페이지 그림화 | 중간 PDF·TIFF와 페이지별 출력 생성 | 페이지 수·DPI·임시 폴더 여유 공간 |
| 동영상 인코딩 | 해상도·길이·코덱에 따라 연산량 증가 | 하드웨어 인코더 사용 가능 여부와 품질 설정 |
| 선택 엔진 추가 | 앱과 별도로 엔진을 내려받고 압축 해제 | 다운로드 크기와 설치 후 크기는 다름 |
예를 들어 6,000 × 4,000 픽셀의 8비트 RGBA 버퍼 하나만 약 96MB, 즉 약 91.6MiB입니다. 여기에 원본·복사본·프레임·병렬 작업이 더해집니다. 이는 일반적인 버퍼 계산이며 Filee의 실제 사용량을 측정한 값이 아닙니다.
설치 파일의 크기보다 입력을 펼친 뒤의 크기와 동시에 처리하는 파일 수가 실행 자원을 더 크게 좌우합니다.
로컬 변환 경로에 필요한 엔진과 글꼴이 준비되어 있어야 합니다.
src/Filee.Engines/Infrastructure/engines.json의 기본 Windows 구성에서 FFmpeg 다운로드는 99,899,672바이트,
LibreOffice는 373,252,096바이트입니다. 이 값은 파일에 적힌 다운로드 크기이지 전체 설치 용량이 아닙니다.
네트워크가 없는 상태에서는 새 엔진과 웹 원본을 받을 수 없습니다.
UpdateService에는 6시간 간격의 업데이트 확인 설정도 있습니다.
따라서 “오프라인 변환 가능”을 “앱에 네트워크 기능 자체가 없음”으로 해석하지 마세요.
배포 검사의 범위를 읽는 과제로 build/smoke-launch-app.py를 살펴볼 수 있습니다. 이 도구는 패키지 앱의 시작·종료, macOS의 두 번째 실행 전달, Linux X11 입력 훅 오류를 확인합니다. 변환 결과나 이미지 편집 정확도를 검사하는 테스트는 아니므로 별도의 샘플 파일 검증이 필요합니다. 이 검토에서는 해당 도구를 실행하지 않았습니다.
아래는 독자를 위한 제안입니다. 구현 과제는 별도의 학습용 사본에서 수행하는 것을 전제로 합니다. 각 과제는 입력·예상 출력·근거를 설명할 수 있는 결과물을 목표로 삼습니다.
질문: photo.JPEG, backup.tar.gz, README는 각각 어떻게 인식될까요?
FormatRegistry의 ByExtension과 CompoundExtensions를 읽습니다.ExtensionOf() → FindByExtension() → Detect()를 연결합니다.완료 기준: 각각 jpg, tgz, null이 되는 이유를 설명합니다.
대응 예시는 OutputPathResolverTests.Two_part_extensions_are_one_extension()에 있습니다.
질문: HWPX → PNG에 직접 간선이 없어도 어떻게 결과를 만들까요?
RoutePlannerTests.Two_step_route_is_found()의 가짜 엔진 두 개를 읽습니다.ConverterCatalog.CreatePlanner()에서 어떤 간선이 제외되는지 표시합니다.완료 기준: 경로, 총비용, 엔진 가용 조건을 설명하고, 경로 없음과 변환 실행 실패를 구별합니다.
만들 것: OutputPathResolver.Resolve()의 입력·예상 출력 표와 작은 단위 테스트 제안입니다.
photo.png가 이미 있을 때 JPG → PNG의 기본 동작을 적습니다.ConflictPolicy.Skip, Overwrite, Rename을 비교합니다.photo.png일 때 Overwrite여도 같은 경로를 반환하지 않는 사례를 추가합니다.완료 기준: 파일이 존재한다는 판단 함수를 주입해 사례를 재현하고, 원본 보호가 일반적인 충돌 정책보다 먼저 적용되는 이유를 설명합니다.
만들 것: 별도 학습용 프로젝트에서 실행 중인 호출 수와 최대 동시 호출 수를 기록하는 가짜 엔진입니다.
tests/Filee.Core.Tests/FakeConverter.cs의 계약 구현을 참고합니다.MaxParallelism을 1 또는 2로 고정합니다.완료 기준: 엔진별 제한을 넘지 않고, 예외·취소 뒤에도 허가가 반환되는지 확인하는 검증 조건을 세웁니다. 작업 완료 상태와 파일별 상태가 항상 같지는 않다는 점도 설명합니다.
예시: 이미 알려진 텍스트 형식 하나에 대해 특정 출력으로 가는 자체 변환기를 설계합니다. 기존 경로와 겹치는지 먼저 확인하고, 임의의 새 형식 이름을 제품에 등록하는 것부터 시작하지 마세요.
IConverter 구현, Edges, 비용, GetStatus()를 정의합니다.EngineRegistry.CreateAll() 등록과 기존 경로에 미치는 영향을 적습니다.완료 기준: 직접 변환 성공뿐 아니라 새 우회 경로, 엔진 미설치, 잘못된 입력의 결과까지 검토합니다. 오래된 기여 문서와 현재 엔진 조회 정책의 차이도 설계서에 반영합니다.
“테스트 파일에 이런 검증이 있다”, “내가 실행해 통과했다”, “아직 예상이다”는 다른 문장입니다. 근거 파일과 함수, 예상 입력·출력을 함께 남기면 나중에 소스가 바뀌어도 학습 기록을 검토할 수 있습니다.
하루에 저장소 전체를 이해하려 하면 파일 형식의 세부사항에 묻히기 쉽습니다. 아래 과정은 한 주마다 읽을 파일, 설명할 개념, 남길 결과물을 정해 진도를 확인합니다. C#이 처음이라면 첫 주를 두 주로 늘리고 작은 코드 예제부터 읽어도 됩니다.
| 주차 | 배울 개념과 읽을 코드 | 주말에 남길 결과물 |
|---|---|---|
| 1주차 | C# 타입·인터페이스·record·null 가능성. FileFormat, ConversionEdge, IConverter | 핵심 타입 5개의 역할을 설명한 한 장짜리 노트 |
| 2주차 | 컬렉션·우선순위 큐·다익스트라. RoutePlanner와 대응 테스트 | 비용과 제약이 다른 그래프 3개의 손 계산 |
| 3주차 | Task·async/await·취소·채널·세마포어. JobQueue, ConversionJob | 대기 → 실행 → 완료·부분 실패·취소 상태도 |
| 4주차 | Avalonia·MVVM·바인딩·UI 스레드. JobViewModel, ConversionService | 진행률이 큐에서 화면으로 전달되는 호출 지도 |
| 5주차 | 중간 문서 모델·입출력·프로세스 경계. DocumentReaders, DocxWriterConverter, ProcessRunner | 텍스트·표·그림 보존 여부의 검토표 |
| 6주차 | 단위·통합 테스트, 패키징, 네이티브 호환성. ci.yml, portable.yml, engines.json | 새 엔진을 배포하기 위한 변경 파일과 검증 계획 |
매주 한 기능을 입력부터 출력까지 설명할 수 있게 되면, 큰 저장소도 읽을 수 있는 작은 경로들의 모음이 됩니다.
DonutGeometry의 좌표 계산과 실제 그리기를 비교하고 입력 경계값을 정리합니다.FolderWatcher.ProcessPendingAsync()에서 쓰기 중인 파일과 완성된 파일을 구분하는 규칙을 읽습니다.“형식 규칙이면 Core, 특정 도구의 구현이면 Engines, 화면 반응이면 App, OS 기능이면 Platform”이라는 출발점을 세우고 실제 참조 관계로 확인하세요. 정답 파일 하나를 외우는 것보다 변경의 책임과 영향을 설명하는 능력이 중요합니다.
| 용어 | 쉬운 설명 |
|---|---|
| .NET SDK / 런타임 | SDK는 프로그램을 만드는 도구 묶음, 런타임은 만들어진 프로그램의 실행 환경입니다. |
| NuGet / 중앙 버전 관리 | 외부 C# 패키지를 가져오는 체계입니다. Filee는 버전을 Directory.Packages.props에 모읍니다. |
| Avalonia / AXAML | 여러 데스크탑 OS의 화면을 만드는 UI 도구와 그 화면을 선언하는 XML 계열 문법입니다. |
| MVVM | 화면 모양과 화면 상태·명령, 작업 데이터를 구분하는 설계 방식입니다. |
| 바인딩 | 화면 요소를 C# 속성이나 명령과 연결하는 것입니다. |
| 소스 생성기 | 빌드 과정에서 반복 코드를 생성하는 도구입니다. [ObservableProperty]가 대표 예입니다. |
| 인터페이스 / 어댑터 | 공통 호출 규격과, 서로 다른 도구를 그 규격에 맞추는 구현입니다. |
| 의존성 주입 | 필요한 서비스를 객체가 직접 만들기보다 외부에서 전달받도록 연결하는 방식입니다. |
| 프리셋 | 목표 형식·품질·저장 위치 같은 사용자 선택을 묶은 주문서입니다. |
| 노드 / 간선 | 그래프의 지점과 연결입니다. Filee에서는 파일 형식이 노드, 직접 변환이 간선입니다. |
| 가중치 / 다익스트라 | 연결마다 둔 비용과, 누적 비용이 작은 경로를 찾아가는 알고리즘입니다. |
| 자기 간선 | 같은 형식으로 되돌아오는 변환입니다. JPG 품질을 낮추는 재인코딩도 여기에 해당할 수 있습니다. |
| 직렬 / 병렬 / 비동기 | 차례대로 처리, 여러 작업을 함께 처리, 완료를 기다리는 동안 호출 흐름을 양보하는 방식은 서로 다른 개념입니다. |
| 생산자·소비자 / Channel | 요청을 넣는 쪽과 꺼내 처리하는 쪽을 큐로 연결합니다. Filee는 채널에 변환 작업을 넣습니다. |
| 역압력 | 처리 속도보다 요청이 빠를 때 생산 속도를 제한하는 방식입니다. 현재 작업 채널은 용량 제한이 없습니다. |
| SemaphoreSlim | 한 번에 들어갈 수 있는 수를 정한 허가표입니다. Filee는 엔진별 동시 호출을 제한합니다. |
| CancellationToken | 진행 중인 작업에 취소 요청을 전달하는 신호입니다. 작업 구현도 그 신호에 협조해야 합니다. |
| UI 스레드 / Dispatcher | 화면을 갱신하는 실행 흐름과 그쪽에 일을 전달하는 통로입니다. |
| 중간 문서 모델 | 여러 입력을 공통 문단·표 등의 구조로 옮긴 표현입니다. Filee의 HDocument가 그 예입니다. |
| 문자 조형 / 글꼴 대체 | 문자를 문맥에 맞게 배치·결합하는 처리와, 없는 글꼴을 다른 글꼴로 바꾸는 처리는 서로 다릅니다. |
| 네이티브 의존성 / ABI | OS·CPU에 맞춘 바이너리와 그 바이너리끼리 호출하는 약속입니다. .NET 앱도 이 조건을 피하지 못합니다. |
| self-contained | 앱 배포물에 .NET 런타임을 포함하는 방식입니다. 모든 OS 라이브러리까지 포함한다는 뜻은 아닙니다. |
| SHA-256 / 준비용 폴더 | 받은 엔진이 지정 파일과 같은지 확인하는 해시와, 설치가 완성되기 전에 작업하는 별도 폴더입니다. |
| 테스트 대역 / 통합 테스트 | 가짜 엔진으로 규칙만 검증하거나, 실제 엔진·파일까지 연결해 결과를 확인하는 서로 다른 검사입니다. |
| 물리 줄 수 / 커버리지 | 파일의 줄 수와 테스트가 실제 코드 경로를 실행한 비율은 다른 지표입니다. |
| shallow clone | 최근 일부 이력만 받은 복제본입니다. 현재 파일은 읽을 수 있어도 전체 개발 이력 통계에는 한계가 있습니다. |
2026-10-30 추가 근거 (분석 SHA aad99622f110c8b66a3ac7115e8ff6375fdc5699): README.md · Directory.Build.props · docs/ENGINES.md · src/Filee.Cli/Cli.cs · src/Filee.Cli/Help.cs · src/Filee.Core/Formats/FormatRegistry.cs. 설치·빌드·모델 호출 없이 소스를 대조했습니다.
2026-10-29 재검토: 공식 소스 커밋 11769a896a496292ab4bf899020164d767fd60f4. 아래 초판 기록과 현재 소스 개정 내용을 구분한다.
2026-10-28 재검토 소스: 206df593ca0bc5f00f47c3b2bdf8f6aa98e50b1f. 설치·외부 모델 호출·실행 없이 아래 파일을 대조했습니다.
README.ko.md · CHANGELOG.md · Directory.Build.props · src/Filee.Core/Conversion/RoutePlanner.cs · src/Filee.Core/Conversion/IConverter.cs · src/Filee.Engines/Ocr/TesseractConverter.cs · src/Filee.Engines/Pdf/PdfTablesConverter.cs · docs/GNOME-WAYLAND.md · installer/linux/kwin/filee-donut/contents/code/main.js
아래는 다음 학습을 위한 공식 문서 링크입니다. 본문에 인용한 버전과 Filee의 동작 근거는 최신 문서의 예제가 아니라 위 커밋의 프로젝트 파일과 소스입니다.
| 항목 | 값과 확인 범위 |
|---|---|
| 선정 | TrendShift Daily #25 (2026-10-23) |
| 스타 / 포크 | 10,465 / 683 — 2026-10-23 GitHub 기준 |
| 생성일 | 2026-09-29 — 2026-10-23 GitHub 기준 |
| 주 언어 | C# — 2026-10-23 GitHub 기준 |
| 최신 릴리스 | v2.0.0, 2026-10-21 — 2026-10-23 GitHub 기준 |
| 최근 push | 2026-10-23 — 2026-10-23 GitHub 기준 |
| 소스 기준 커밋 | 3823747, 2026-10-23, Merge pull request #467 from adnan-bhaldar/Fix/readme-format |
| 코드 규모 | C# 649개 / 154,445줄. 제품 101,285줄, 테스트 52,917줄, 빌드 도구 243줄 — 커밋 3823747의 추적 파일 기준 |
| UI·기타 구현 | AXAML 4,444줄, C 515줄, PowerShell 1,175줄, Python 716줄 — 동일한 물리 줄 수 기준 |
| 형식 / 변환기 | 등록 ID 262개(파일 형식 261개 + 폴더용 가상 ID 1개), 읽기 전용 표시 85개 / 등록된 변환기 생성식 29개 — 커밋 3823747 기준 |
| 라이선스 | Filee 코드는 MIT(2026-10-23 GitHub 기준). 포함·다운로드되는 엔진과 라이브러리는 각자의 라이선스와 고지 적용 |
| 근거의 범위 | 코드·설정·테스트 정의는 구현과 검사 조건을 보여 주며, 실제 변환 품질·성능은 입력과 실행 환경에 따라 달라짐 |
형식과 품질: 등록 ID 262개에는 폴더 출력용 가상 ID 1개가 포함됩니다. 모든 형식 사이의 변환이나 완전한 원본 보존을 뜻하지 않습니다. PDF → PPTX는 페이지를 그림으로 넣는 방식이며, 문서의 글꼴·수식·복잡한 문자 조형·레이아웃은 경로에 따라 달라질 수 있습니다.
운영 환경: macOS는 미리보기이고, Wayland 전역 제스처는 KDE·GNOME·Hyprland별로 준비하는 실험 경로입니다. 선택 엔진의 설치·버전·OS 요구사항을 확인해야 합니다. 소스의 프로세스 관리가 외부 엔진을 OS 수준에서 격리해 주는 것은 아니며, MIT 표지만으로 모든 외부 엔진의 배포 조건을 대신할 수도 없습니다.
버전 기준: 소스 설명은 커밋 3823747 기준입니다.
해당 커밋과 v2.0.0 릴리스 바이너리의 동작이 모두 같다고 볼 수는 없습니다.
GitHub 수치는 2026-10-23 기준이며, 테스트 정의와 실제 실행 결과는 구별해야 합니다.