IRONSOFTWAREHOME
동영상

C#에서 차량 번호판에 대한 OCR을 수행하는 방법

칸나오팟 우돈판트
Kannapat Udonpant
Updated: 2026년 8월 1일

이 가이드는 코팍스 옴니페이지 Capture SDK(현재 Tungsten Automation으로 판매됨)에서 IronOCR 로 OCR 워크로드를 이전하는 .NET 개발자를 위한 것입니다. 이 문서에서는 SDK 설치 프로그램 종속성 제거, 엔진 수명 주기 절차 제거, 영역 기반 인식 패턴 교체, 오류 처리 현대화 등 전체 마이그레이션 경로를 다룹니다. 비교 기사를 미리 읽을 필요는 없습니다.

Kofax OmniPage(텅스텐)에서 마이그레이션해야 하는 이유는 무엇입니까?

OmniPage Capture SDK는 NuGet , Docker, CI/CD 파이프라인이 등장하기 이전 시대의 Enterprise 문서 관리 인프라를 위해 설계되었습니다. 2005년에는 타당해 보였던 건축적 선택들이 2026년에는 오히려 마찰을 일으킨다.

SDK 설치 프로그램은 NuGet 환경에 적합하지 않습니다. OmniPage 코드를 실행하는 모든 개발 머신, 빌드 에이전트 및 프로덕션 서버는 컴파일 전에 Tungsten SDK 설치 프로그램을 실행해야 합니다. 복원할 .csproj 패키지 참조가 없습니다. SDK 버전을 업그레이드하려면 전체 시스템에 대해 설치 프로그램을 다시 실행해야 합니다. 새로운 개발자는 SDK 라이선스를 관리하는 담당자에게 연락하여 설치 프로그램 접근 권한을 받을 때까지 기다리지 않고는 프로젝트를 실행할 수 없습니다.

라이선스 파일은 운영 상의 책임입니다. .lic 파일은 모든 시스템에서 특정 경로에 있어야 하며, 이는 engine.Initialize()를 호출하는 경우에 해당합니다. 새 서버에 배포하고 파일을 삭제하면 모든 OCR 호출이 OCR 오류가 아닌 라이선스 예외와 함께 실패합니다. 부동 라이선스를 사용하고 애플리케이션 서버와 라이선스 서버 사이에 네트워크 분할이 있을 경우 모든 Initialize() 호출이 연결 복구 전까지 실패하게 되며, 어제 라이선스를 성공적으로 검증했더라도 상관 없습니다.

엔진 라이프사이클 관리가 오류 경로에서 자원을 누출합니다. OmniPageEngine.Shutdown()는 예외 처리기, 조기 반환, 타임아웃과 같은 모든 코드 경로에서 호출되어야 하며 그렇지 않으면 라이선스 서버의 체크아웃 타임아웃이 만료될 때까지 부동 라이선스 좌석이 잠긴 상태로 남습니다. 이 제약 조건을 방어적으로 작성하려면 엔진 종료가 생략되는 것을 방지하기 위한 IDisposable 패턴으로 모든 통합 지점을 감싸야 합니다.

하드웨어 지문 인식은 최신 배포 방식과 충돌합니다. OmniPage 활성화는 하드웨어와 연동됩니다. 컨테이너 재시작, VM 마이그레이션 및 클라우드 자동 확장은 모두 하드웨어 ID 변경을 수반하며, 이로 인해 재활성화 요구 사항이 발생합니다. 자동 확장과 호환되지 않는 배포 모델은 클라우드 인프라와 호환되지 않는 배포 모델입니다.

페이지당 가격 책정은 규모가 커질수록 예측하기 어렵습니다. 신규 고객 유치나 밀린 작업 일괄 처리와 같은 문서 처리량 급증은 누구도 예산에 반영하지 않았던 할당량을 초과하는 청구서를 발생시킵니다.IronOCR라이선스 등급 내에서 영구적으로 무제한 사용할 수 있습니다. 페이지당 사용량 제한이나 할당량, 초과 사용 요금 청구가 없습니다.

구매 프로세스로 인해 배송이 차단됩니다. OmniPage SDK는 판매 승인이 필요합니다. 평가판 접근 권한, 가격 및 계약 조건은 모두 4~12주간 진행되는 영업 상담을 통해 결정됩니다. 제품 출시 기한 내에 OCR 기능을 개발하는 팀은 Enterprise 조달 주기를 기다릴 수 없습니다. dotnet add package IronOcr 는 30초 안에 해결됩니다. IronOCR 라이선스 페이지에서 게시된 셀프 서비스 가격 — $999 Lite부터 $2,999의 Enterprise까지, 모두 영구적입니다.

근본적인 문제

OmniPage는 첫 번째 바이트를 읽기 전에 전체 초기화 과정을 거쳐야 하고, 마지막 바이트를 읽은 후에는 종료 과정을 거쳐야 합니다. 모든 호출 지점은 이 두 가지 과정을 모두 관리해야 합니다.

// OmniPage: Ceremony required on EVERY entry point — init, process, shutdown
using var engine = new OmniPageEngine();
engine.SetLicenseFile(@"C:\Program Files\OmniPage\license.lic"); // File must exist here
engine.Initialize();   // Network call to license server — can fail for license reasons, not OCR reasons

var document = engine.CreateDocument();
document.AddPage("invoice.jpg");
document.Recognize(new RecognitionSettings { Language = "English" });
string text = document.GetText();
document.Dispose();    // Must not be skipped
engine.Shutdown();     // Must not be skipped — omitting this locks a floating seat
C#
// IronOCR: One NuGet package, one line at startup, one call to read
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; // At app startup — once, ever
var text = new IronTesseract().Read("invoice.jpg").Text;
C#

OmniPage 버전은 8개의 개별 단계, 2개의 필수 정리 호출, 네트워크 종속성 및 파일 시스템 종속성을 포함합니다.IronOCR버전에는 두 가지가 있습니다.

##IronOCR과 Kofax OmniPage(텅스텐)의 기능 비교

아래 표는 이번 마이그레이션을 평가하는 팀에게 가장 중요한 기능들을 다룹니다.

기능코팍스 옴니페이지 SDKIronOCR
설치 방법사용자 지정 SDK 설치 프로그램( NuGet 미사용)dotnet add package IronOcr
첫 번째 OCR 호출 시간4~12주(조달) + 시간(설치)30초
라이선스 메커니즘디스크의 .lic 파일 + 선택적 라이선스 서버앱 시작 시 문자열 키
하드웨어 지문 인식예 (VM 마이그레이션 후 재활성화)아니요
라이선스 서버 필요예 (유동 라이선스의 경우)아니요
페이지별 런타임 요금 청구사용 가능 (가변적)아니요
공개된 가격아니요 (영업 담당자에게 문의하세요)네 ($999 / $1,499 / $2,999 영구적)
연간 유지 보수 비용라이선스 비용의 18~25%선택적
엔진 수명주기 관리필수 (Initialize / Shutdown)필요하지 않음
윈도우 x64
Linux예 (2026년 1월 추가)예 (모든 버전)
macOS아니요
Docker/Kubernetes난이도 높음 (설치 프로그램 + 라이선스 파일이 이미지에 포함됨)간단합니다 (NuGet 패키지만 해당)
Azure / AWS Lambda복잡함(라이선스 서버 연결 가능성)직관적
이미지 입력 ​​형식JPG, PNG, BMP, TIFF, GIF 등
네이티브 PDF 입력예 (모듈 라이선스가 필요할 수 있습니다)예 (내장되어 있으며, 추가 라이선스가 필요하지 않습니다)
여러 페이지로 구성된 TIFF 파일
검색 가능한 PDF 출력네 (result.SaveAsSearchablePdf())
자동 전처리설정 객체 구성내장형 + 명시적 파이프라인 API
지원되는 언어120+125개 이상 (개별 NuGet 패키지)
구조화된 데이터 출력예 (단어 좌표)페이지, 단락, 줄, 단어, 문자의 좌표
자신감 점수네 (result.Confidence, 단어당)
바코드 판독추가 기능 모듈(별도 라이선스)내장 (ocr.Configuration.ReadBarCodes = true)
스레드 안전성복잡한 (엔진 공유 제약 조건)전체 (1스레드 당 IronTesseract)
CI/CD 파이프라인 지원모든 에이전트에 설치 프로그램이 필요합니다.표준 dotnet restore

빠른 시작: Kofax OmniPage에서IronOCR로 마이그레이션

1단계: SDK를 NuGet 패키지로 교체합니다.

OmniPage에는 제거할 NuGet 패키지가 없습니다. 이동이 완료되면 .csproj 파일에서 수동 DLL 참조를 제거하고 개발 머신에서 SDK를 제거하십시오. 다음으로IronOCR설치하세요.

dotnet add package IronOcr

IronOCR NuGet 패키지에는 OCR 엔진, 전처리 필터 및 런타임 구성 요소가 포함되어 있습니다. 별도의 설치 프로그램이 필요 없고, 네이티브 DLL 관리 기능도 없으며, 구성 요소 등록도 필요 없습니다.

단계 2: 네임스페이스 업데이트

// Before (Kofax OmniPage)
using Kofax.OmniPage.CSDK;
using Kofax.OmniPageCSDK;
using CSDK;

// After (IronOCR)
using IronOcr;
C#

단계 3: 라이선스 초기화

애플리케이션 시작 시 한 줄 추가하십시오. 이는 .lic 파일 경로, 라이선스 서버 설정, engine.Initialize() 호출을 대체합니다:

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

키를 환경 변수 (IRONOCR_LICENSE_KEY) 또는 appsettings.json에 저장하여 소스 코드 대신 사용하십시오. 키는 오프라인에서 읽어오므로 런타임에 네트워크 호출이 발생하지 않습니다.

코드 마이그레이션 예제

엔진 초기화 오류 경로 교체

OmniPage의 라이프사이클 모델에서 가장 위험한 측면은 정상적인 경로가 아니라 오류 경로입니다. engine.Initialize()engine.Shutdown() 사이에 발생한 예외는 Shutdown()에 도달하지 않으면 부동 라이선스 좌석을 잠긴 상태로 둘 수 있습니다. 실제 운영 환경에서는 모든 문서 처리 호출 주변에 try/finally 블록을 사용해야 합니다.

Kofax OmniPage 접근 방식:

// OmniPage: try/finally required everywhere to protect license seat release
public string ProcessInvoice(string imagePath)
{
    var engine = new OmniPageEngine();
    engine.SetLicenseFile(@"C:\Program Files\OmniPage\license.lic");

    try
    {
        engine.Initialize(); // Contacts license server — failure here locks nothing
        var document = engine.CreateDocument();

        try
        {
            document.AddPage(imagePath);
            document.Recognize(new RecognitionSettings { Language = "English" });
            return document.GetText();
        }
        catch (RecognitionException ex)
        {
            // Log, rethrow — but Shutdown must still be called
            throw new OcrProcessingException("Recognition failed", ex);
        }
        finally
        {
            document.Dispose(); // Inner finally: release document
        }
    }
    catch (LicenseValidationException ex)
    {
        throw new OcrProcessingException("License validation failed", ex);
    }
    finally
    {
        engine.Shutdown(); // Outer finally: release license seat — MUST execute
    }
}
C#

IronOCR 접근 방식:

// IronOCR: 아니요 license seat to release, no engine to shut down
public string ProcessInvoice(string imagePath)
{
    using var input = new OcrInput();
    input.LoadImage(imagePath);

    var ocr = new IronTesseract();
    var result = ocr.Read(input);
    return result.Text;
    // OcrInput disposal is automatic — no license implications on any code path
}
C#

using 블록은 OcrInput에서 메모리 정리를 처리합니다. 라이선스 좌석을 보호할 try/finally가 존재하지 않습니다. 이 메서드 내에서 발생하는 예외는 해당 메서드의 범위 외에는 어떠한 부작용도 일으키지 않습니다. 스레드 로컬 인스턴스를 포함한 구성 옵션은 IronTesseract 설정 가이드를 참조하십시오.

영역 기반 인식 마이그레이션

OmniPage의 주요 구조화된 추출 메커니즘은 영역 정의입니다. 문서 영역은 좌표 경계와 영역별 인식 유형(OCR, ICR, OMR, 바코드)으로 선언됩니다. 개발자는 문서 템플릿 당 FormZone 개체를 정의하고 이를 인식 엔진에 전달합니다. IronOCR는 템플릿 관리나 영역 유형 선언 없이 동일한 대상 추출을 달성하기 위해 CropRectangle를 사용합니다:

Kofax OmniPage 접근 방식:

// OmniPage: Zone-based form extraction with template management
public Dictionary<string, string> ExtractInvoiceFields(string invoicePath)
{
    using var engine = new OmniPageEngine();
    engine.SetLicenseFile(licensePath);
    engine.Initialize();

    // Define zones per document template
    var zones = new List<FormZone>
    {
        new FormZone { Name = "InvoiceNumber", Type = "OCR",
            X = 520, Y = 80, Width = 200, Height = 30 },
        new FormZone { Name = "InvoiceDate",   Type = "OCR",
            X = 520, Y = 120, Width = 200, Height = 30 },
        new FormZone { Name = "TotalAmount",   Type = "OCR",
            X = 520, Y = 580, Width = 200, Height = 30 },
        new FormZone { Name = "VendorName",    Type = "OCR",
            X = 50,  Y = 80,  Width = 300, Height = 40 }
    };

    var template = new FormTemplate { Name = "StandardInvoice", Zones = zones };
    var settings = new RecognitionSettings { Language = "English" };

    var document = engine.CreateDocument();
    document.AddPage(invoicePath);
    document.ApplyTemplate(template);
    document.Recognize(settings);

    var fields = new Dictionary<string, string>();
    foreach (var zone in zones)
        fields[zone.Name] = document.GetZoneText(zone.Name);

    document.Dispose();
    engine.Shutdown();
    return fields;
}
C#

IronOCR 접근 방식:

// IronOCR: CropRectangle targets specific regions — no template management
public Dictionary<string, string> ExtractInvoiceFields(string invoicePath)
{
    var fields = new Dictionary<string, string>();
    var ocr = new IronTesseract();

    // Extract each field by reading only the target region
    var fieldRegions = new Dictionary<string, CropRectangle>
    {
        ["InvoiceNumber"] = new CropRectangle(520, 80,  200, 30),
        ["InvoiceDate"]   = new CropRectangle(520, 120, 200, 30),
        ["TotalAmount"]   = new CropRectangle(520, 580, 200, 30),
        ["VendorName"]    = new CropRectangle(50,  80,  300, 40)
    };

    foreach (var (fieldName, region) in fieldRegions)
    {
        using var input = new OcrInput();
        input.LoadImage(invoicePath, region);
        fields[fieldName] = ocr.Read(input).Text.Trim();
    }

    return fields;
}
C#

CropRectangle는 픽셀 단위로 (x, y, width, height)를 지정합니다. OCR 엔진은 전체 페이지가 아닌 지정된 영역만 처리합니다. 이는 OmniPage에서 영역 기반 처리가 제공하는 것과 동일한 효율성 이점입니다. 영역 기반 OCR 가이드에는 여러 영역을 단일 이미지 로드에서 추출하기 위해 OcrInput의 다중 영역 API를 사용하는 방법과 좌표 선택 패턴이 포함되어 있습니다.

구조화된 데이터 출력 마이그레이션

OmniPage는 독자적인 내보내기 파이프라인을 통해 문서 구조를 노출합니다. 인식된 문서에 형식 설정이 적용되고, 지정된 형식(RTF, XML, CSV, 검색 가능한 PDF)의 파일로 출력됩니다. 단어 수준 좌표에 접근하려면 명시적인 위치 쿼리를 사용하여 결과 반복자를 순회해야 합니다.IronOCR별도의 내보내기 단계 없이 동일한 구조화된 데이터를 결과 객체에 직접 표시합니다.

Kofax OmniPage 접근 방식:

// OmniPage: Structured output requires format configuration and file export
public void ExtractStructuredContent(string imagePath, string outputDir)
{
    using var engine = new OmniPageEngine();
    engine.SetLicenseFile(licensePath);
    engine.Initialize();

    var settings = new RecognitionSettings { Language = "English" };
    var document = engine.CreateDocument();
    document.AddPage(imagePath);
    document.Recognize(settings);

    // Word-level coordinates through result iterator
    var iterator = document.GetResultIterator(ResultIteratorLevel.Word);
    while (iterator.MoveNext())
    {
        string word = iterator.GetText();
        var bounds = iterator.GetBoundingBox();
        double confidence = iterator.GetConfidence();
        Console.WriteLine($"Word: {word} at ({bounds.X},{bounds.Y}) conf:{confidence:F1}%");
    }

    // Structured export requires separate output format configuration
    var outputSettings = new OutputSettings
    {
        Format = OutputFormat.XML,
        IncludeCoordinates = true,
        IncludeConfidence = true
    };
    document.SaveAs(Path.Combine(outputDir, "output.xml"), outputSettings);

    document.Dispose();
    engine.Shutdown();
}
C#

IronOCR 접근 방식:

// IronOCR: Structured data directly on OcrResult — no export step
public void ExtractStructuredContent(string imagePath)
{
    var result = new IronTesseract().Read(imagePath);

    Console.WriteLine($"Confidence: {result.Confidence:F1}%");
    Console.WriteLine($"Pages: {result.Pages.Length}");

    foreach (var page in result.Pages)
    {
        foreach (var paragraph in page.Paragraphs)
        {
            Console.WriteLine($"[Paragraph at ({paragraph.X},{paragraph.Y})]");
            Console.WriteLine(paragraph.Text);

            foreach (var word in paragraph.Words)
            {
                // Per-word confidence and coordinates — no iterator needed
                Console.WriteLine(
                    $"  Word: '{word.Text}' " +
                    $"at ({word.X},{word.Y}) " +
                    $"conf: {word.Confidence:F1}%");
            }
        }
    }
}
C#

OcrResult 개체의 계층 구조 — 페이지, 문단, 줄, 단어, 문자 — 는 탐색 가능한 객체 그래프로 처리되며, 순차 커서 대신 동일한 위치 데이터를 OmniPage의 결과 반복자가 노출시킵니다. 별도의 설정 없이 결과, 페이지, 단락 및 단어 수준에서 신뢰도 점수를 확인할 수 있습니다. 읽기 결과 가이드는 모든 구조화된 데이터 속성을 다루고, 신뢰도 점수 가이드는 단어별 유효성 검사 패턴을 다룹니다.

다중 페이지 TIFF 처리 마이그레이션

OmniPage의 다중 페이지 TIFF 워크플로는 TIFF 컨테이너에서 페이지별 추출을 필요로 하며, 페이지별로 별도의 인식 호출과 문서 폐기가 수행됩니다. 이로 인해 정형화된 코드가 생성될 뿐만 아니라 페이지 수에 비례하여 리소스 관리 영역이 늘어납니다.IronOCR단일 호출로 여러 프레임으로 구성된 TIFF 파일을 불러옵니다.

Kofax OmniPage 접근 방식:

// OmniPage: Page-by-page TIFF extraction with per-page lifecycle
public List<string> ExtractFromMultiPageTiff(string tiffPath)
{
    var pageTexts = new List<string>();

    using var engine = new OmniPageEngine();
    engine.SetLicenseFile(licensePath);
    engine.Initialize();

    // Open TIFF and iterate frames
    var tiffContainer = engine.OpenTiff(tiffPath);
    int pageCount = tiffContainer.GetPageCount();

    var settings = new RecognitionSettings { Language = "English" };

    for (int i = 0; i < pageCount; i++)
    {
        var page = tiffContainer.GetPage(i); // Extract frame
        var document = engine.CreateDocument();

        try
        {
            document.AddPage(page);
            document.Recognize(settings);
            pageTexts.Add(document.GetText());
        }
        finally
        {
            document.Dispose(); // Dispose per page to manage memory
        }
    }

    tiffContainer.Dispose();
    engine.Shutdown();
    return pageTexts;
}
C#

IronOCR 접근 방식:

// IronOCR: Multi-frame TIFF loaded in one call — all pages in one result
public List<string> ExtractFromMultiPageTiff(string tiffPath)
{
    using var input = new OcrInput();
    input.LoadImageFrames(tiffPath); // All frames loaded automatically

    var result = new IronTesseract().Read(input);

    // Each TIFF frame becomes a page in the result
    return result.Pages.Select(page => page.Text).ToList();
}
C#

LoadImageFrames는 TIFF 컨테이너의 모든 프레임을 단일 호출로 읽습니다. 결과는 프레임 당 하나의 OcrResult.Page을 노출하여 페이지별 구조를 보존하며 수동 반복 루프나 페이지별 정리가 필요하지 않습니다. 생산 TIFF 배치 워크플로에 대해서는 TIFF 및 GIF 입력 가이드를 참조하십시오.

스레드 안전 병렬 처리 마이그레이션

OmniPage의 엔진은 공유되는 상태 저장 리소스입니다. 스레드 간에 하나의 OmniPageEngine 인스턴스를 공유하려면 외부 동기화가 필요합니다. 여러 스레드가 동시에 CreateDocument()를 호출하면 얽힌 상태를 생성할 수 있기 때문입니다. 안전한 패턴 — 스레드 당 하나의 엔진 인스턴스 — 은 무거운 초기화 비용과 충돌합니다.IronOCR인스턴스는 공유 상태가 없으므로, 스레드 당 IronTesseract 를 하나 생성하여 조정 오버헤드를 없애십시오:

Kofax OmniPage 접근 방식:

// OmniPage: Shared engine with locking to serialize document operations
public ConcurrentDictionary<string, string> ProcessBatchWithEngine(
    string[] imagePaths, string licensePath)
{
    var results = new ConcurrentDictionary<string, string>();
    var engineLock = new object();

    // One engine — document operations must be serialized
    using var engine = new OmniPageEngine();
    engine.SetLicenseFile(licensePath);
    engine.Initialize();

    var settings = new RecognitionSettings { Language = "English" };

    Parallel.ForEach(imagePaths, imagePath =>
    {
        lock (engineLock) // Serialize: one recognition at a time
        {
            var document = engine.CreateDocument();
            try
            {
                document.AddPage(imagePath);
                document.Recognize(settings);
                results[imagePath] = document.GetText();
            }
            finally
            {
                document.Dispose();
            }
        }
    });

    engine.Shutdown();
    return results;
}
C#

IronOCR 접근 방식:

// IronOCR: One IronTesseract per thread — no locking, genuine parallelism
public ConcurrentDictionary<string, string> ProcessBatchInParallel(string[] imagePaths)
{
    var results = new ConcurrentDictionary<string, string>();

    Parallel.ForEach(imagePaths, imagePath =>
    {
        // Each thread creates its own instance — no shared state, no locks
        var ocr = new IronTesseract();
        using var input = new OcrInput();
        input.LoadImage(imagePath);

        var result = ocr.Read(input);
        results[imagePath] = result.Text;
    });

    return results;
}
C#

OmniPage 버전은 락을 통해 모든 인식을 직렬화하므로 병렬 처리가 불가능합니다.IronOCR버전은 별도의 조정 없이 문서를 동시에 처리합니다. 높은 처리량의 배치 워크로드에 대해서는 멀티스레딩 예제속도 최적화 가이드를 참조하십시오.

스캔한 파일에서 검색 가능한 PDF 생성

OmniPage의 검색 가능한 PDF 출력을 위해서는 저장 전에 명시적인 OutputSettingsOutputFormat 설정을 사용하여 인식 파이프라인을 구성해야 합니다.IronOCR결과 객체에 대한 단일 메서드 호출을 통해 검색 가능한 PDF를 생성합니다.

Kofax OmniPage 접근 방식:

// OmniPage: Searchable PDF requires OutputSettings configuration before save
public void ConvertArchiveToSearchable(string[] scannedPdfPaths, string outputDirectory)
{
    using var engine = new OmniPageEngine();
    engine.SetLicenseFile(licensePath);
    engine.Initialize();

    var recognitionSettings = new RecognitionSettings
    {
        Language = "English",
        AccuracyMode = "Maximum",
        PreserveLayout = true
    };

    var outputSettings = new OutputSettings
    {
        Format = OutputFormat.SearchablePDF,
        Compression = PDFCompression.Standard,
        ImageQuality = 85,
        EmbedFonts = true
    };

    foreach (var pdfPath in scannedPdfPaths)
    {
        var document = engine.OpenPDF(pdfPath);
        document.RecognizeAll(recognitionSettings);

        string outputPath = Path.Combine(
            outputDirectory,
            Path.GetFileNameWithoutExtension(pdfPath) + "_searchable.pdf");

        document.SaveAs(outputPath, outputSettings);
        document.Dispose();
    }

    engine.Shutdown();
}
C#

IronOCR 접근 방식:

// IronOCR: Searchable PDF output is one method call on the result
public void ConvertArchiveToSearchable(string[] scannedPdfPaths, string outputDirectory)
{
    var ocr = new IronTesseract();

    foreach (var pdfPath in scannedPdfPaths)
    {
        using var input = new OcrInput();
        input.LoadPdf(pdfPath); // All pages loaded automatically

        var result = ocr.Read(input);

        string outputPath = Path.Combine(
            outputDirectory,
            Path.GetFileNameWithoutExtension(pdfPath) + "_searchable.pdf");

        result.SaveAsSearchablePdf(outputPath);
        Console.WriteLine($"Processed: {Path.GetFileName(pdfPath)} ({result.Pages.Length} pages)");
    }
}
C#

SaveAsSearchablePdf은 PDF에 텍스트 레이어를 삽입하여 문서 관리 시스템에서 인덱싱할 수 있게 하며, 원본 스캔의 시각적 외관은 변경하지 않습니다. 검색 가능한 PDF 가이드에서는 텍스트 레이어 옵션을 다루고, PDF OCR 예제에서는 스캔한 PDF를 처음부터 끝까지 처리하는 과정을 보여줍니다.

코팍스 옴니페이지 API와IronOCR매핑 참조

코팍스 옴니페이지IronOCR에 상응하는
using Kofax.OmniPage.CSDK;using IronOcr;
using Kofax.OmniPageCSDK;using IronOcr;
using CSDK;using IronOcr;
new OmniPageEngine()필요 없음 - 엔진 객체가 없습니다.
engine.SetLicenseFile(path)IronOcr.License.LicenseKey = "key";
engine.Initialize()필요하지 않음
engine.Shutdown()필요하지 않음
engine.CreateDocument()new OcrInput()
document.AddPage(imagePath)input.LoadImage(imagePath)
engine.OpenPDF(pdfPath)input.LoadPdf(pdfPath)
engine.OpenTiff(tiffPath)input.LoadImageFrames(tiffPath)
document.Recognize(settings)new IronTesseract().Read(input)
document.RecognizeAll(settings)new IronTesseract().Read(input) (모든 페이지 동시에)
document.GetText()result.Text
document.GetZoneText(zoneName)input.LoadImage(path, cropRectangle) + result.Text
document.Dispose()using var input = new OcrInput() (자동)
iterator.GetText()result.Pages[n].Words[m].Text
iterator.GetBoundingBox()result.Pages[n].Words[m].X / Y / Width / Height
iterator.GetConfidence()result.Pages[n].Words[m].Confidence
engine.LoadLanguageDictionary("German")dotnet add package IronOcr.Languages.German
settings.PrimaryLanguage = "English"ocr.Language = OcrLanguage.English;
settings.SecondaryLanguages = new[] {"German"}ocr.Language = OcrLanguage.English + OcrLanguage.German;
settings.DeskewImage = trueinput.Deskew();
settings.DespeckleLevel = 2input.DeNoise();
settings.ContrastEnhancement = trueinput.Contrast();
settings.AutoRotate = trueinput.Deskew(); (회전 보정 포함)
document.SaveAs(path, outputSettings)result.SaveAsSearchablePdf(path)
OutputFormat.SearchablePDFresult.SaveAsSearchablePdf(path)
OutputFormat.XML (좌표 포함)result.Pages / .Paragraphs / .Words 객체 그래프
FormZone 좌표 경계를 사용new CropRectangle(x, y, width, height)
페이지별 라이선스 계산적용 안 됨
.lic 파일 배포적용 안 됨
라이선스 서버 구성적용 안 됨

일반적인 마이그레이션 문제와 해결책

문제 1: 운영 환경에서 발생하는 라이선스 파일 찾을 수 없음 예외

Kofax OmniPage: 모든 배포에는 애플리케이션 프로세스에서 접근 가능한 특정 경로에 .lic 파일이 존재해야 합니다. 배포 파이프라인에서 라이선스 파일을 대상 서버에 명시적으로 복사하지 않으면 엔진 초기화 시 FileNotFoundException 또는 LicenseException가 발생합니다. 보안 팀은 종종 컨테이너 이미지에 .lic 파일을 임베딩하거나 소스 컨트롤에 커밋하는 것을 경고합니다.

**해결책:**IronOCR라이선스 정보를 문자열에서 읽어옵니다. 환경 변수로 키를 저장하고 시작 시 읽어오세요. 배포할 파일도 없고, 구성할 경로도 없습니다.

// At application startup — reads IRONOCR_LICENSE_KEY from environment
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY")
    ?? throw new InvalidOperationException("IronOCR license key not configured.");
C#

Docker에서는 --env IRONOCR_LICENSE_KEY=YOUR-KEY를 전달하십시오. Azure App Service에서 애플리케이션 설정으로 설정하세요. Kubernetes에서는 Secret을 통해 주입합니다. 파일 마운트도 없고, 경로 구성도 없고, 내장 라이선스 파일에 대한 보안 검토도 없습니다.

문제 2: 프로세스 충돌 후 플로팅 라이선스 시트가 잠김

Kofax OmniPage: 애플리케이션 프로세스가 충돌하거나 워치독에 의해 종료되거나 Environment.FailFast 통해 종료되면, engine.Shutdown()는 실행되지 않습니다. 플로팅 라이선스 시트는 라이선스 서버의 시간 초과(일반적으로 30~60분)가 만료될 때까지 체크아웃된 상태로 유지됩니다. 컨테이너 환경에서 파드가 자주 재시작될 경우, 이러한 동작으로 인해 라이선스 풀이 고갈됩니다.

**해결책:**IronOCR에는 대여된 라이선스 시트라는 개념이 없습니다. 프로세스 충돌은 리소스를 해제하지 않으며 외부 시스템을 잠그지도 않습니다. 다음 절차는 좌석 확보를 기다릴 필요 없이 즉시 시작됩니다.

// IronOCR: Process crash has no license implications whatsoever
// Start processing immediately after any failure
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var result = new IronTesseract().Read("document.jpg"); // 아니요 seat to check out
C#

안정적인 ASP.NET Core 서비스를 구축하려면 호스팅 서비스와 깔끔하게 통합되고 정상적으로 종료되는 패턴에 대한 내용 은 비동기 OCR 가이드를 참조하세요.

문제 3: Docker 이미지 빌드 실패 — 설치 프로그램이 비대화형으로 실행될 수 없음

Kofax OmniPage: OmniPage SDK 설치 프로그램은 GUI 또는 반대화면 설치 프로그램이며 docker build 환경에서 깔끔하게 실행되지 않습니다. SDK를 컨테이너 이미지에 통합하려는 팀은 설치 프로그램의 라이선스 계약 또는 구성 요소 선택 단계에서 오류를 겪습니다. 해결 방법(자동 설치 스위치, 미리 추출된 DLL 복사본)은 문서화되어 있지 않으며 버전별로 다릅니다.

Solution: IronOCR의 Dockerfile는 세 줄로 구성되어 있습니다:

FROM mcr.microsoft.com/dotnet/aspnet:8.0
RUN apt-get update && apt-get install -y libgdiplus  # Single Linux dependency
COPY --from=build /app/publish /app
WORKDIR /app
ENTRYPOINT ["dotnet", "YourApp.dll"]
Text

libgdiplus는 유일한 시스템 종속성입니다.IronOCR NuGet 패키지는 모든 다른 패키지 참조처럼 빌드 단계 내부의 dotnet restore에 의해 복원됩니다. Docker 배포 가이드는 Debian 및 Alpine 기본 이미지를 모두 다루고, Linux 배포 가이드는 배포판별 패키지 이름을 다룹니다.

문제 4: VM 마이그레이션 또는 클라우드 자동 확장 후 재활성화 필요

Kofax OmniPage: OmniPage 활성화는 하드웨어 ID와 연동됩니다. 물리적 호스트 간에 VM을 마이그레이션하거나, 새 인스턴스로 자동 확장하거나, 컨테이너를 새 이미지로 교체하는 클라우드 환경에서는 하드웨어 ID 변경이 발생하며, 이에 대한 재활성화가 필요합니다. 사고 발생 중에 Tungsten 지원팀에 연락하여 재활성화를 요청하는 것은 운영상의 위험을 초래합니다.

해결책: IronOCR의 라이선스 키는 하드웨어와 무관합니다. 동일한 키는 라이선스 티어 내의 모든 머신, 모든 컨테이너, 모든 클라우드 지역, 모든 수의 자동 확장 인스턴스에서 작동합니다. 재활성화 필요 없음, 고객 지원 문의 필요 없음, 시스템 다운타임 없음:

// Identical startup code on any hardware topology
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
bool valid = IronOcr.License.IsLicensed; // Verify without a network call
C#

문제 5: RecognitionSettings 객체에IronOCR에 해당하는 객체가 없음

Kofax OmniPage: OmniPage는 각 문서별로 엔진 동작을 구성하기 위해 RecognitionSettings 객체 (또는 SDK 버전에 따라 PreprocessingSettings)를 사용합니다. 마이그레이션을 진행하는 팀은IronOCR에서 병렬 구성 객체를 기대합니다.

Solution: IronOCR는 구성을 두 가지 표면으로 분리합니다: OcrInput에서의 전처리 작업과 IronTesseract에서의 엔진 설정입니다. 인스턴스화할 설정 객체가 없습니다.

// OmniPage settings object →IronOCR method calls on OcrInput
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.English;              // RecognitionSettings.Language
// ocr.Configuration.TesseractVersion = ...     // Engine version already optimized

using var input = new OcrInput();
input.LoadImage(imagePath);
input.Deskew();                                  // settings.DeskewImage = true
input.DeNoise();                                 // settings.DespeckleLevel = 2
input.Contrast();                                // settings.ContrastEnhancement = true

var result = ocr.Read(input);
C#

이미지 품질 보정 가이드 에는 사용 가능한 모든 전처리 방법이 나열되어 있으며, 어떤 필터가 어떤 문서 품질 프로필에 적용되는지에 대한 지침이 포함되어 있습니다.

문제 6: 영역 템플릿 파일을 직접 가져올 수 없습니다.

Kofax OmniPage: OmniPage 양식 템플릿은 독점적인 .fdt 또는 .fpf 템플릿 파일에 구역 정의를 저장하며, 문서 클래스별로 필드 위치, 인식 유형, 검증 규칙을 정의합니다. 이 파일들은IronOCR에서 가져올 수 없습니다.

Solution: 템플릿 파일(이는 XML 기반입니다)에서 좌표 데이터를 추출하고 각 구역을 CropRectangle로 변환하십시오. 필드 이름은 딕셔너리 키가 됩니다. 영역 좌표는 (x, y, width, height) 매개변수에 직접 매핑됩니다:

// Convert OmniPage zone definition toIronOCR CropRectangle
// OmniPage zone: Name="TotalDue" X="490" Y="612" Width="180" Height="28"
//IronOCR equivalent:
var totalDueRegion = new CropRectangle(490, 612, 180, 28);

using var input = new OcrInput();
input.LoadImage(invoicePath, totalDueRegion);
string totalDue = new IronTesseract().Read(input).Text.Trim();
C#

페이지별로 영역이 다양한 문서의 경우 파일을 다시 로드하는 대신 각 지역별로 다른 CropRectangle 값을 사용하여 동일한 이미지를 로드하십시오. 영역 자르기 예제는 단일 이미지 소스에서 여러 영역을 읽는 방법을 보여줍니다.

코팍스 옴니페이지 마이그레이션 체크리스트

사전 마이그레이션

코드베이스에서 모든 OmniPage 통합 지점을 식별하십시오.

# Find all OmniPage namespace references
grep -r "Kofax\|OmniPage\|CSDK" --include="*.cs" --include="*.csproj" .

# Find engine lifecycle calls
grep -r "Initialize\|Shutdown\|SetLicenseFile" --include="*.cs" .

# Find document and zone creation patterns
grep -r "CreateDocument\|AddPage\|FormZone\|RecognitionSettings\|PreprocessingSettings" --include="*.cs" .

# Find output format configuration
grep -r "OutputSettings\|OutputFormat\|SaveAs\|GetText" --include="*.cs" .

# Find license file path references
grep -r "\.lic\|license\.lic\|licensePath" --include="*.cs" --include="*.config" --include="*.json" .
SHELL

시작 전 재고 목록:

  • OmniPage 네임스페이스를 가져온 파일 수 계산
  • 모든 FormTemplateFormZone 정의를 나열하고 좌표 데이터를 추출하십시오
  • 어떤 언어 사전이 로드되었는지 식별하고 IronOcr.Languages.* NuGet 패키지로 매핑하십시오
  • 사용된 출력 형식(검색 가능한 PDF, 일반 텍스트, XML)과 해당IronOCR형식에 대한 대응값을 기록해 두십시오.
  • 배포 스크립트와 구성에서 모든 .lic 파일 참조를 찾으십시오

코드 마이그레이션

  1. 모든 .csproj 파일에서 OmniPage DLL 참조 제거
  2. OCR을 수행하는 각 프로젝트에서 dotnet add package IronOcr 실행
  3. 사용 중인 각 언어에 대한 언어 팩 추가: dotnet add package IronOcr.Languages.[Language]
  4. 각 애플리케이션 진입점(Program.cs, Startup.cs 또는 서비스 호스트)에 IronOcr.License.LicenseKey = ...; 추가
  5. 모든 using Kofax.OmniPage.CSDK;, using CSDK; 및 관련 네임스페이스 가져오기를 using IronOcr;으로 대체
  6. 모든 OmniPageEngine 생성, SetLicenseFileInitialize 호출 제거
  7. 모든 engine.Shutdown() 호출 및 종료 보장을 위해 존재하는 IDisposable 구현 제거
  8. engine.CreateDocument() + document.AddPage()new OcrInput() + input.LoadImage() 대체
  9. engine.OpenPDF() + 페이지별 반복을 input.LoadPdf() (모든 페이지를 한 번에 호출)로 대체
  10. engine.OpenTiff() + 프레임별 루프를 input.LoadImageFrames()로 대체
  11. document.Recognize(settings)new IronTesseract().Read(input)으로 대체
  12. FormZone 좌표 데이터를 CropRectangle(x, y, width, height) 인스턴스로 변환
  13. document.GetZoneText()을 지역별 input.LoadImage(path, cropRectangle) + result.Text으로 대체
  14. 검색 가능한 PDF를 위한 document.SaveAs(path, outputSettings)result.SaveAsSearchablePdf(path)으로 대체
  15. 결과 반복자 패턴을 result.Pages / .Paragraphs / .Words 속성 탐색으로 대체
  16. 모든 PreprocessingSettings 객체를 제거하고 불리언 플래그를 명시적인 input.Deskew(), input.DeNoise(), input.Contrast() 메서드 호출로 대체
  17. 배포 스크립트, 구성 파일 및 인프라 코드 템플릿에서 라이선스 파일 경로를 제거합니다.

마이그레이션 이후

  • 실제 데이터셋에서 추출한 100개 이상의 대표 샘플을 사용하여 OCR 정확도를 검증합니다. 송장, 계약서, 양식 등의 OmniPage 출력 결과와 각 줄을 비교합니다.
  • OmniPage GetZoneText() 출력과 일치하는 텍스트를 반환하는 CropRectangle 기반의 영역 추출을 확인
  • 다중 페이지 PDF 처리 테스트: 페이지 수, 페이지 순서 및 텍스트 연속성 확인
  • 다중 프레임 TIFF 처리 테스트: 모든 프레임이 처리되고 프레임 순서가 유지되는지 확인합니다.
  • 검색 가능한 PDF 출력물이 사용 중인 문서 관리 시스템(SharePoint, OpenText 등)에서 색인화 가능한지 확인합니다.
  • 50개 이상의 문서를 동시에 처리하는 병렬 처리 테스트를 실행하고 스레드 안전성 문제가 없는지 확인합니다.
  • 언어 팩 범위 테스트: 이전에 사용한 언어 사전을 IronOcr.Languages.*로 로드하고 인식 품질 확인
  • 프로세스 충돌 및 컨테이너 재시작 시 라이선스 복구 조치가 필요하지 않은지 확인합니다.
  • CI 에이전트에서 Docker 빌드 실행 — 설치 단계 없이 IronOCR를 해결하는지 확인
  • 단어별 신뢰도 점수가 제공되는지 확인하고, 하위 검증 워크플로의 데이터 품질 기대치와 일치하는지 검증합니다.
  • 어떤 경로에서도 .lic 파일이 없는 상태에서 애플리케이션이 깔끔하게 시작되는지 확인

##IronOCR로 마이그레이션할 때의 주요 이점

배포 복잡성이 몇 주에서 몇 분으로 하락합니다. 이전에 SDK 설치 프로그램 접근 권한, .lic 파일 배포, 라이선스 서버를 위한 방화벽 구성, 인프라 팀 조정이 필요했던 프로젝트가 이제 dotnet restore을 통해 배포됩니다. 새로운 개발자가 저장소를 복제하고 프로젝트를 실행합니다. CI/CD 파이프라인을 통해 새로운 프로덕션 서버가 프로비저닝됩니다. 컨테이너 이미지는 설치 프로그램 단계 없이 빌드됩니다.

라이선스 위험이 완전히 사라집니다. 소진해야 할 부동 좌석이 없으며, 대기해야 할 체크아웃 타임아웃도 없고, 재활성화할 하드웨어 지문도 없으며, 배포 파이프라인에서 보호해야 할 .lic 파일도 없습니다. 새벽 3시에 애플리케이션이 충돌해도 아무것도 해제되지 않고 아무것도 잠기지 않습니다. 당직 엔지니어가 프로세스를 다시 시작합니다. OCR이 즉시 재개됩니다. IronOCR 제품 페이지에는 모든 라이선스 등급이 나와 있습니다.

크로스 플랫폼 배포가 표준 NuGet 대상으로 추가됩니다. macOS 개발 환경에서는 플랫폼 예외 없이 작동합니다. Linux 운영 서버에는 2026년 1월 버전의 SDK가 필요하지 않습니다. 하나의 시스템 종속성이 있는 표준 mcr.microsoft.com/dotnet/aspnet 기본 이미지를 기반으로 Docker 컨테이너가 빌드됩니다. Windows, Linux, macOS에서 모두 작동하는 빌드를 생성하는 .csproj에 있는 동일한 IronOcr 패키지 참조 클라우드별 구성에 대한 자세한 내용은 Azure 배포 가이드AWS 배포 가이드를 참조하세요.

병렬 처리량은 하드웨어에 따라 확장됩니다. OmniPage의 공유 엔진 아키텍처는 동시 인식을 직렬화하는 잠금 기능을 필요로 합니다. IronOCR의 무상태 IronTesseract 인스턴스는 사용 가능한 CPU 코어에 따라 선형적으로 확장됩니다. 배치 처리 서버의 코어 수를 두 배로 늘리면 구성 변경이나 추가 라이선스 없이 처리량이 두 배로 증가합니다.

구조화된 데이터 접근이 즉각적입니다. OcrResult.Pages, Paragraphs, Lines, Words, 및 Characters 는 완전한 문서 구조를 탐색 가능한 .NET 객체 그래프로 노출합니다. 단어별 신뢰도와 좌표는 각 단어 객체의 속성입니다. 위치 데이터에 접근하기 위해 별도의 내보내기 파이프라인, 형식 구성 또는 파일 출력이 필요하지 않습니다.

비용은 고정되어 있고 예측 가능합니다. OmniPage는 SDK 라이선스, 연간 유지 보수 비용, 페이지당 런타임 비용을 합산하여 사용량에 따라 비용이 증가하고 매년 반복됩니다. IronOCR는 $999–$2,399 영구적으로 한 번 구매합니다. 연간 50만 페이지 처리량을 보이는 워크플로우에서 페이지당 비용이 발생하던 방식이IronOCR라이선스 비용을 몇 주 만에 회수할 수 있게 되었습니다. IronOCR 문서 허브튜토리얼은 지원 계약 없이 이용할 수 있습니다.

참고해 주세요: Kofax OmniPage, OpenPDF, 및 Tesseract는 각각의 소유주가 등록한 상표입니다. 이 사이트는 Google, Kofax 또는 LibrePDF와 관련이 없으며, 그들의 인증이나 후원을 받지 않았습니다. 모든 제품명, 로고 및 브랜드는 해당 소유자의 자산입니다. 비교는 정보 제공 목적으로만 사용되며, 작성 시점에 공개적으로 이용 가능한 정보를 반영합니다.

관련 기사

Key in blue circle

무료 30일 체험 키를 즉시 받으세요.

Your trial license will be sent to your email address

제한 없음. 100% 무제한 이용. 신용카드 불필요.

bullet_checked신용카드나 계정 생성은 필요하지 않습니다.제한 없음. 100% 무제한 이용. 신용카드 불필요.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
부담 없는 무료 상담을 받아보세요
아래 양식을 작성하시거나 sales@ironsoftware.com으로 이메일을 보내주세요.
고객님의 정보는 항상 비밀로 유지됩니다.
전 세계 수백만 엔지니어들이 신뢰하는 제품입니다.
Iron Software의 고객 로고
지금 바로 30일 무료 체험판 키를 받으세요.
신용카드나 계정 생성은 필요하지 않습니다.