본문으로 건너뛰기
5분 AI.
2026-10-30 소스 대조 · 2026-10-29 크기·데이터 경로 재검토 · TRENDSHIFT DAILY #7 · 2026-10-27 재검토 (초판 2026-10-23)

Filee 딥다이브
— 파일을 바꾸는 작은 도넛 뒤의 변환 공장

데스크탑 앱·CLI

빠른 판단

무엇
로컬 변환 엔진을 드래그 메뉴·CLI·감시 폴더로 연결하는 문서·이미지·미디어 변환 앱
이럴 때
파일 변환 프리셋을 반복 적용하거나 OCR·PDF 표 추출·미디어 편집을 로컬 엔진으로 처리하려 할 때
입력
지원 파일과 변환 프리셋
결과
연결한 로컬 엔진이 생성한 대상 형식 파일
도입 전 확인
OCR·미디어·표 계산 출력은 엔진과 입력 구조에 따라 다르다. PDF 표 추출은 선이 있는 표를 대상으로 하며 Wayland 제스처는 실험 기능이다.
파일을 끌어 놓으면 사진·문서·영상의 형식이 바뀝니다. 이 단순한 동작 뒤에는 C# 계약, 가중 그래프 탐색, 비동기 작업 큐, 네이티브 엔진, 운영체제 통합이 있습니다. Filee의 실제 코드를 따라가며, 여러 도구를 하나의 데스크탑 제품으로 묶는 방법을 배웁니다. KnifeLemon/Filee · 스타 10,465 · 포크 683 · MIT · 초판 관측 릴리스 v2.0.0. 현재 소스의 공통 버전은 2.1.0이며 아래 개정 절에서 구분합니다. 저장소 정보는 2026-10-23 GitHub 기준이며, 소스 설명은 커밋 3823747 기준입니다.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

파일 하나를 바꾸는 일에서 소프트웨어 설계 전체를 배운다

Filee는 내 컴퓨터에서 여러 변환 엔진을 조합해 파일 형식을 바꾸는 무료 오픈소스 데스크탑 앱입니다. Windows에서는 기본적으로 Ctrl, macOS에서는 Option을 누른 채 파일을 끌면 커서 옆에 원형 메뉴가 나타납니다. 메뉴의 한 조각에 파일을 놓으면 그 조각에 연결된 프리셋으로 변환합니다. 홈 화면의 드롭 영역과 CLI도 제공합니다.

이 저장소에서 배울 핵심은 변환 알고리즘 하나보다, 서로 다른 변환기를 같은 규칙으로 연결하고 실행하는 설계입니다.

한 문장 비유

도넛은 주문판이고, 뒤에서는 공정표를 짜는 변환 공장이 돌아갑니다

주문은 “이 HWPX를 PNG로 만들어 주세요”입니다. 한 기계로 끝나지 않으면 HWPX를 PDF로 만드는 기계와 PDF를 그림으로 만드는 기계를 차례로 배치합니다. RoutePlanner가 공정표를 만들고 JobQueue가 기계 사용 순서와 결과물을 관리합니다.

주문판을 CLI로 바꾸어도 공장 자체는 같습니다. 화면과 핵심 로직을 나눈 효과를 눈으로 확인할 수 있는 예입니다.

1-1. 사용자의 동작을 코드의 단위로 바꾸기

사용자가 보는 것코드 속 대응물역할
원본의 확장자FormatRegistry지원 형식과 확장자 별칭을 조회
도넛 메뉴의 한 조각Preset목표 형식·품질·저장 규칙을 묶음
여러 파일을 한 번에 놓기ConversionJob한 번의 요청과 파일별 상태를 관리
실제 변환 작업IConverter.ConvertAsync()한 단계의 변환을 수행
완료·실패·진행률JobViewModel작업 상태를 화면에 표시할 값으로 변환
용어
프리셋과 엔진은 다른 개념입니다
프리셋은 “WebP, 품질 80, 원본 옆에 저장” 같은 주문서입니다. 엔진은 ImageMagick이나 FFmpeg처럼 실제로 변환을 수행하는 도구입니다. 한 프리셋을 실행하는 데 여러 엔진이 필요할 수 있습니다.

README는 이미지, PDF, Office 문서, HWP/HWPX, 미디어, 전자책, 압축 파일 등을 포함한 255가지 형식을 소개합니다. 커밋 3823747의 FormatRegistry.Known에는 262개 ID가 있습니다. 실제 파일 형식 261개와 폴더 출력용 가상 ID 1개를 합친 수이며, 모든 형식 사이의 변환이 가능하다는 뜻은 아닙니다.

1-2. 같은 기능을 명령으로 표현하면

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/ 아래에 있습니다.

2왜 주목받는가

선정 사실, 제품의 매력, 소스에서 확인한 범위를 나누어 읽기

2-1. 짧은 기간에 관심을 모은 배경

선정 근거는 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의 강점은 지원 형식의 숫자와 함께, 여러 전문 도구를 하나의 짧은 작업 흐름으로 묶었다는 데 있습니다.

2-2. 소스를 읽으면 홍보 문구의 경계가 보입니다

소개 문구·문서소스에서 확인한 사실읽는 방법
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에도 시스템 소프트웨어를 쓰지 않는다는 오래된 주석이 남아 있습니다.

2-3. v2.0.0의 변화도 설계 학습 소재입니다

CHANGELOG.md의 2.0.0 항목은 전용 Windows 설치 프로그램, 브라우저의 이미지·파일 링크 드래그, 도넛 뒷면, 새 자르기 UI 등을 설명합니다. 현재 코드에는 이를 위한 src/Filee.Setup/, src/Filee.Core/Web/, DonutMenu.Flip.cs, CropCanvas.cs가 있습니다. 단, 현재 HEAD에는 릴리스 이후 수정도 포함될 수 있어 모든 코드를 v2.0.0 배포물과 동일시하면 안 됩니다.

3기술 스택 전체 지도

웹 서버의 앞뒤 대신, 데스크탑 UI·핵심 로직·외부 프로세스로 나누기

이 저장소의 중심은 .NET 10과 Avalonia입니다. 웹 앱처럼 프론트엔드와 서버 API가 따로 있는 구조가 아닙니다. 여기서 백엔드에 해당하는 것은 같은 컴퓨터의 Filee.Core와 Filee.Engines입니다. 데이터베이스 서버나 Supabase는 이 변환 흐름에 필요하지 않습니다.

3-1. 언어와 공통 빌드 설정

근거 파일실제 설정초보자가 볼 점
global.jsonSDK 10.0.100, rollForward: latestFeature지정 버전을 출발점으로 이후 SDK 기능 밴드 선택을 허용
Directory.Build.propsTargetFramework=net10.0, LangVersion=latest모든 C# 프로젝트에 공통 설정 적용
같은 파일Nullable=enable, ImplicitUsings=enablenull 가능성을 타입에 표현하고 공통 using을 줄임
Directory.Packages.propsManagePackageVersionsCentrally=trueNuGet 패키지 버전을 한 파일에서 관리
Filee.slnx앱·Core·엔진·CLI·플랫폼·설치기와 테스트 프로젝트솔루션은 여러 프로젝트를 함께 다루는 묶음

3-2. 프론트엔드: Avalonia 화면과 C# 상태

의존성선언 버전Filee에서 하는 일
Avalonia 계열12.1.3Desktop, Fluent 테마, ColorPicker, Headless 테스트
CommunityToolkit.Mvvm8.4.2관찰 가능한 속성과 명령 코드 생성
SharpHook8.0.1전역 키보드·마우스 입력 수신
AvaloniaUI.DiagnosticsSupport2.2.3Debug에서 UI 진단, 비 Debug 구성에서는 자산 제외 설정
Microsoft.Extensions.DependencyInjection10.0.12장기 서비스 생성과 연결
Microsoft.Extensions.Logging 계열10.0.12로컬 로그와 엔진 오류 기록

화면은 .axaml, 상태와 동작은 C#로 작성합니다. 예를 들어 src/Filee.App/Views/MainWindow.axaml이 MainWindowViewModel의 값을 바인딩합니다. 앱 프로젝트에는 AvaloniaUseCompiledBindingsByDefault=true가 설정되어 있습니다.

용어
컴파일된 바인딩
화면의 “이 글자는 이 속성을 보여 준다”는 연결을 빌드 때 검사하도록 돕는 방식입니다. x:DataType으로 데이터의 타입을 알려 주면 잘못된 속성 이름을 더 일찍 발견할 수 있습니다.

3-3. 백엔드에 해당하는 변환 계층

다음 버전은 모두 Directory.Packages.props에 선언된 패키지 버전입니다.

분야패키지와 버전역할
이미지Magick.NET-Q8-AnyCPU 14.17.2ImageMagick을 C#에서 사용
그리기·SVGSkiaSharp 3.119.4, Svg.Skia 5.1.1그래픽 렌더링과 SVG 처리
PDFPDFsharp 6.2.4, PDFtoImage 5.2.1, PdfPig 0.1.16PDF 작성·페이지 그림화·텍스트 읽기
한글·마크다운Unhwp 0.13.0, Markdig 1.4.0HWP 처리와 Markdown 해석
스프레드시트ExcelDataReader 3.9.0, ExcelNumberFormat 1.1.0시트 읽기와 숫자 표시 형식
이메일·HTMLMimeKitLite 4.18.1, MsgReader 6.2.0, AngleSharp 1.8.2이메일과 HTML 문서 읽기
구조화 데이터YamlDotNet 18.1.0, Tomlyn 2.10.1YAML·TOML 해석
CAD·3DACadSharp 3.8.0, SharpGLTF.Core 1.0.7CAD와 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을 선택했습니다. 이 설명은 저장소의 선택 근거이며, 모든 미래 버전에 대한 일반적인 호환성 판단은 아닙니다.

3-4. 별도 실행 파일로 사용하는 엔진

다음은 src/Filee.Engines/Infrastructure/engines.json의 기본 Windows 구성입니다. 플랫폼별 항목은 별도입니다. 버전뿐 아니라 다운로드 주소·SHA-256·크기도 함께 고정합니다.

구성 요소버전쓰임새
rhwp / 7-Zip0.8.7 / 26.03HWP·HWPX와 압축, 배포 시 포함되는 작은 엔진
FFmpeg / Pandoc9.0.2 / 3.12미디어와 추가 문서 형식
LibreOffice / H2Orestart26.2.6 / 0.7.14추가 Office 형식과 한글 관련 확장
calibre / Ghostscript9.15.0 / 10.08.0추가 전자책 형식과 PostScript 계열
JRE / C++ 런타임21.0.12.1 / 14.44.35208일부 엔진이 요구하는 실행 환경

3-5. 인프라·빌드·테스트

.github/workflows/ci.yml은 복원, 포맷 확인, Release 빌드, UI 테스트와 나머지 테스트, 설치기 검사를 정의합니다. portable.yml은 Linux x64·ARM64, macOS Intel·Apple Silicon을 다룹니다. 이 설정은 CI의 검사 절차를 정의하며, 개별 실행의 성공 여부는 해당 실행 기록으로 판단해야 합니다.

기술근거와 설정배울 점
xUnitxunit.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은 주로 빌드·검증을 돕습니다.

4아키텍처 심화 분석

드롭 한 번이 결과 파일로 바뀌는 경로와 네 가지 설계 패턴
[사용자 입력] 전역 키 + 드래그 홈 드롭 영역 파일 관리자 메뉴 감시 폴더 | | | | TriggerService +----------------+ WatchFolderService | | | RadialController --> ConversionService <--------------------+ | | DonutMenu / Preset | Start() / RunAsync() → Enqueue() v [Filee.Core / JobQueue] <--- [Filee.Cli / CliHost] | | | ConverterCatalog.CreatePlanner() | | | RoutePlanner.Plan() | 사용 가능한 엔진의 경로 결정 v IConverter.ConvertAsync()를 단계별 호출 | +------------+---------------------+ | | [프로세스 안의 라이브러리] [별도 프로세스] Magick.NET / PDFsharp rhwp / FFmpeg / LibreOffice 자체 DOCX·HWPX 읽기·쓰기 ProcessRunner / FfmpegRunner | | +----------------+-----------------+ | 임시 중간 파일 / 할당된 최종 출력 경로 | JobUpdated / JobFinished 이벤트 v UI 스레드 전달 --> 진행률·결과 표시 JobFinished 처리 --> 로컬 기록 저장

그림은 책임을 보여 주는 요약입니다. CLI는 ConversionService를 거치지 않고 CliHost.Create()에서 Core와 Engines를 조립합니다. 앱에서는 src/Filee.App/Services/AppHost.cs의 Build()가 이를 의존성 주입 컨테이너에 등록합니다.

4-1. 패턴 ① 인터페이스를 통한 전략 교체와 어댑터

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() 순으로 읽어 보세요. 인터페이스 선언과 실제 구현을 오가면 “추상화”의 의미가 구체적으로 보입니다.

4-2. 패턴 ② 가중 그래프를 이용한 변환 경로 계획

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");
HWPX --[rhwp / 비용 10]--> PDF --[PDFium / 비용 10]--> PNG 합계 비용 20, 두 단계 추가 엔진의 간선을 등록하면, 그 간선을 통과하는 조합도 탐색 대상이 됩니다. 모든 형식 사이에 모든 경로가 생기는 것은 아닙니다.

ConverterCatalog.CreatePlanner()는 현재 사용 가능한 엔진만 넣습니다. 사용자 우선순위에 따른 추가 비용은 Math.Min(PriorityIndex(c), 9)입니다. 이 비용은 실측 시간이나 화질 점수가 아니라, 엔진 선호와 변환 특성을 표현하기 위한 상대값입니다.

형식만 연결하면 끝나는 것이 아니라, 그 경로가 사용자의 의도를 보존하는지도 함께 검사해야 합니다.

간선의 제약막으려는 문제
ImageSourcesOnlyPDF를 PNG로 만든 뒤 사진처럼 벡터 추적하는 우회 경로
DirectOnly페이지를 그림 슬라이드로 바꾸는 PDF → PPTX를 다른 문서 변환의 중간 단계로 쓰는 경로
FrameSequence영상의 한 프레임 추출과 모든 프레임 저장을 혼동하는 경로
Unshaped복잡한 문자 조형이 필요한 문서를 해당 기능 없는 렌더러로 보내는 경로

JobQueue.RunFileAsync()는 문자의 특성을 검사한 뒤 필요하면 shaping: true로 경로를 다시 찾습니다. 다만 RhwpConverter.ScanScripts() 주석은 바이너리 HWP를 이 방식으로 검사하지 않는다고 밝힙니다. 경로 제약이 존재한다고 모든 문서의 품질이 보장되는 것은 아닙니다.

4-3. 패턴 ③ 생산자·소비자 큐와 엔진별 동시성 제한

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까지 묶는 전역 제한은 아닙니다. 코드를 읽을 때 “어느 범위에서 제한되는가”까지 확인해야 합니다.

4-4. 패턴 ④ MVVM과 운영체제 경계 분리

Filee.Core.csproj는 Avalonia를 참조하지 않습니다. 운영체제 기능은 Core의 IPlatformServices 계약과 Windows·Linux·MacOS 구현으로 나눕니다. AppHost.Build()가 실행 OS에 맞는 구현을 선택합니다.

화면 쪽의 JobViewModel은 ObservableObject를 상속하며 [ObservableProperty], [RelayCommand]를 사용합니다. 작업 큐의 이벤트는 백그라운드에서 발생하므로 ConversionService.OnJobUpdated()가 Dispatcher.UIThread.Post()로 화면 갱신을 넘깁니다.

용어
MVVM: 화면·화면 상태·작업 데이터를 나누기
View는 보이는 모양, ViewModel은 화면에 표시할 값과 명령, Model은 변환 작업 같은 업무 데이터입니다. Filee에서는 AXAML 화면, JobViewModel, ConversionJob을 비교하면 경계가 드러납니다.

4-5. 한 파일의 수명과 실패 처리까지 따라가기

  1. FormatRegistry.Detect()가 확장자로 형식을 찾습니다. 전체 파일 내용을 검사하는 함수는 아닙니다.
  2. JobQueue.RunFileAsync()가 경로를 고르고, 중간 결과를 작업별 임시 폴더에 둡니다.
  3. 마지막 출력은 할당기를 거쳐 OutputPathResolver.Resolve()의 규칙으로 이름을 정합니다.
  4. 원본과 같은 경로는 덮어쓰지 않고, 기본 충돌 처리에서는 photo (2).png처럼 번호를 붙입니다.
  5. 일부 파일만 성공하면 CompletedWithErrors로 구분하고, 작업 종료 때 임시 파일 정리를 시도합니다.

외부 명령에는 ProcessRunner.RunAsync()가 UseShellExecute=false와 ArgumentList.Add()를 사용합니다. 취소·시간 초과 때 프로세스 트리 종료를 시도하고 표준 출력·오류를 수집합니다. FFmpeg에는 별도의 FfmpegRunner도 있습니다. 이는 셸 인용과 프로세스 관리의 문제를 줄이는 설계이지, 변환 엔진을 운영체제 수준의 샌드박스에 넣는 기능은 아닙니다.

2026-10-27 개정: 2.1 계열의 새 변환 경로

공통 버전 설정 Directory.Build.props는 2.1.0입니다. 당시 고정 소스는 2d562869aee7402a2c3521ecebdb26e042f60364이며, 이 페이지의 기존 코드 규모·형식 개수는 2026-10-23의 관측값으로 남깁니다. 다음 내용은 새로 읽은 코드 경로이며 바이너리 실행 결과는 아닙니다.

기능구현과 제한
OCR → 검색 가능한 PDF·문서ConversionEdge.Ocr와 PlanWithOcr()가 인식 단계를 먼저 배치합니다. 일반 변환에서는 OCR 간선을 제외합니다. Tesseract는 글자 없는 PDF 페이지만 300dpi로 인식하고 기존 텍스트 페이지는 복사합니다. 인식으로 다시 만든 페이지의 책갈피·양식 보존은 보장되지 않습니다.
PDF 표 → XLSX·ODS·CSVPdfTablesConverter는 선으로 구획된 표를 읽어 시트로 만듭니다. 빈 공간만으로 정렬한 표·스캔은 대상이 아니며 표가 없으면 실패합니다. DirectOnly 간선이어서 이미지 → PDF → 표 계산 경로로 잘못 제시되지 않습니다.
미디어·PDF 편집CHANGELOG는 압축·병합·클립 편집과 PDF 페이지 편집·워터마크·번호·암호를 설명합니다. 소스에는 ClipCutter, PdfPageTools, IPdfFinisher 계약이 추가됐습니다. 모든 입력의 품질이나 무손실 처리를 뜻하지 않습니다.
Wayland 드래그GNOME·Hyprland 경로도 실험 기능으로 문서화됐습니다. 최신 KWin 스크립트는 도넛을 올리기 전에 현재 Activity·desktop에 배치해 작업 공간이 갑자기 바뀌는 문제를 다룹니다.

OCR의 실행 자원과 엔진 준비

TesseractConverter는 파일 하나를 처리하면서 페이지 인식을 CPU 수에 따라 1~4개로 제한하고, 각 Tesseract의 내부 스레드는 하나로 둡니다. 언어 데이터를 작업 폴더에 복사하며 첫 사용 시 다운로드가 필요합니다. Windows는 선택 엔진, Linux·macOS는 시스템 설치본도 찾습니다. macOS의 Apple Vision 경로도 있지만 언어별 가용 조건이 다릅니다.

OCR 옵션 켬 → 입력 / 필요 시 PNG → OCR 전용 간선 → 검색 가능한 PDF → 목표가 문서이면 그 PDF에서 후속 변환 일반 변환 → OCR 간선을 사용하지 않음

실습 과제: RoutePlanner.Plan(..., ocr: true)와 일반 호출을 비교해 OCR 간선이 언제 후보가 되는지 그려 보세요. 다음에는 선이 있는 PDF·선 없는 PDF·스캔에 대해 표 변환의 예상 성공/거부를 적습니다. 다운로드 완료와 인식 품질은 별도 검증 항목입니다.

2026-10-28 개정: 2.2.0의 이미지 작업과 엔진 대기

현재 Directory.Build.props의 버전은 2.2.0이며 분석 SHA는 206df593ca0bc5f00f47c3b2bdf8f6aa98e50b1f입니다. README는 현재 270개 형식을 안내합니다. 아래의 초판 규모표는 당시 관측값이며 현재 지원 수와 구분합니다.

실습은 복사한 사진 하나로 편집 → 저장 → 원본과 크기·방향·가림 영역 비교 순서로 시작합니다. 이번 분석은 소스와 변경기록을 읽었으며 다운로드 바이너리나 외부 엔진을 실행하지 않았습니다.

근거: 2.2.0 변경기록 · 가림 미리보기 · 대기 판정

2026-10-29 소스 개정 — 자유 크기와 측정 데이터

이미지 편집 창에 자유 너비×높이 모드가 추가됐다. 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를 발견하기 위한 변경이며 엔진을 자동 설치했다는 뜻은 아니다. 앱·설치 프로그램 공유 언어 목록에는 이탈리아어가 추가됐다. 위 기능은 소스 분기로 확인했고 실제 변환·편집을 실행하지 않았다.

형식 목록을 자동화에 넘기는 JSON 계약

현재 CLI의 filee formats --json은 formats 배열을, filee formats pdf --json처럼 형식을 지정한 호출은 해당 형식의 정보와 targets·withEngines 배열을 반환합니다. 각 형식 정보는 id·name·category·extensions·writable을 담습니다. targets는 지금 설치된 엔진으로 가능한 변환, withEngines는 추가 엔진이 있을 때 가능한 변환이므로 둘을 합쳐 현재 즉시 지원한다고 표시하지 않습니다.

# 독자의 별도 설치 환경에서 선택할 예시
filee formats --json
filee formats pdf --json

README는 270개 형식을 안내합니다. 새 입력인 Bink(.bik)는 FFmpeg의 demuxer·decoder로 읽을 뿐 Bink 인코더가 없어 .bik 출력을 만들지 않습니다. Apple Voice Memos .qta 역시 읽기 전용이며, FFmpeg가 해독할 수 있는 첫 오디오 트랙을 변환합니다. iOS 26의 공간 APAC 트랙은 decoder가 없다는 제한이 있습니다. 형식 등록 수와 읽기·쓰기 가능 범위는 별개입니다.

2026-10-30 후속 대조: Windows ARM64와 설치 대기

고정 커밋 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은 일부 실패 또는 취소를 포함하므로 종료 코드만으로 모든 파일이 변환되었다고 판정하면 안 됩니다.

5디렉토리 구조 해부

처음부터 전부 읽지 말고, 한 요청이 지나는 파일을 먼저 찾기
Filee/ 저장소 루트 ├── global.json .NET SDK 기준 ├── Directory.Build.props 공통 빌드 설정 ├── Directory.Packages.props NuGet 버전의 중앙 관리 ├── Filee.slnx 솔루션 구성 ├── src/ │ ├── Filee.App/ Avalonia 앱 │ │ ├── Controls/ 도넛·자르기 등 사용자 정의 컨트롤 │ │ ├── Services/ 앱 서비스 조립·입력·변환·업데이트 │ │ ├── ViewModels/ 화면 상태와 명령 │ │ ├── Views/ AXAML 화면 │ │ └── Assets/i18n/ 언어별 JSON 문구 │ ├── Filee.Core/ UI와 OS 구현에서 독립된 핵심 로직 │ │ ├── Conversion/ 계약·경로 탐색·작업 큐 │ │ ├── Formats/ 형식·확장자·동반 파일 │ │ ├── Presets/ 변환 옵션과 출력 경로 규칙 │ │ ├── Settings/ 설정·프로필·기록의 로컬 저장 │ │ ├── Watching/ 폴더 감시와 중복 처리 방지 │ │ └── Web/ 브라우저 드롭과 파일 다운로드 │ ├── Filee.Engines/ 29개 변환기와 형식별 구현 │ │ ├── Infrastructure/ 엔진 조회·설치·프로세스 실행 │ │ ├── Hwp/Hwpx/ 문서 모델·읽기·쓰기 │ │ ├── Office/ DOCX·시트·프레젠테이션 처리 │ │ └── Media/ FFmpeg·라이브 포토 등 │ ├── Filee.Cli/ convert·watch·formats 명령 │ ├── Filee.Platform.Windows/ Windows 셸·플랫폼 기능 │ ├── Filee.Platform.Linux/ Linux 플랫폼 기능 │ ├── Filee.Platform.MacOS/ macOS 플랫폼 기능 │ ├── Filee.ExplorerMenu/ Windows 탐색기 확장 C 코드 │ └── Filee.Setup/ 전용 Windows 설치 프로그램 ├── tests/ 6개 테스트 프로젝트 ├── build/ 패키징·서명·호환성 검사 도구 ├── installer/ Linux·macOS 통합과 설치 자원 ├── .github/workflows/ CI와 릴리스 정의 └── docs/ 구조·엔진·기여 문서와 미디어

5-1. 가장 큰 폴더가 알려 주는 것

프로젝트C# 파일 / 물리 줄 수읽을 때의 질문
Filee.Engines229개 / 63,784줄형식 차이와 호환성 예외를 어디서 처리하는가?
Filee.App121개 / 20,200줄사용자 동작을 작업 요청으로 어떻게 바꾸는가?
Filee.Core37개 / 8,368줄UI 없이도 검증할 수 있는 규칙은 무엇인가?
Filee.Setup32개 / 4,996줄설치·업데이트·제거도 왜 별도 제품 로직인가?
플랫폼 3개 합계22개 / 3,263줄OS마다 다른 부분을 어떻게 가두는가?
Filee.Cli6개 / 674줄공통 로직이 있으면 새 진입점이 얼마나 작아지는가?

엔진 폴더가 가장 큽니다. Filee는 외부 프로그램만 호출하는 얇은 껍데기가 아닙니다. 예를 들어 src/Filee.Engines/Hwp/Hwpx/에는 문서 모델과 읽기·쓰기 코드가 있고, src/Filee.Engines/Office/에는 내장 DOCX 작성기를 연결하는 변환기가 있습니다.

5-2. 코드 규모 집계 기준

종류파일 수 / 물리 줄 수범위
C# 전체649개 / 154,445줄제품·테스트·빌드 도구 포함
C# 제품 구현447개 / 101,285줄저장소의 src/ 아래
C# 테스트199개 / 52,917줄tests/ 아래, 테스트용 입력 생성기 포함
C# 빌드 도구3개 / 243줄build/tools/ 아래
AXAML39개 / 4,444줄화면과 테마 선언
C / JavaScript1개 / 515줄, 1개 / 41줄Explorer 메뉴와 KWin 통합
PowerShell / Python9개 / 1,175줄, 5개 / 716줄빌드·설치·검증 도구
셸 / YAML4개 / 123줄, 11개 / 831줄설치 보조와 CI·저장소 설정

집계 대상은 git ls-files에 나오는 추적 파일 852개 중 확장자별 파일이며, 물리 줄 수는 Python의 read_bytes().splitlines() 길이를 합산한 값입니다. 빈 줄·주석을 포함하고, 미추적 빌드 결과나 외부 엔진의 소스는 포함하지 않습니다. 코드의 논리 줄 수와는 다릅니다.

테스트 C# 줄 수는 제품 C# 줄 수의 약 52.2%입니다. 이것은 테스트 코드의 양을 보여 주며 커버리지 52.2%라는 뜻은 아닙니다. 파일 규모만으로 전체 커밋 수·기여자 수·개발 속도를 판단할 수도 없습니다.

5-3. 초보자를 위한 읽기 순서

  1. FileFormat.cs와 FormatRegistry.cs: 입력과 형식을 먼저 이해합니다.
  2. IConverter.cs와 RoutePlannerTests.cs: 작은 계약과 예제로 이동합니다.
  3. RoutePlanner.cs와 JobQueue.cs: 계획과 실행을 분리해 읽습니다.
  4. ConversionService.cs와 JobViewModel.cs: 결과가 화면에 도착하는 길을 봅니다.
  5. 관심 있는 엔진 하나를 고릅니다. 첫날부터 모든 파일 포맷의 내부 구조를 읽을 필요는 없습니다.

6학습 포인트 (기술별)

기술 이름을 외우기보다, 그 기술이 해결한 문제를 찾기

6-1. C#: 계약과 데이터 모델을 읽는 법

ConversionEdge는 readonly record struct, ConversionStep은 sealed record입니다. 작은 값과 한 단계의 실행 문맥을 구분하고, 이름 있는 인자로 선택 조건을 전달합니다. CancellationToken과 IProgress<double>도 계약의 일부입니다.

실습 아이디어: ConversionEdge의 필드마다 “이 조건이 없으면 생기는 잘못된 변환”을 한 문장씩 적어 보세요. 문법을 아는 데서 끝내지 않고 타입이 어떤 사고를 막는지 설명하는 연습입니다.

6-2. 그래프: 비용과 제약을 분리하기

RoutePlanner의 dist는 현재 비용, prev는 직전 단계, hops는 단계 수를 저장합니다. 출발점과 목표가 같을 때도 재인코딩하려면 자기 자신으로 향하는 간선이 필요합니다. 단순히 “형식이 같으니 끝”이라고 처리하지 않습니다.

비유

환승 경로를 고를 때 운임만 보면 부족합니다. 환승 횟수, 이용 불가 노선, 목적에 맞지 않는 교통수단도 고려합니다. Filee의 그래프 역시 비용표와 통행 규칙이 함께 있어야 쓸 만한 경로를 고릅니다.

실습 아이디어: 가짜 엔진의 A → B 비용을 8, B → C를 8, A → C를 25로 두고 경로를 손으로 계산합니다. 여기에 B → C의 DirectOnly를 켜면 왜 결과가 달라지는지 RoutePlannerTests와 대조해 보세요.

6-3. 비동기: 응답성과 처리량은 별개의 문제

큐는 UI 호출을 빨리 반환하게 하고, 파일 병렬화는 처리량을 높입니다. 세마포어는 엔진을 동시에 호출하는 수를 제한합니다. async가 자동으로 CPU 작업을 여러 코어에 나누거나 네이티브 엔진을 안전하게 만들지는 않습니다.

실습 아이디어: 10개 파일, CPU 논리 프로세서 8개, rhwp 제한 2개라는 가정으로 “대기 중인 파일”과 “엔진에 들어간 파일”을 나누어 그려 보세요. 다음에는 취소 요청 시 finally가 왜 필요한지 설명합니다.

6-4. 문서 처리: 중간 모델로 조합 폭발 줄이기

src/Filee.Engines/Hwp/Hwpx/HwpxModel.cs의 HDocument를 여러 읽기·쓰기 경로가 공유합니다. DocumentReaders.ReadAsync()가 입력을 모델로 바꾸고, DocxWriterConverter.ConvertAsync()가 그 모델을 DOCX로 씁니다.

입력: Markdown / HTML / EPUB / HWPX / 기타 지원 문서 | DocumentReaders.ReadAsync() v HDocument | DocxWriter.Write() 등 출력기 v 출력: DOCX 또는 해당 모델을 쓰는 다른 문서 형식

DocxWriterConverter의 기본 간선 비용은 8이고, PDF 입력에는 DocumentReaders.PdfPenalty=6을 더합니다. 읽기와 쓰기를 나누면 새 입력을 추가할 때 여러 출력으로 연결할 수 있지만, 중간 모델에 표현되지 않는 원본 기능은 잃을 수 있습니다.

중간 모델은 변환 조합을 늘려 주지만, 모델에 담지 못한 정보까지 보존해 주지는 않습니다.

실습 아이디어: 제목·문단·표·수식·그림이 있는 문서의 각 요소가 모델에서 무엇으로 표현되는지 표를 만드세요. “결과 파일이 열림”과 “의미가 보존됨”을 다른 검증으로 다룹니다.

6-5. Avalonia와 수학: 그리기와 판단을 떼어 내기

src/Filee.App/Controls/DonutGeometry.cs의 Span(), AngleOf(), IndexAt(), HitTest()는 각도·거리로 메뉴 조각을 고릅니다. 도넛을 그리는 코드와 이 계산을 나누어서 경계값을 테스트할 수 있습니다.

실습 아이디어: 네 조각 도넛의 위·오른쪽·아래·왼쪽 점을 종이에 찍고 IndexAt()의 결과를 계산합니다. 12시 방향을 기준으로 시계 방향 각도를 쓰는 이유도 찾아보세요. 대응 테스트는 tests/Filee.App.Tests/DonutGeometryTests.cs입니다.

6-6. 신뢰 경계: 다운로드한 바이트와 실행할 도구

EngineInstaller는 내려받은 엔진을 SHA-256과 대조한 후 풀고, 준비용 폴더에서 설치를 진행합니다. 일반 웹 파일을 받는 WebDownloader는 쿠키·자격 증명을 보내지 않으며 2 GiB 상한, 리다이렉트 5회, 응답·정체 30초 제한을 둡니다.

실습 아이디어: 엔진 다운로드와 웹 원본 다운로드의 신뢰 근거를 비교하세요. 전자는 저장소가 고정한 해시가 있고, 후자는 원격 사이트의 파일입니다. 일반 파일 다운로드의 HTTPS 하향 이동 금지 규칙을 엔진 설치기에 그대로 있다고 가정하면 안 됩니다. 설치기는 고정 해시 검증을 전제로 일부 HTTP 미러 이동을 허용합니다.

7하드웨어 / 시스템 요구사항

배포판 실행 조건, 소스 개발 조건, 학습용 환경 예시를 구분
환경문서·설정에서 확인한 조건기능상 주의점
WindowsREADME 기준 Windows 10/11, 현재 패키지 빌드 win-x64설치형과 포터블 제공. 탐색기 확장은 네이티브 구성 요소
macOSREADME·설치 안내 기준 13 이상, osx-x64·osx-arm64, 미리보기전역 입력에는 손쉬운 사용 권한, 선택 단축키에는 Finder 자동화 권한 필요
LinuxREADME·설치 안내 기준 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가 다를 수 있습니다.

7-1. 메모리와 디스크는 입력 규모에 따라 달라집니다

README와 설치 안내에는 공식적인 최소 RAM·CPU 코어 수·GPU 사양이 없습니다. 학습용으로는 메모리 8GB 이상과 디스크 여유 공간 수 GB를 초기 예산으로 제안하지만, 이는 학습용 자원 예산 예시이며 벤치마크나 작동 보증이 아닙니다. 첫 예제는 작은 이미지나 짧은 문서로 잡으세요.

작업 종류자원이 커지는 이유사전에 생각할 것
큰 이미지·다중 프레임압축 파일보다 디코딩한 픽셀이 훨씬 큼가로 × 세로 × 채널 × 프레임 수
긴 문서의 페이지 그림화중간 PDF·TIFF와 페이지별 출력 생성페이지 수·DPI·임시 폴더 여유 공간
동영상 인코딩해상도·길이·코덱에 따라 연산량 증가하드웨어 인코더 사용 가능 여부와 품질 설정
선택 엔진 추가앱과 별도로 엔진을 내려받고 압축 해제다운로드 크기와 설치 후 크기는 다름

예를 들어 6,000 × 4,000 픽셀의 8비트 RGBA 버퍼 하나만 약 96MB, 즉 약 91.6MiB입니다. 여기에 원본·복사본·프레임·병렬 작업이 더해집니다. 이는 일반적인 버퍼 계산이며 Filee의 실제 사용량을 측정한 값이 아닙니다.

설치 파일의 크기보다 입력을 펼친 뒤의 크기와 동시에 처리하는 파일 수가 실행 자원을 더 크게 좌우합니다.

7-2. 오프라인으로 쓰려면 무엇을 미리 준비할까?

로컬 변환 경로에 필요한 엔진과 글꼴이 준비되어 있어야 합니다. src/Filee.Engines/Infrastructure/engines.json의 기본 Windows 구성에서 FFmpeg 다운로드는 99,899,672바이트, LibreOffice는 373,252,096바이트입니다. 이 값은 파일에 적힌 다운로드 크기이지 전체 설치 용량이 아닙니다.

네트워크가 없는 상태에서는 새 엔진과 웹 원본을 받을 수 없습니다. UpdateService에는 6시간 간격의 업데이트 확인 설정도 있습니다. 따라서 “오프라인 변환 가능”을 “앱에 네트워크 기능 자체가 없음”으로 해석하지 마세요.

8직접 해볼 수 있는 실습 과제

배포 검사의 범위를 읽는 과제로 build/smoke-launch-app.py를 살펴볼 수 있습니다. 이 도구는 패키지 앱의 시작·종료, macOS의 두 번째 실행 전달, Linux X11 입력 훅 오류를 확인합니다. 변환 결과나 이미지 편집 정확도를 검사하는 테스트는 아니므로 별도의 샘플 파일 검증이 필요합니다. 이 검토에서는 해당 도구를 실행하지 않았습니다.

읽기에서 시작해 작은 확장으로 끝내는 다섯 가지 과제

아래는 독자를 위한 제안입니다. 구현 과제는 별도의 학습용 사본에서 수행하는 것을 전제로 합니다. 각 과제는 입력·예상 출력·근거를 설명할 수 있는 결과물을 목표로 삼습니다.

과제 1 · 입문

확장자 세 개를 형식 ID까지 추적하기 읽기만으로 가능

질문: photo.JPEG, backup.tar.gz, README는 각각 어떻게 인식될까요?

  1. FormatRegistry의 ByExtension과 CompoundExtensions를 읽습니다.
  2. ExtensionOf() → FindByExtension() → Detect()를 연결합니다.
  3. 형식 ID, 확장자 별칭, 알 수 없는 경우를 표 한 장으로 정리합니다.

완료 기준: 각각 jpg, tgz, null이 되는 이유를 설명합니다. 대응 예시는 OutputPathResolverTests.Two_part_extensions_are_one_extension()에 있습니다.

과제 2 · 입문

두 단계 변환의 공정표 그리기 읽기만으로 가능

질문: HWPX → PNG에 직접 간선이 없어도 어떻게 결과를 만들까요?

  1. RoutePlannerTests.Two_step_route_is_found()의 가짜 엔진 두 개를 읽습니다.
  2. HWPX, PDF, PNG를 노드로 놓고 비용을 적습니다.
  3. 가짜 PDFium 변환기의 상태를 사용 불가로 두면 ConverterCatalog.CreatePlanner()에서 어떤 간선이 제외되는지 표시합니다.

완료 기준: 경로, 총비용, 엔진 가용 조건을 설명하고, 경로 없음과 변환 실행 실패를 구별합니다.

과제 3 · 중급

출력 이름 충돌 규칙을 예제로 검증하기

만들 것: OutputPathResolver.Resolve()의 입력·예상 출력 표와 작은 단위 테스트 제안입니다.

  1. photo.png가 이미 있을 때 JPG → PNG의 기본 동작을 적습니다.
  2. ConflictPolicy.Skip, Overwrite, Rename을 비교합니다.
  3. 원본 자체가 photo.png일 때 Overwrite여도 같은 경로를 반환하지 않는 사례를 추가합니다.

완료 기준: 파일이 존재한다는 판단 함수를 주입해 사례를 재현하고, 원본 보호가 일반적인 충돌 정책보다 먼저 적용되는 이유를 설명합니다.

과제 4 · 중급

가짜 변환기로 동시 실행 수 기록하기

만들 것: 별도 학습용 프로젝트에서 실행 중인 호출 수와 최대 동시 호출 수를 기록하는 가짜 엔진입니다.

  1. tests/Filee.Core.Tests/FakeConverter.cs의 계약 구현을 참고합니다.
  2. 테스트 엔진의 MaxParallelism을 1 또는 2로 고정합니다.
  3. 입력 여러 개와 취소 요청을 가정하고 진입·종료·최댓값을 기록하도록 설계합니다.

완료 기준: 엔진별 제한을 넘지 않고, 예외·취소 뒤에도 허가가 반환되는지 확인하는 검증 조건을 세웁니다. 작업 완료 상태와 파일별 상태가 항상 같지는 않다는 점도 설명합니다.

과제 5 · 고급

새 변환 간선 하나를 추가하는 설계서 작성하기

예시: 이미 알려진 텍스트 형식 하나에 대해 특정 출력으로 가는 자체 변환기를 설계합니다. 기존 경로와 겹치는지 먼저 확인하고, 임의의 새 형식 이름을 제품에 등록하는 것부터 시작하지 마세요.

  1. IConverter 구현, Edges, 비용, GetStatus()를 정의합니다.
  2. EngineRegistry.CreateAll() 등록과 기존 경로에 미치는 영향을 적습니다.
  3. 출력 할당·취소·진행률·원본 보존·다국어 오류 메시지를 포함합니다.
  4. 외부 엔진이면 배포 버전·해시·플랫폼·라이선스 계획을 추가합니다.

완료 기준: 직접 변환 성공뿐 아니라 새 우회 경로, 엔진 미설치, 잘못된 입력의 결과까지 검토합니다. 오래된 기여 문서와 현재 엔진 조회 정책의 차이도 설계서에 반영합니다.

학습 기록 요령
관찰한 사실과 예상 결과를 따로 적으세요

“테스트 파일에 이런 검증이 있다”, “내가 실행해 통과했다”, “아직 예상이다”는 다른 문장입니다. 근거 파일과 함수, 예상 입력·출력을 함께 남기면 나중에 소스가 바뀌어도 학습 기록을 검토할 수 있습니다.

9관련 기술 심화 학습 로드맵

한 주에 한 경계씩 이해하는 6주 과정

하루에 저장소 전체를 이해하려 하면 파일 형식의 세부사항에 묻히기 쉽습니다. 아래 과정은 한 주마다 읽을 파일, 설명할 개념, 남길 결과물을 정해 진도를 확인합니다. 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새 엔진을 배포하기 위한 변경 파일과 검증 계획

매주 한 기능을 입력부터 출력까지 설명할 수 있게 되면, 큰 저장소도 읽을 수 있는 작은 경로들의 모음이 됩니다.

9-1. 관심 분야에 따른 다음 갈림길

로드맵의 마지막 질문
새 기능을 어디에 넣을지 근거를 말할 수 있나요?

“형식 규칙이면 Core, 특정 도구의 구현이면 Engines, 화면 반응이면 App, OS 기능이면 Platform”이라는 출발점을 세우고 실제 참조 관계로 확인하세요. 정답 파일 하나를 외우는 것보다 변경의 책임과 영향을 설명하는 능력이 중요합니다.

10핵심 키워드 사전

이름을 코드 속 역할과 연결하는 짧은 사전
용어쉬운 설명
.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가 그 예입니다.
문자 조형 / 글꼴 대체문자를 문맥에 맞게 배치·결합하는 처리와, 없는 글꼴을 다른 글꼴로 바꾸는 처리는 서로 다릅니다.
네이티브 의존성 / ABIOS·CPU에 맞춘 바이너리와 그 바이너리끼리 호출하는 약속입니다. .NET 앱도 이 조건을 피하지 못합니다.
self-contained앱 배포물에 .NET 런타임을 포함하는 방식입니다. 모든 OS 라이브러리까지 포함한다는 뜻은 아닙니다.
SHA-256 / 준비용 폴더받은 엔진이 지정 파일과 같은지 확인하는 해시와, 설치가 완성되기 전에 작업하는 별도 폴더입니다.
테스트 대역 / 통합 테스트가짜 엔진으로 규칙만 검증하거나, 실제 엔진·파일까지 연결해 결과를 확인하는 서로 다른 검사입니다.
물리 줄 수 / 커버리지파일의 줄 수와 테스트가 실제 코드 경로를 실행한 비율은 다른 지표입니다.
shallow clone최근 일부 이력만 받은 복제본입니다. 현재 파일은 읽을 수 있어도 전체 개발 이력 통계에는 한계가 있습니다.

11참고 링크

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

분석 근거는 커밋에 고정하고, 후속 학습 문서는 별도로 찾기

11-1. 프로젝트와 근거 파일

11-2. 관련 기술의 공식 학습 자료

아래는 다음 학습을 위한 공식 문서 링크입니다. 본문에 인용한 버전과 Filee의 동작 근거는 최신 문서의 예제가 아니라 위 커밋의 프로젝트 파일과 소스입니다.

초판 관측표 (2026-10-23, 현재 규모 수치 아님)

항목값과 확인 범위
선정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 기준
최근 push2026-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 기준이며, 테스트 정의와 실제 실행 결과는 구별해야 합니다.