Windows.Media.Ocr에서 IronOCR로 마이그레이션하기
이 가이드는 Windows.Media.OCR에서 IronOCR로 전환하는 .NET 개발자를 위한 단계별 마이그레이션 경로를 제공합니다. 이 문서는 네임스페이스 제거, 프로젝트 파일 변경, 마이그레이션 과정에서 가장 빈번하게 발생하는 패턴에 대한 코드 마이그레이션 예시, 그리고 완료된 전환을 검증하기 위한 실용적인 체크리스트를 다룹니다.
Windows.Media.OCR(UWP/WinRT OCR)에서 마이그레이션해야 하는 이유
Windows.Media.OCR은 지정된 범위 내에서 잘 작동합니다. 이러한 경계는 좁으며, 프로젝트는 일상적으로 그 경계를 넘어 확장됩니다. 팀이 마이그레이션을 결정하는 이유는 예측 가능한 범주로 나뉩니다.
Windows TFM은 모든 비 Windows 대상을 차단합니다. 프로젝트 파일은 컴파일 시점에 네임스페이스가 해결되기 전에 net*-windows* Target Framework Moniker를 선언해야 합니다. 그 선언은 런타임 플래그가 아니라 빌드 제약 조건으로, 귀하의 프로젝트를 참조하는 모든 프로젝트로 전파됩니다. 공유 OCR 서비스 라이브러리, 웹 API, Linux에 배포된 백그라운드 워커 등 모든 항목이 동일한 제약 조건을 따릅니다. 이를 제거한다는 것은 Windows.Media.OCR을 제거하는 것을 의미합니다.
언어 가용성은 OS에 의해 런타임에 결정됩니다. 빌드 시점에 개발자가 결정하지 않습니다. OcrEngine.TryCreateFromLanguage은(는) 호스트 컴퓨터에 요청한 언어 팩이 없으면 null을 반환합니다. 개발자는 코드에서 언어 팩을 설치할 수 없으며, 애플리케이션 바이너리에 언어 팩을 번들로 제공할 수도 없고, 대체 모델을 제공할 수도 없습니다. 빌드 에이전트, CI 러너, 최소 구성 클라우드 VM, 컨테이너와 같은 자동화 환경에서는 언어 팩이 거의 설치되지 않습니다. 언어 팩 누락으로 인한 프로덕션 오류는 코드를 살펴보는 것만으로는 재현할 수 없습니다; 이는 대상 머신의 OS 구성을 확인해야 함을 의미합니다.
사전 처리 없음은 최적이 아닌 입력에 대한 복구 경로가 없음을 의미합니다. API는 SoftwareBitmap을(를) 수락하고 텍스트를 생성합니다. 이 두 지점 간의 이미지 품질 개선은 전적으로 개발자의 책임이며, Windows 전용인 별도의 Windows Imaging Component API를 사용하여 수행해야 합니다. 휴대폰 사진, 정렬이 맞지 않은 평판 스캔, 복사본 문서는 정확도를 은연중에 저하시키며, 결과를 진단하거나 개선할 수 있는 내장된 메커니즘이 없습니다.
PDF는 Enterprise 워크플로에서 가장 널리 사용되는 문서 형식입니다. Windows.Media.OCR에는 PDF 입력 경로가 없습니다. 스캔된 PDF를 처리하려면 외부 렌더러, 페이지별 래스터화 및 수동 결과 조립이 필요합니다. 해당 렌더러는 종속성, 라이선스 문제, 그리고 별도의 오류 발생 지점을 추가합니다. 이는 바로 "무료이며 내장된" 라이브러리가 피해야 했던 복잡성 그 자체입니다.
서버 측 배포는 구조적으로 지원되지 않습니다. Windows.Media.OCR은 클라이언트 애플리케이션을 대상으로 합니다. Windows Server에서 실행하려면 Desktop Experience 기능 팩이 필요하며, 이로 인해 VM 비용과 인프라 복잡성이 증가합니다. Docker 배포는 불가능합니다. Linux 기반 Azure Functions, AWS Lambda 및 기타 Linux 기반 컨테이너 워크로드에서는 해당 API를 참조할 수 없습니다.
WinRT 비동기 스택은 .NET Standard 패턴과 호환되지 않습니다. 단일 문자를 읽기 전까지여섯 개 이상의 체인 await 호출 - StorageFile, 스트림, BitmapDecoder, SoftwareBitmap, null 검사, RecognizeAsync - 이 필요합니다. 해당 체인을 백그라운드 서비스, Parallel.ForEach 루프 또는 표준 ASP.NET 컨트롤러에 통합하는 것은 번거롭습니다. WinRT IAsyncOperation 기계가 그 아래에 자리잡고 있으며, .NET의 Task 모델과의 상호작용은 UI 이외의 상황에서 미묘한 경계 사례를 만듭니다.
근본적인 문제
Windows.Media.OCR의 언어 지원은 배포 시점에 해결할 수 없는 런타임 알 수 없는 항목입니다:
// Windows.Media.Ocr: language availability decided by OS admin, not the developer
// Returns null on any machine without the language pack installed
var engine = OcrEngine.TryCreateFromLanguage(
new Windows.Globalization.Language("ja-JP"));
if (engine == null)
throw new InvalidOperationException(
"Japanese OCR unavailable — install the Japanese language pack in Windows Settings.");
// 아니요 recovery path. 아니요 bundled model. 아니요 fallback.
// IronOCR: language availability is a NuGet package, not an OS configuration
// dotnet add package IronOcr.Languages.Japanese
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.Japanese;
var result = ocr.Read("invoice.jpg"); // Works on any OS, any machine
Console.WriteLine(result.Text);
##IronOCR대 Windows.Media.OCR (UWP/WinRT OCR): 기능 비교
아래 표는 마이그레이션 결정과 관련된 전체 기능 범위를 다루고 있습니다.
| 기능 | Windows.Media.Ocr | IronOCR |
|---|---|---|
| 플랫폼: Windows 10/11 | 예 | 예 |
| 플랫폼: Windows Server | 제한적 (데스크톱 사용 경험 필수) | 예 |
| 플랫폼: Linux | 아니요 | 예 |
| 플랫폼: macOS | 아니요 | 예 |
| 플랫폼: Docker 컨테이너 | 아니요 | 예 |
| 플랫폼: Azure Functions (Linux) | 아니요 | 예 |
| 플랫폼: AWS Lambda | 아니요 | 예 |
| 프로젝트 TFM 요구 사항 | net*-windows* 필요함 | 없음 (표준 TFM) |
| 설치 | Windows 기본 제공 (NuGet 미포함) | 단일 NuGet 패키지 (IronOcr) |
| 이미지 입력 (JPG, PNG, BMP) | 예 (WinRT 파이프라인을 통해) | 예 |
| PDF 입력 | 아니요 | 예 (원어민) |
| 여러 페이지로 구성된 TIFF 입력 | 아니요 | 예 |
| 스트림 및 바이트 배열 입력 | 아니요 (StorageFile만 해당) | 예 |
| 원문 | 운영체제에 설치된 언어 팩 | 125개 이상의 번들 NuGet 패키지 |
| 언어 호환성 | 아니요 (기기에 따라 다름) | 예 (애플리케이션과 함께 배포) |
| 다국어 동시 | 아니요 | 예 |
| 전처리: 기울기 보정 | 아니요 | 예 (input.Deskew()) |
| 전처리: 노이즈 제거 | 아니요 | 예 (input.DeNoise()) |
| 전처리: 대비 | 아니요 | 예 (input.Contrast()) |
| 전처리: 이진화 | 아니요 | 예 (input.Binarize()) |
| 검색 가능한 PDF 출력 | 아니요 | 예 (result.SaveAsSearchablePdf()) |
| 단어별 신뢰도 점수 | 아니요 | 예 (word.Confidence) |
| 구조화된 출력(단락, 줄, 단어) | 줄만 | 페이지, 단락, 줄, 단어, 문자 |
| OCR 중 BarCode 판독 | 아니요 | 예 |
| 영역 기반 OCR | 아니요 | 예 (CropRectangle) |
| 동기식 OCR 경로 | 아니요 | 예 |
| 스레드 안전 병렬 처리 | 제한적 | 전체 |
| 상업적 지원 | 아니요 (Windows 플랫폼 팀) | 예 |
| 라이선스 모델 | 무료 (Windows 기본 제공) | 영구 ($999 Lite, $1,499 Pro, $2,999 Enterprise) |
빠른 시작: Windows.Media.OCR(UWP/WinRT OCR)에서 IronOCR로의 마이그레이션
1단계: NuGet 패키지 교체
Windows.Media.OCR에는 NuGet 패키지가 없습니다. 이 라이브러리는 Windows 런타임의 일부이며 Windows TFM을 통해 해결됩니다. 이를 제거한다는 것은 프로젝트 파일에서 Windows 전용 네임스페이스 참조와, 가능한 경우 Windows TFM을 제거하는 것을 의미합니다.
모든 소스 파일에서 Windows.Media.OCR 네임스페이스를 제거하십시오:
# Audit all files referencing Windows OCR namespaces
grep -r "Windows.Media.Ocr\|Windows.Graphics.Imaging\|Windows.Storage" --include="*.cs" .
IronOCR 설치:
IronOCR NuGet 패키지는 플랫폼 특정 TFMs 없이 net6.0, net7.0, net8.0, 및 net9.0을(를) 대상으로 합니다. Windows OCR 네임스페이스를 제거한 후, 프로젝트 파일에서 <TargetFramework>을 net8.0-windows10.0.19041.0에서 net8.0 (또는 해당 버전)으로 업데이트합니다. 프로젝트에 다른 WinRT API가 남아 있지 않은 경우.
단계 2: 네임스페이스 업데이트
세 개의 Windows OCR 네임스페이스를 단일IronOCR네임스페이스로 대체하십시오:
// Before (Windows.Media.Ocr)
using Windows.Media.Ocr;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Globalization;
// After (IronOCR)
using IronOcr;
단계 3: 라이선스 초기화
애플리케이션 시작 시 한 번 라이센스 초기화 호출하기 — Program.cs, Startup.cs 또는 애플리케이션 호스트 빌더에서:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"IronOCR 라이선스 페이지에서 무료 체험판 키를 받을 수 있으며, 이를 사용하면 체험판 워터마크를 제거할 수 있습니다.
코드 마이그레이션 예제
백그라운드 서비스에서 WinRT 비동기 체인 대체하기
Windows.Media.OCR은 인식이 시작되기 전에 최소 6개의 연쇄된 비동기 작업이 필요합니다. 문서 큐를 처리하는 백그라운드 서비스에서는 그 체인이 루프 내에서 실행되며, 각 반복에서SoftwareBitmap 처분, null 검사 및 WinRT IAsyncOperation 상호운용성이 마찰을 추가합니다.
Windows.Media.OCR 접근 방식:
// Windows.Media.Ocr: full async chain required per document
// Requires net8.0-windows10.0.19041.0 TFM — cannot deploy to Linux workers
public async Task<List<string>> ProcessQueueAsync(IEnumerable<string> imagePaths)
{
var engine = OcrEngine.TryCreateFromUserProfileLanguages();
if (engine == null)
throw new InvalidOperationException("No OCR language pack installed on this machine.");
var results = new List<string>();
foreach (var path in imagePaths)
{
// Each document: 4 async steps before RecognizeAsync
var file = await StorageFile.GetFileFromPathAsync(path);
using var stream = await file.OpenAsync(FileAccessMode.Read);
var decoder = await BitmapDecoder.CreateAsync(stream);
var bitmap = await decoder.GetSoftwareBitmapAsync();
var ocrResult = await engine.RecognizeAsync(bitmap);
results.Add(ocrResult.Text);
bitmap.Dispose();
}
return results;
}
IronOCR 접근 방식:
// IronOCR: one call per document, no WinRT, no SoftwareBitmap, no null checks
// Runs on Windows, Linux, macOS, Docker — same binary, no TFM change
public List<string> ProcessQueue(IEnumerable<string> imagePaths)
{
var results = new List<string>();
foreach (var path in imagePaths)
{
var result = new IronTesseract().Read(path);
results.Add(result.Text);
}
return results;
}
IronOCR 버전은 StorageFile 왕복, BitmapDecoder, SoftwareBitmap 라이프사이클 및 null 검사 구문을 제거합니다. 비동기 네이티브 서비스를 위해, IronOCR은 비동기 경로를 제공합니다이 Task 기반 파이프라인에 WinRT 상호운용성 오버헤드 없이 깔끔하게 통합됩니다. IronTesseract 설정 가이드에는 대용량 처리 큐 시나리오에 대한 인스턴스 수명 주기 권장 사항이 포함되어 있습니다.
메모리 내 이미지 데이터에 대한 SoftwareBitmap 변환 제거
이미 메모리에 이미지 데이터를 보유한 애플리케이션 - 네트워크 다운로드, 데이터베이스 블롭 또는 카메라 캡처 콜백 - 은 Windows.Media.Ocr가 처리하기 전에 해당 데이터를 SoftwareBitmap로 변환해야 합니다. 그 변환 경로는 스트림을 필요로 하는 BitmapDecoder를 거치며 이는 바이트 배열을 MemoryStream에 복사하는 것을 의미합니다. IronOCR은 바이트 배열과 스트림을 직접 입력으로 받아들입니다.
Windows.Media.OCR 접근 방식:
// Windows.Media.Ocr: byte array must travel through WinRT stream → BitmapDecoder → SoftwareBitmap
public async Task<string> RecognizeFromBytesAsync(byte[] imageBytes)
{
var engine = OcrEngine.TryCreateFromUserProfileLanguages();
if (engine == null)
throw new InvalidOperationException("No OCR language available.");
// Copy byte array into InMemoryRandomAccessStream (WinRT type)
using var ras = new Windows.Storage.Streams.InMemoryRandomAccessStream();
using var writer = new Windows.Storage.Streams.DataWriter(ras);
writer.WriteBytes(imageBytes);
await writer.StoreAsync();
ras.Seek(0);
var decoder = await BitmapDecoder.CreateAsync(ras);
var bitmap = await decoder.GetSoftwareBitmapAsync();
var result = await engine.RecognizeAsync(bitmap);
bitmap.Dispose();
return result.Text;
}
IronOCR 접근 방식:
// IronOCR: byte array loads directly into OcrInput — no conversion, no WinRT types
public string RecognizeFromBytes(byte[] imageBytes)
{
using var input = new OcrInput();
input.LoadImage(imageBytes); // direct byte array load
var result = new IronTesseract().Read(input);
return result.Text;
}
Windows.Media.Ocr 경로는 WinRT 유형이므로 Windows 외부에서는 인스턴스를 만들 수 없는 InMemoryRandomAccessStream가 필요하며, DataWriter, BitmapDecoder, 및 SoftwareBitmap도 필요합니다.IronOCR경로는 OcrInput.LoadImage(byte[])를 사용하고 결과를 두 줄로 생성합니다. 스트림 입력 가이드에서 바이트 배열 입력과 동일한 간단함을 따르는 Stream 기반 로딩 패턴을 참조하십시오.
OS 연동 없이 다국어 문서 처리
단일 처리 단계에서 영어, 프랑스어, 독일어 텍스트를 인식해야 하는 다국어 청구서 처리 파이프라인은 Windows.Media.OCR을 사용할 경우 아키텍처적 한계에 직면하게 됩니다. 이 API는 엔진 인스턴스당 하나의 언어만 허용합니다. 여러 언어가 혼합된 문서를 처리하려면 가장 유력한 단일 언어 엔진을 사용하거나, 인식 작업을 세 번 수행한 후 결과를 병합해야 하는데, 두 방법 모두 신뢰할 수 있는 결과를 산출하지 못합니다.
Windows.Media.OCR 접근 방식:
// Windows.Media.Ocr: one language per engine, no simultaneous multi-language support
// Each language requires a separate language pack installed on the machine
public async Task<string> RecognizeMultiLanguageAsync(SoftwareBitmap bitmap)
{
// Must pick ONE language — no simultaneous recognition
var engine = OcrEngine.TryCreateFromLanguage(
new Windows.Globalization.Language("en-US"));
if (engine == null)
throw new InvalidOperationException("English language pack not installed.");
// French and German text on the same document will be misrecognized
var result = await engine.RecognizeAsync(bitmap);
return result.Text;
}
IronOCR 접근 방식:
// IronOCR: simultaneous multi-language recognition in a single pass
// Language packs are NuGet packages — no OS coordination required
// dotnet add package IronOcr.Languages.French
// dotnet add package IronOcr.Languages.German
public string RecognizeMultiLanguage(string documentPath)
{
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.English + OcrLanguage.French + OcrLanguage.German;
var result = ocr.Read(documentPath);
// Structured output: walk paragraphs with location data
foreach (var page in result.Pages)
{
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($"[{paragraph.X},{paragraph.Y}] {paragraph.Text}");
}
}
return result.Text;
}
IronOCR은 단일 인식 단계에서 여러 언어 모델을 결합하므로, 특정 영역에서 어떤 언어가 사용되는지 추측할 필요가 없습니다. 다중 언어 OCR 가이드는 언어 팩 설치 및 125개 이상 지원되는 모든 언어에 대한 OcrLanguage 열거형 값을 다룹니다. 언어 색인에는 CJK 문자, 아랍어, 히브리어, 데바나가리 문자, 키릴 문자 계열을 포함한 전체 목록이 수록되어 있습니다.
병렬 처리를 통한 서버 측 OCR 지원
Windows.Media.OCR은 Linux의 서버 환경에서는 실행될 수 없으며, 크로스 플랫폼 호스트의 표준 ASP.NET Core 컨트롤러에서 호출할 수 없고, 서버 환경에서 UI 스레드가 아닌 스레드에서 호출할 경우 정의되지 않은 동작을 보입니다. OCR 엔드포인트를 Windows 전용 데스크톱 애플리케이션에서 확장 가능한 웹 API로 이전하는 팀은 이 세 가지 제약 조건을 동시에 모두 충족하게 됩니다.
Windows.Media.OCR 접근 방식:
// Windows.Media.Ocr: cannot run on Linux, Docker, or Azure Functions on Linux
// UWP/WinRT assumptions about thread context cause failures in ASP.NET pipelines
// The entire approach below is non-deployable outside Windows with Desktop Experience
[HttpPost("ocr")]
public async Task<IActionResult> RecognizeDocument(IFormFile file)
{
// WinRT requires STA thread context in some scenarios — not guaranteed in ASP.NET
// Cannot deploy this controller to a Linux App Service plan
using var stream = file.OpenReadStream();
// InMemoryRandomAccessStream is a WinRT type — does not exist on Linux
// var ras = new InMemoryRandomAccessStream(); // compile error on net8.0 TFM
return StatusCode(503, "Windows-only — cannot deploy cross-platform.");
}
IronOCR 접근 방식:
// IronOCR: ASP.NET Core controller running on Linux, Docker, or Windows — same code
[HttpPost("ocr")]
public async Task<IActionResult> RecognizeDocument(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("No file provided.");
using var memoryStream = new MemoryStream();
await file.CopyToAsync(memoryStream);
var imageBytes = memoryStream.ToArray();
using var input = new OcrInput();
input.LoadImage(imageBytes);
input.Deskew(); // straighten uploaded scans automatically
input.DeNoise(); // remove mobile camera noise
var result = new IronTesseract().Read(input);
return Ok(new
{
Text = result.Text,
Confidence = result.Confidence,
Pages = result.Pages.Count
});
}
이 컨트롤러는 수정 없이 Linux App Service, Docker 및 AWS Lambda에 배포할 수 있습니다. Docker 배포 가이드는 Linux 기본 이미지에서 필요한 단일 apt-get 종속성을 다룹니다. Azure 배포 가이드와 AWS 가이드는 클라우드별 구성 방법을 단계별로 안내합니다.
스캔된 아카이브에서 검색 가능한 PDF 생성
Windows.Media.OCR은 일반 텍스트 문자열을 생성합니다. 출력 형식은 OcrResult.Text 및 OcrResult.Lines의 라인 기하학을 제외하고 없습니다. 문서 관리 시스템 및 규정 준수 워크플로에서 흔히 요구되는 스캔된 아카이브를 검색 가능한 PDF로 변환하려면, PDF 출력 레이어를 구성하기 위해 별도의 라이브러리가 필요합니다. IronOCR은 기본적으로 검색 가능한 PDF를 생성합니다.
Windows.Media.OCR 접근 방식:
// Windows.Media.Ocr: plain text output only
// Searchable PDF requires external PDF library + manual text layer construction
public async Task<string> GetTextOnlyAsync(SoftwareBitmap bitmap)
{
var engine = OcrEngine.TryCreateFromUserProfileLanguages();
if (engine == null)
throw new InvalidOperationException("No OCR language available.");
var result = await engine.RecognizeAsync(bitmap);
// result.Text is all you get
// Producing a searchable PDF requires an entirely separate library
return result.Text;
}
IronOCR 접근 방식:
// IronOCR: searchable PDF output is one method call on OcrResult
public void ProcessScannedArchive(IEnumerable<string> pdfPaths, string outputDirectory)
{
foreach (var sourcePdf in pdfPaths)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdf(sourcePdf); // native PDF input — no external renderer
input.Deskew(); // correct scan misalignment per page
input.DeNoise(); // remove scanner speckle
var result = ocr.Read(input);
var outputFileName = Path.Combine(
outputDirectory,
Path.GetFileNameWithoutExtension(sourcePdf) + "-searchable.pdf");
result.SaveAsSearchablePdf(outputFileName);
Console.WriteLine($"Processed: {sourcePdf} → {outputFileName} " +
$"({result.Pages.Count} pages, {result.Confidence:F1}% confidence)");
}
}
SaveAsSearchablePdf 호출은 원본 스캔 이미지 위에 텍스트 레이어를 삽입하여 시각적 충실도를 유지하면서 모든 PDF 뷰어에서 전체 텍스트 검색 및 Ctrl+F를 가능하게 합니다. 검색 가능한 PDF 사용 설명서에는 글꼴 임베딩, 텍스트 레이어 배치 및 다중 페이지 출력 옵션에 대한 내용이 포함되어 있습니다. PDF 입력 가이드에는 암호로 보호된 PDF 및 대용량 아카이브의 페이지 범위 선택에 대한 내용이 포함되어 있습니다.
WORD 단위 좌표를 활용한 구조화된 데이터 추출
Windows.Media.Ocr는 라인 수준 텍스트와 경계 사각형을 가진 OcrResult.Lines를 노출합니다. 단어별 기하학은 OcrLine.Words에서 OcrWord.BoundingRect와 함께 존재하지만 단락, 신뢰 점수 및 문자 수준 데이터는 없습니다. 양식 필드 추출이나 송장 내역 분석의 경우, 줄의 기하학적 구조만으로는 불충분합니다. 구조화된 필드를 주변 텍스트와 구별하기 위해서는 단락 경계와 WORD 신뢰도 점수가 필요합니다.
Windows.Media.OCR 접근 방식:
// Windows.Media.Ocr: line-level geometry, no paragraph grouping, no confidence scores
public async Task<List<string>> ExtractLineTextAsync(SoftwareBitmap bitmap)
{
var engine = OcrEngine.TryCreateFromUserProfileLanguages();
if (engine == null)
throw new InvalidOperationException("No OCR language available.");
var result = await engine.RecognizeAsync(bitmap);
var lineTexts = new List<string>();
foreach (var line in result.Lines)
{
// Line text + word bounding rects — no paragraph grouping, no confidence
lineTexts.Add(line.Text);
}
return lineTexts;
}
IronOCR 접근 방식:
// IronOCR: full hierarchy — pages, paragraphs, lines, words, characters
// Each element carries coordinates and confidence for downstream validation
public void ExtractStructuredData(string documentPath)
{
var result = new IronTesseract().Read(documentPath);
Console.WriteLine($"Overall confidence: {result.Confidence:F1}%");
foreach (var page in result.Pages)
{
Console.WriteLine($"\n--- Page {page.PageNumber} ---");
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($"Paragraph at ({paragraph.X},{paragraph.Y}): {paragraph.Text}");
// Filter words below confidence threshold for validation workflows
var lowConfidence = paragraph.Words
.Where(w => w.Confidence < 70)
.ToList();
if (lowConfidence.Any())
{
Console.WriteLine($" Low-confidence words: " +
string.Join(", ", lowConfidence.Select(w => $"'{w.Text}' ({w.Confidence:F0}%)")));
}
}
}
}
구조화된 결과 모델 — Pages, Paragraphs, Lines, Words, Characters — 양식 필드 추출, 인보이스 파싱 및 문서 레이아웃 분석을 위해 필요한 좌표 및 신뢰 데이터를 제공합니다. 읽기 결과 가이드는 OcrResult 전체 개체 그래프를 문서화합니다. 신뢰도 점수 가이드에서는 WORD별 신뢰도 값을 활용하여 불확실한 추출 결과를 표시하고, 이를 사람이 검토하도록 하는 방법을 설명합니다.
Windows.Media.OCR API와IronOCR매핑 참조
| Windows.Media.Ocr | IronOCR |
|---|---|
OcrEngine.TryCreateFromLanguage(lang) | new IronTesseract() + ocr.Language = OcrLanguage.X |
OcrEngine.TryCreateFromUserProfileLanguages() | new IronTesseract() (기본 영어; (null 반환 없음) |
engine.RecognizeAsync(softwareBitmap) | ocr.Read("image.jpg") 또는 ocr.Read(ocrInput) |
StorageFile.GetFileFromPathAsync(path) | ocr.Read("path") 직접 (파일 핸들 필요 없음) |
file.OpenAsync(FileAccessMode.Read) | 제거됨 — OcrInput이(가) 직접 로드됩니다 |
BitmapDecoder.CreateAsync(stream) | input.LoadImage(stream)을(를) OcrInput 통해 |
decoder.GetSoftwareBitmapAsync() | 제거됨 — IronOCR에는 SoftwareBitmap이(가) 없습니다 |
SoftwareBitmap (WinRT 유형) | 제거됨 — OcrInput은(는) 바이트, 스트림, 파일 경로를 허용합니다 |
InMemoryRandomAccessStream (WinRT 유형) | new MemoryStream() + input.LoadImage(stream) |
OcrResult.Text | OcrResult.Text |
OcrResult.Lines | OcrResult.Lines (또한 Pages, Paragraphs, Words, Characters) |
OcrLine.Text | OcrResult.Lines[i].Text |
OcrLine.Words | OcrResult.Words 또는 page.Paragraphs[i].Words |
OcrWord.BoundingRect | word.X, word.Y, word.Width, word.Height |
| 동등한 것 없음 | result.Confidence (전반) / word.Confidence (단어별) |
| 동등한 것 없음 | result.SaveAsSearchablePdf("output.pdf") |
| 동등한 것 없음 | input.LoadPdf("document.pdf") |
| 동등한 것 없음 | input.Deskew(), input.DeNoise(), input.Contrast() |
| 동등한 것 없음 | ocr.Language = OcrLanguage.A + OcrLanguage.B (동시) |
| 동등한 것 없음 | ocr.Configuration.ReadBarCodes = true |
| 동등한 것 없음 | input.LoadImage(byteArray) |
일반적인 마이그레이션 문제와 해결책
문제 1: 마이그레이션 후에도 프로젝트 파일에 Windows TFM이 여전히 필요함
Windows.Media.Ocr: WinRT 유형을 해결하려면 <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework> 선언이 필요합니다. 동일한 프로젝트 내의 다른 WinRT 종속성을 확인하지 않고 Windows.Media.OCR 참조를 제거하면 TFM이 그대로 남아 크로스 플랫폼 빌드가 불가능해질 수 있습니다.
해결 방법: Windows OCR 네임스페이스 참조를 제거한 후, TFM을 변경하기 전에 프로젝트 내에서 남아 있는 WinRT API 사용 여부를 검색하십시오:
# Find remaining WinRT API usage before removing the Windows TFM
grep -r "Windows\." --include="*.cs" .
grep -r "WinRT\|IAsyncOperation\|StorageFile\|SoftwareBitmap" --include="*.cs" .
WinRT 참조가 남아 있지 않은 경우, 프로젝트 파일을 업데이트하십시오:
<!-- Before -->
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<!-- After -->
<TargetFramework>net8.0</TargetFramework>
다른 WinRT 기능(Windows 알림, 셸 통합, XAML)이 계속 사용되는 경우, TFM을 프로젝트 전체에서 제거하기보다는 OCR 호출을 인터페이스 뒤에 추상화하고 플랫폼별 구현을 제공하십시오.
문제 2: Null 엔진 검사에는 IronOCR에 상응하는 기능이 없습니다
Windows.Media.Ocr: 모든 TryCreateFromLanguage 및 TryCreateFromUserProfileLanguages 호출은 null을 반환할 수 있습니다. 기존 코드에는 모두 null 엔진에서 예외를 발생시키거나 분기 처리하는 null 검사 가드 절이 포함되어 있습니다.
해결책: IronOCR은 초기화 실패 시 null을 반환하는 대신 구조화된 예외를 발생시킵니다. null 검사 가드 절을 제거하십시오. 초기화 오류를 호출자에게 전달해야 하는 경우 표준 try/catch 블록으로 감싸십시오:
// Before: null-check pattern
var engine = OcrEngine.TryCreateFromUserProfileLanguages();
if (engine == null)
throw new InvalidOperationException("OCR unavailable.");
// After: no null — IronTesseract throws if misconfigured
try
{
var result = new IronTesseract().Read("document.jpg");
}
catch (IronOcr.Exceptions.OcrException ex)
{
// structured exception with diagnostic message
logger.LogError("OCR failed: {Message}", ex.Message);
}
문제 3: 기존 메서드 시그니처의 SoftwareBitmap 매개변수
Windows.Media.Ocr: 유틸리티 메서드, 서비스 및 리포지토리 클래스는 SoftwareBitmap을(를) 매개변수 유형으로 수락할 수 있습니다. Windows TFM이 제거된 상태에서는 해당 메서드 시그니처를 컴파일할 수 없습니다.
해결책: SoftwareBitmap 매개변수를 byte[] 또는 Stream로 변경하십시오. IronOCR의 OcrInput는 둘 다 직접 허용합니다. 이전에 SoftwareBitmap을(를) 생성했던 호출 사이트는 대신 기본 데이터를 전달할 수 있습니다:
// Before: SoftwareBitmap parameter — cannot compile cross-platform
public async Task<string> RecognizeAsync(SoftwareBitmap bitmap) { ... }
// After: byte array parameter — compiles on all platforms
public string Recognize(byte[] imageBytes)
{
using var input = new OcrInput();
input.LoadImage(imageBytes);
return new IronTesseract().Read(input).Text;
}
문제 4: 비동기 호출 전용 호출자는 동기식 IronOCR을 직접 사용할 수 없습니다
Windows.Media.Ocr: 모든 인식 호출은 async입니다. 코드베이스 전반에 걸쳐 호출자는 await을 사용하고 Task<string>을 반환합니다. IronOCR의 동기 Read 메서드로 전환하는 것은 가능한 솔루션이지만 async이(가) 아키텍처적으로 존재했던 환경에서는 차단 호출을 유발할 수 있습니다.
해결책: IronOCR은 필요한 호출자에게 비동기 경로를 제공합니다. 기존 비동기 메서드에서 CPU에 바운드된 래핑에 Task.Run을 사용하거나 네이티브 비동기 API를 사용하십시오:
// Option A: wrap synchronous call in Task.Run for async callers
public async Task<string> RecognizeAsync(string imagePath)
{
return await Task.Run(() => new IronTesseract().Read(imagePath).Text);
}
// Option B:IronOCR async path
// See: https://ironsoftware.com/csharp/ocr/how-to/async/
비동기 OCR 가이드에는 '실행 후 잊어버리기(fire-and-forget)' 또는 진행 상황 보고 패턴이 필요한 시나리오를 위한 내장 비동기 API가 설명되어 있습니다.
문제 5: Windows 언어 태그 형식이 직접 매핑되지 않음
Windows.Media.Ocr: 언어는 Windows.Globalization.Language("fr-FR")에 전달된 BCP-47 문자열 태그를 사용하여 지정됩니다. 해당 문자열 태그에는 IronOCR에 직접 대응하는 항목이 없습니다.
해결책: BCP-47 언어 태그를 OcrLanguage 열거형으로 매핑하십시오. 일반적인 언어의 경우 매핑은 간단합니다:
// Before: BCP-47 string tags
var engine = OcrEngine.TryCreateFromLanguage(
new Windows.Globalization.Language("fr-FR"));
// After: OcrLanguage enum
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.French;
// Also: OcrLanguage.German, OcrLanguage.Japanese, OcrLanguage.Arabic, etc.
전체 매핑 정보는 IronOCR 언어 카탈로그에서 확인할 수 있습니다. 주요 열거형에 나열되지 않은 언어의 경우, 사용자 정의 언어 팩 지원은 .traineddata 파일을 직접 로드하도록 다룹니다.
문제 6: FileAccessMode.Read에 대한 대체 기능이 없음
Windows.Media.Ocr: file.OpenAsync(FileAccessMode.Read)은(는) WinRT 전용 파일 여는 패턴입니다. FileAccessMode 열거형은 표준 .NET에 존재하지 않습니다.
해결책: 표준 System.IO.File.ReadAllBytes 또는 FileStream으로 대체하십시오. OcrInput은 둘 다 수락합니다:
// Before: WinRT file access
using var stream = await file.OpenAsync(FileAccessMode.Read);
// After: standard .NET
var imageBytes = File.ReadAllBytes(imagePath);
using var input = new OcrInput();
input.LoadImage(imageBytes);
Windows.Media.OCR (UWP/WinRT OCR) 마이그레이션 체크리스트
사전 마이그레이션
변경 사항을 적용하기 전에 코드베이스를 검토하십시오:
# Find all Windows OCR namespace usages
grep -rn "using Windows.Media.Ocr" --include="*.cs" .
grep -rn "using Windows.Graphics.Imaging" --include="*.cs" .
grep -rn "using Windows.Storage" --include="*.cs" .
grep -rn "using Windows.Globalization" --include="*.cs" .
# Find WinRT type usages
grep -rn "OcrEngine\|SoftwareBitmap\|BitmapDecoder\|StorageFile" --include="*.cs" .
grep -rn "TryCreateFromLanguage\|TryCreateFromUserProfileLanguages\|RecognizeAsync" --include="*.cs" .
grep -rn "InMemoryRandomAccessStream\|DataWriter\|FileAccessMode" --include="*.cs" .
# Find project files with Windows TFM
grep -rn "net.*-windows" --include="*.csproj" .
# Count files requiring changes
grep -rl "Windows.Media.Ocr\|Windows.Graphics.Imaging\|SoftwareBitmap" --include="*.cs" . | wc -l
영향을 받은 파일의 수, 사용 중인 언어 태그 ("en-US", "fr-FR" 등) 및 공용 메서드 서명에 WinRT 유형이 나타나는 경우 (이는 내부 재작성 외에도 API 표면 변경이 필요합니다)를 기록하십시오.
코드 마이그레이션
IronOcrNuGet 패키지를 설치하십시오:dotnet add package IronOcrProgram.cs나Startup.cs에서 라이센스 초기화 호출을 추가하십시오:IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";- 모든 소스 파일에서
using Windows.Media.Ocr;을 제거합니다 - 모든 소스 파일에서
using Windows.Graphics.Imaging;을 제거합니다 - 모든 소스 파일에서
using Windows.Storage;을 제거합니다 - 모든 소스 파일에서
using Windows.Globalization;을 제거합니다 - 모든 OCR 수행 파일에
using IronOcr;을 추가합니다 - 모든
OcrEngine.TryCreateFromLanguage(new Language("xx-XX"))호출을new IronTesseract()으로 대체하고ocr.Language = OcrLanguage.X을 설정하십시오 - 모든
OcrEngine.TryCreateFromUserProfileLanguages()호출을new IronTesseract()으로 교체하십시오 - 엔진 생성 결과에 대한 모든 null 검사 보호 절 제거
- 메서드 서명에서
SoftwareBitmap매개변수를byte[]또는Stream으로 교체하십시오 StorageFile+BitmapDecoder+SoftwareBitmap구성 체인을OcrInput.LoadImage(path),OcrInput.LoadImage(bytes)또는OcrInput.LoadImage(stream)으로 교체하십시오engine.RecognizeAsync(bitmap)을(를)ocr.Read(path)이나ocr.Read(input)으로 대체하십시오InMemoryRandomAccessStream및DataWriter사용을MemoryStream로 대체하십시오- Windows BCP-47 언어 태그 문자열을
OcrLanguage열거형 값으로 대체하십시오; 필요한 언어별 NuGet Install-Package .csproj파일에서<TargetFramework>을 업데이트하여 WinRT API가 남아 있지 않은 경우-windowsX.Y.Z접미사를 제거합니다
마이그레이션 이후
- Windows TFM 접미사 없이
net8.0(또는 귀하의 대상 버전)을 타겟으로 컴파일되는지 확인하십시오 mcr.microsoft.com/dotnet/aspnet:8.0을 사용하여 Linux 환경이나 Docker 컨테이너에서 프로젝트가 컴파일되고 실행되는지 확인하십시오- 테스트 Suite 내 각 문서 유형에 대해 OCR 출력 텍스트가 예상 결과와 일치하는지 확인하십시오 -IronOCR언어 NuGet 패키지를 사용하여 이전에 지원되었던 모든 언어에서 올바른 출력이 생성되는지 확인하십시오.
- 단일 인식 처리 단계에서 다국어 문서가 올바른 결과를 산출하는지 확인
- Windows 언어 팩이 설치되지 않은 기계에서 엔진 초기화 시
NullReferenceException또는InvalidOperationException이 발생하지 않는지 확인하십시오 - 정리된 입력 문서와 저품질 입력 문서의
result.Confidence값이 예상 범위 내에 있는지 확인하십시오 - 애플리케이션이 문서를 생성하는 경우,
SaveAsSearchablePdf출력이 PDF 뷰어에서 올바르게 열리고 텍스트 검색을 지원하는지 확인하십시오 - 기존 병렬 또는 멀티스레드 처리 경로를 실행하고 부하 상태에서 스레드 안전성을 확인하십시오
- 대상 환경(Docker, Azure App Service, AWS, Linux 서버)에 배포하고, 최소 한 번의 전체 엔드투엔드 OCR 작업을 실행합니다.
##IronOCR로 마이그레이션할 때의 주요 이점
크로스 플랫폼 배포는 더 이상 코드를 다시 작성하는 문제가 아니라 구성 설정의 문제가 되었습니다. 마이그레이션 후, OCR 구성 요소는 Windows, Linux, macOS, Docker 및 모든 주요 클라우드 제공업체에서 동일하게 실행됩니다. 호스팅 비용을 절감하기 위해 OCR 워크로드를 Windows VM에서 Linux 컨테이너로 이동하는 것은 배포 작업입니다. Linux 배포 가이드와 Docker 배포 가이드는 Linux 기본 이미지에서 필요한 한 줄의 종속성 추가 방법을 다룹니다.
언어 지원은 애플리케이션 바이너리와 함께 제공됩니다. 언어 팩은 NuGet 패키지로 설치되며IronOCR패키지와 버전이 고정되어 있습니다. 애플리케이션이 인식할 수 있는 언어 세트는 프로젝트 파일에 정의되어 있으며, 개발자 워크스테이션, CI 실행기, 스테이징 서버, 프로덕션 호스트 등 모든 시스템에서 동일합니다. OS 관리자의 조정, 그룹 정책 예외, 런타임 null 검사 등이 필요하지 않습니다.
외부 도구 없이 OCR 정확도가 향상됩니다. 전처리 파이프라인 — Deskew, DeNoise, Contrast, Binarize, Sharpen, Scale — 은IronOCR안에서 인식 엔진이 이미지를 보기 전에 실행됩니다. 스캔 정렬 불량이나 노이즈로 인해 Windows.Media.OCR에서 품질이 저하된 결과물을 생성했던 문서도, 외부 이미지 처리 종속성을 추가하지 않고도 품질이 개선됩니다. 이미지 품질 보정 가이드와 필터 마법사는 각 문서 유형에 적합한 필터 조합을 찾는 데 도움을 줍니다.
PDF 워크플로가 단일 라이브러리로 통합되었습니다. Windows.Media.OCR과 PDF 입력을 연결하기 위해 필요했던 외부 PDF 렌더러는 더 이상 필요하지 않습니다. 스캔된 PDF 아카이브는 이미지와 동일한 IronTesseract.Read 호출을 통해 처리됩니다. 검색 가능한 PDF 출력은 결과 객체의 메서드입니다. 두 개의 라이브러리 아키텍처는 버전 관리, 라이선스 관리 부담, 배포 범위를 포함하여 사라집니다.
구조화된 출력은 문서 인텔리전스 파이프라인을 가능하게 합니다. OcrResult 계층 구조 — Pages, Paragraphs, Lines, Words, Characters — 는 인보이스 필드 추출, 양식 파싱 및 문서 분류에 필요한 데이터를 제공합니다. Windows.Media.OCR의 줄 단위 출력 결과는 이러한 워크플로에는 부적합합니다. IronOCR을 사용하면 신뢰도 필터링된 단어 추출, 단락 경계 감지, 좌표 기반 필드 매핑을 별도의 라이브러리 없이도 기본 기능으로 활용할 수 있습니다.
영구 라이선스는 무제한적인 인프라 의존성을 대체합니다. 이종 시스템으로 구성된 환경 전반에 걸쳐 Windows 언어 팩을 설치하고 유지 관리하는 비용, Windows Server Desktop Experience 라이선스 비용, 그리고 Windows 전용 CI 인프라 비용은 실제로 존재하지만 분산되어 있습니다. 이러한 비용은 OCR 예산의 별도 항목으로 나타나기보다는 IT 지원 요청이나 인프라 예산에 반영됩니다. $999IronOCR Lite 라이센스는 단일 개발자 프로젝트에서 그 오버헤드를 제거합니다. $1,499의 Professional License는 10명의 개발자를 지원합니다. 두 제품 모두 1회 구매 시 1년간의 업데이트가 포함됩니다.
