IRONSOFTWAREHOME
동영상

오픈소스 라이브러리를 사용하여 C#에서 OCR을 구현하는 방법

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

이 가이드는 Klippa의 REST API를 통합한 후 온프레미스 문서 처리를 위해 IronOCR 로 전환하는 .NET 개발자를 위한 것입니다. 이 문서에서는 HTTP 클라이언트 인프라를 제거하고, JSON 역직렬화를 없애고, 클라우드에 의존하는 문서 업로드를 네트워크에 전혀 연결하지 않는 로컬 OCR 호출로 대체하는 실질적인 단계를 다룹니다.

Klippa OCR에서 마이그레이션해야 하는 이유는 무엇일까요?

Klippa는 .NET SDK를 제공하지 않는 클라우드 전용 문서 인텔리전스 서비스입니다. 모든 통합은 수작업으로 개발된 REST 클라이언트입니다. 그러한 구조적 현실은 생산 시스템의 수명 주기 동안 누적되는 연쇄적인 결과를 초래합니다.

NuGet 패키지가 없다는 것은 통합 레이어를 직접 소유하고 있다는 의미입니다. 설치할 것이 아무것도 없습니다. 입장 비용은 HttpClient 래퍼 작성, X-Auth-Key 인증 헤더 구성, MultipartFormDataContent 요청 본문 작성, Klippa의 JSON 응답 스키마 역직렬화, 그리고 일시적인 오류에 대한 재시도 로직 연결입니다. 첫 번째 문서가 프로덕션 환경에서 안정적으로 처리되기까지 2~4일 정도의 파이프라인 구축 작업이 필요합니다. Klippa가 API 스키마를 업데이트하면 역직렬화 코드가 제대로 작동하지 않아 수동으로 수정해야 합니다.

모든 문서 업로드는 네트워크 연결에 의존합니다. Klippa는 EU 내 서버에서만 문서를 처리합니다. Klippa 측의 생산 중단, 지연 시간 증가 또는 애플리케이션 서버에서 외부 인터넷 액세스 중단이 발생하면 문서 처리가 완전히 중단됩니다. 클라우드 서비스 이용 불가 시 대체 기능, 로컬 모드 또는 재시도 기능이 제공되지 않습니다.

민감한 문서가 귀사의 인프라를 벗어납니다. 결제 내역이 포함된 영수증, 부가가치세 번호와 금액이 기재된 송장, 여권 정보가 포함된 신분증 등 재무 문서는 모든 API 호출 시 제3자 서버로 전송됩니다. GDPR의 데이터 전송 조항은 EU 기반 처리와 관련하여 이러한 사항 중 일부를 다루지만, 감사 범위는 여전히 Klippa의 인프라, 데이터 보존 정책 및 하위 처리업체까지 확장됩니다. 의료, 법률, 금융 서비스 또는 정부 계약을 체결한 팀의 경우 "EU 호스팅"은 데이터가 조직 외부로 유출되지 않아야 한다는 요건을 충족하지 못합니다.

문서별 가격 상한선 없음. Klippa는 가격 정보를 공개하지 않습니다. 월 1만 건의 영수증(경비 관리 시스템)이나 하루 500건의 송장(AP 자동화 워크플로)과 같이 의미 있는 문서 처리량이 발생할 경우, 문서별 요금 청구 모델은 영구 라이선스로는 절대 발생하지 않는 비용을 초래합니다. 비용 추이는 기업 성장과 직접적으로 연관되어 있는데, 이는 인프라 투자의 취지와는 정반대입니다.

요구사항이 확장됨에 따라 전문가의 업무 범위가 제한됩니다. 클리파는 영수증, 송장 및 신분증에 대한 교육을 받았습니다. 경비 관리 용도로 시작한 애플리케이션은 그 용도로만 머무르는 경우가 드뭅니다. 스캔한 고용 계약서, 의료 양식, 기술 도면, 비표준 레이아웃의 구매 주문서와 같이 앞서 언급한 세 가지 범주 이외의 문서 유형이 처음 나타나면 Klippa는 유용한 결과를 반환하지 않습니다.IronOCR범주 제한 없이 텍스트가 포함된 모든 문서를 처리합니다.

비동기 전용 REST 호출은 동기 컨텍스트에서 지연 시간을 추가합니다. 모든 Klippa 호출은 비동기 HTTP 작업입니다. 단일 문서의 왕복 전송은 네트워크를 통해 500ms에서 2000ms가 소요됩니다.IronOCR동기식 처리가 아키텍처에 더 적합한 시나리오에서 비동기 오버헤드 없이 동일한 문서를 로컬에서 100~400ms 내에 처리합니다.

근본적인 문제

Klippa에는 SDK가 없습니다. OCR은 HTTP 요청을 구성하고 전송한 다음 JSON을 역직렬화하는 것을 의미합니다.

// Klippa: 15+ lines of HTTP plumbing before you read a single character
var content = new MultipartFormDataContent();
content.Add(new ByteArrayContent(File.ReadAllBytes(imagePath)), "document", "receipt.jpg");
_client.DefaultRequestHeaders.Add("X-Auth-Key", _apiKey); // auth header — rotates, breaks, leaks

var response = await _client.PostAsync(
    "https://custom-ocr.klippa.com/api/v1/parseDocument", content);
response.EnsureSuccessStatusCode(); // throws on 4xx/5xx — no retry, document lost

var json = await response.Content.ReadAsStringAsync();
var parsed = JsonSerializer.Deserialize<KlippaResponse>(json); // your schema, your maintenance
var text = parsed?.Data?.ParsedDocument?.Text; // nullable chain — breaks when schema changes
C#

IronOCR 이 모든 것을 대체합니다.

// IronOCR: no HTTP, no auth headers, no JSON — just text
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read(imagePath).Text;
C#

##IronOCR과 Klippa OCR: 기능 비교

아래 표는 프로덕션 환경으로의 마이그레이션 결정에 가장 중요한 요소들을 기준으로 두 라이브러리를 비교합니다.

기능클리파 OCRIronOCR
배포 모델클라우드 전용(EU 서버)온프레미스, 완전 로컬
.NET SDK / NuGet 패키지NoneIronOcr NuGet 패키지
인터넷 필요네, 모든 통화에서요.절대
문서 데이터가 네트워크를 떠납니다.항상절대
범용 OCR아니요 (영수증, 송장, 신분증만 가능)예 (문서 종류는 상관없습니다)
인증 설정X-Auth-Key HTTP 헤더IronOcr.License.LicenseKey 문자열
HTTP 클라이언트 필요아니요
응답 역직렬화수동 JSON 파싱타입화된 OcrResult 객체
재시도/타임아웃 로직손으로 말아서 만든필요 없음 (지역 통화)
오프라인/에어갭 지원아니요
PDF 입력예 (클라우드)예 (토착민, 현지인)
여러 페이지로 구성된 TIFF 입력알 수 없음
이미지 입력 ​​형식JPG, PNG (구름)JPG, PNG, BMP, TIFF, GIF 등
스트림 및 바이트 배열 입력SDK 없음
자동 이미지 전처리구름 쪽 (불투명)예 (왜곡 제거, 노이즈 제거, 대비 조정, 이진화, 선명도 향상)
구조화된 출력: 단어 좌표아니요
단어별 신뢰도 점수아니요
검색 가능한 PDF 출력아니요
OCR 중 바코드 판독아니요
다국어 지원학습된 문서 유형으로 제한됨125개 이상의 언어
나사 안전해당 없음 (HTTP 호출)예 (스레드당 하나의 IronTesseract)
크로스 플랫폼 배포REST에 구애받지 않는윈도우, 리눅스, macOS, Docker, Azure, AWS
HIPAA/ITAR/에어갭 규정 준수아니요
가격 모델문서별 SaaS (요금 미공개)$999로부터 영구 라이선스
대규모 생산 시 페이지당 비용네, 무제한입니다.None

빠른 시작: Klippa OCR에서IronOCR로 마이그레이션

1단계: NuGet 패키지 교체

Klippa는 공식 NuGet 패키지가 없습니다. Klippa 통합을 지원하기 위해 존재하는 HTTP 클라이언트 종속성을 제거하십시오.

# Remove Klippa-related packages (if installed for REST support)
dotnet remove package Newtonsoft.Json
dotnet remove package System.Net.Http.Json
SHELL

NuGet 에서IronOCR설치하세요.

dotnet add package IronOcr

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

Klippa 통합에 필요한 HTTP 및 JSON 네임스페이스를 제거합니다.IronOCR네임스페이스를 하나 추가합니다.

// Before (Klippa integration)
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Text.Json.Serialization;

// After (IronOCR)
using IronOcr;
C#

단계 3: 라이선스 초기화

라이선스 초기화를 응용 프로그램 시작 시 한 번 설정 — Program.cs, Startup.cs, 또는 첫 번째 OCR 호출 전에:

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

코드 마이그레이션 예제

HTTP 클라이언트 서비스 클래스 교체

Klippa 통합에는 HTTP 인프라를 감싸는 완전한 서비스 클래스가 필요합니다. SDK가 없기 때문에 이를 피할 방법이 없습니다.

클리파 접근법:

// Klippa: entire service class just to send one HTTP request
public class KlippaOcrService : IDisposable
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl = "https://custom-ocr.klippa.com/api/v1";

    public KlippaOcrService(string apiKey)
    {
        _httpClient = new HttpClient();
        _httpClient.DefaultRequestHeaders.Add("X-Auth-Key", apiKey);
        _httpClient.Timeout = TimeSpan.FromSeconds(30); // network timeout required
    }

    public async Task<string> ReadDocumentTextAsync(string filePath)
    {
        using var form = new MultipartFormDataContent();
        var fileBytes = await File.ReadAllBytesAsync(filePath);
        form.Add(new ByteArrayContent(fileBytes), "document", Path.GetFileName(filePath));

        var response = await _httpClient.PostAsync($"{_baseUrl}/parseDocument", form);
        response.EnsureSuccessStatusCode();

        var json = await response.Content.ReadAsStringAsync();
        using var doc = JsonDocument.Parse(json);
        // navigate Klippa's nested JSON schema
        return doc.RootElement
            .GetProperty("data")
            .GetProperty("parsed_document")
            .GetProperty("text")
            .GetString() ?? string.Empty;
    }

    public void Dispose() => _httpClient.Dispose();
}
C#

IronOCR 접근 방식:

// IronOCR: no HTTP, no JSON navigation, no Dispose plumbing
public class OcrService
{
    private readonly IronTesseract _ocr = new IronTesseract();

    public string ReadDocumentText(string filePath)
    {
        return _ocr.Read(filePath).Text;
    }
}

// At startup:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Usage — identical call site, different internals:
var service = new OcrService();
var text = service.ReadDocumentText("invoice.jpg"); // local, synchronous, zero network
C#

Klippa 서비스 클래스는 API가 HTTP 인프라를 필요로 하기 때문에 존재하는 것입니다. IronOCR의 같은 기능은 단일 Read() 호출로 축소됩니다. 네트워크 연결이 없기 때문에 타임아웃, 인증 헤더 및 폐기 패턴이 모두 사라집니다. IronTesseract 설정 가이드 에서 초기화 옵션을 확인하고, 기본 OCR 예제 에서 작동 코드를 확인하세요.

다중 파트 양식 업로드 제거

Klippa는 문서를 여러 부분으로 구성된 양식 업로드 방식으로 수신합니다. 업로드 코드는 기계적이지만 취약합니다. 파일 읽기, 콘텐츠 유형 헤더, 경계 구성 및 업로드 크기 관리 등이 여기에 해당합니다.

클리파 접근법:

// Klippa: multipart upload — every document is an HTTP form POST
public async Task<KlippaResult> UploadAndParseAsync(
    string filePath, string documentType = "financial")
{
    using var form = new MultipartFormDataContent();

    // read file into memory — entire document in RAM before upload
    var fileBytes = await File.ReadAllBytesAsync(filePath);
    var byteContent = new ByteArrayContent(fileBytes);
    byteContent.Headers.ContentType =
        new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg");

    form.Add(byteContent, "document", Path.GetFileName(filePath));
    form.Add(new StringContent(documentType), "DocumentType");

    // document leaves your server here
    var response = await _httpClient.PostAsync(
        "https://custom-ocr.klippa.com/api/v1/parseDocument", form);

    if (!response.IsSuccessStatusCode)
    {
        var error = await response.Content.ReadAsStringAsync();
        throw new InvalidOperationException($"Klippa API error: {response.StatusCode}{error}");
    }

    var json = await response.Content.ReadAsStringAsync();
    return JsonSerializer.Deserialize<KlippaResult>(json,
        new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
}
C#

IronOCR 접근 방식:

// IronOCR: load from file path, byte array, or stream — no upload, no form
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// From file path
using var input = new OcrInput();
input.LoadImage("invoice.jpg");
var result = new IronTesseract().Read(input);

// From byte array (same bytes Klippa was uploading)
byte[] fileBytes = await File.ReadAllBytesAsync("invoice.jpg");
using var inputFromBytes = new OcrInput();
inputFromBytes.LoadImage(fileBytes);
var resultFromBytes = new IronTesseract().Read(inputFromBytes);

Console.WriteLine(result.Text);
C#

MultipartFormDataContent 구성, 콘텐츠 타입 헤더 및 업로드 자체가 모두 사라졌습니다. IronOCR는 파일 경로, 바이트 배열 또는 Stream에서 직접 읽습니다 — Klippa가 전송하던 동일한 데이터가 로컬에 남아 있습니다. 이미지 입력 ​​가이드는 지원되는 모든 입력 형식을 다루고, 스트림 입력 가이드는 상위 프로세스에서 바이트 배열로 전달되는 문서의 메모리 스트림 경로를 다룹니다.

JSON 응답 역직렬화 대체

Klippa는 중첩된 JSON 구조를 반환합니다. 해당 구조를 탐색하려면 일치하는 C# 모델이나 인라인 JsonDocument 탐색이 필요합니다 — 이는 모두 Klippa가 응답 스키마를 변경하면 깨집니다.

클리파 접근법:

// Klippa: deserialization model — breaks when API schema changes
public class KlippaResponse
{
    [JsonPropertyName("data")]
    public KlippaData Data { get; set; }
}

public class KlippaData
{
    [JsonPropertyName("parsed_document")]
    public KlippaParsedDocument ParsedDocument { get; set; }
}

public class KlippaParsedDocument
{
    [JsonPropertyName("text")]
    public string Text { get; set; }

    [JsonPropertyName("amount")]
    public decimal? Amount { get; set; }

    [JsonPropertyName("merchant")]
    public string Merchant { get; set; }

    [JsonPropertyName("date")]
    public string Date { get; set; }
}

// Usage: navigate the nullable chain every time
public async Task<string> GetExtractedTextAsync(string imagePath)
{
    var klippaResult = await UploadAndParseAsync(imagePath);
    // every property access is nullable — schema drift breaks this silently
    return klippaResult?.Data?.ParsedDocument?.Text ?? string.Empty;
}
C#

IronOCR 접근 방식:

// IronOCR: typed result object — no JSON schema, no nullable chains
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

var ocr = new IronTesseract();
var result = ocr.Read("invoice.jpg");

// Direct property access — no deserialization, no nullable navigation
string fullText   = result.Text;
double confidence = result.Confidence;
int pageCount     = result.Pages.Count();

// Structured data: lines and words with coordinates
foreach (var page in result.Pages)
{
    foreach (var line in page.Lines)
    {
        Console.WriteLine($"Line: '{line.Text}' at Y={line.Y}");
    }
}
C#

OcrResult은 타입화된 .NET 객체입니다. JSON을 파싱할 필요도 없고, 모델 클래스를 유지 관리할 필요도 없으며, 스키마 변경으로 인해 프로덕션 환경의 역직렬화가 중단될 위험도 없습니다. 결과 읽기 가이드는 단어 좌표, 신뢰도 점수 및 구조화된 페이지 계층을 포함한 완전한 OcrResult 객체 모델을 문서화합니다. 송장 별 특정 필드 추출 패턴은 OcrResult 위에 구축됩니다. 송장 OCR 튜토리얼은 종합적인 추출 로직을 다룹니다.

오류 처리 및 재시도 인프라 제거

HTTP를 통한 Klippa 통합에는 네트워크 호출에서 발생할 수 있는 모든 오류 모드(타임아웃, 4xx 응답, 5xx 응답, 속도 제한 및 부분 JSON)에 대한 오류 처리가 필요합니다. 프로덕션 통합을 실행하는 팀은 Polly 또는 사용자 지정 로직을 사용하여 재시도 정책을 추가합니다. 네트워크 호출이 사라지면 해당 인프라도 사라집니다.

클리파 접근법:

// Klippa: retry policy required — cloud calls fail unpredictably
public async Task<string> ReadWithRetryAsync(string filePath, int maxRetries = 3)
{
    var delay = TimeSpan.FromSeconds(1);

    for (int attempt = 1; attempt <= maxRetries; attempt++)
    {
        try
        {
            using var form = new MultipartFormDataContent();
            form.Add(
                new ByteArrayContent(await File.ReadAllBytesAsync(filePath)),
                "document",
                Path.GetFileName(filePath));

            using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
            var response = await _httpClient.PostAsync(
                "https://custom-ocr.klippa.com/api/v1/parseDocument", form, cts.Token);

            if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
            {
                // rate limited — back off and retry
                await Task.Delay(delay * attempt);
                continue;
            }

            response.EnsureSuccessStatusCode();
            var json = await response.Content.ReadAsStringAsync(cts.Token);
            var parsed = JsonSerializer.Deserialize<KlippaResponse>(json);
            return parsed?.Data?.ParsedDocument?.Text ?? string.Empty;
        }
        catch (HttpRequestException) when (attempt < maxRetries)
        {
            await Task.Delay(delay * attempt); // exponential backoff
        }
        catch (TaskCanceledException) when (attempt < maxRetries)
        {
            await Task.Delay(delay * attempt); // timeout — retry
        }
    }

    throw new InvalidOperationException($"Klippa API failed after {maxRetries} attempts");
}
C#

IronOCR 접근 방식:

// IronOCR: no network, no retry policy needed — local call either works or throws once
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

public string ReadDocument(string filePath)
{
    // 아니요 retry loop. 아니요 CancellationTokenSource. 아니요 HTTP status checks.
    // 아니요 rate limit handling. 아니요 partial-JSON guards.
    var result = new IronTesseract().Read(filePath);
    return result.Text;
}
C#

전체 재시도 인프라 — 루프, 지연 계산, CancellationTokenSource, HTTP 상태 코드 분기, TaskCanceledException 예외 처리 블록 — 이 모든 것은 네트워크 때문에 존재합니다. 네트워크 호출을 제거하면 모든 것이 사라집니다. 로컬 OCR 호출은 입력 파일이 없거나 읽을 수 없는 경우 유형 예외와 함께 즉시 실패하고, 그렇지 않은 경우에는 성공합니다. 마이그레이션 후 처리량이 문제가 되는 경우 속도 최적화 가이드 에서IronOCR성능 튜닝에 대해 설명합니다.

클라우드 업로드 없이 여러 페이지로 구성된 PDF 파일 처리하기

Klippa는 동일한 parseDocument 엔드포인트를 통해 PDF 업로드를 수락합니다. 여러 페이지로 구성된 PDF 파일은 여전히 ​​네트워크를 통해 전송됩니다.IronOCR PDF 파일을 자체적으로 읽어들이며, 페이지별 결과 접근이 가능한 처리 과정 내에 자동 읽기 기능을 제공합니다.

클리파 접근법:

// Klippa: PDF upload — entire document transmitted, results depend on cloud availability
public async Task<List<string>> ExtractPdfPagesAsync(string pdfPath)
{
    var pages = new List<string>();

    // Klippa parses the entire PDF server-side and returns combined results
    // You cannot control per-page processing or access raw page text
    using var form = new MultipartFormDataContent();
    form.Add(
        new ByteArrayContent(await File.ReadAllBytesAsync(pdfPath)),
        "document",
        Path.GetFileName(pdfPath));

    var response = await _httpClient.PostAsync(
        "https://custom-ocr.klippa.com/api/v1/parseDocument", form);
    response.EnsureSuccessStatusCode();

    var json = await response.Content.ReadAsStringAsync();
    var result = JsonSerializer.Deserialize<KlippaResponse>(json);
    // Klippa returns the combined parsed text — no per-page breakdown in basic API
    pages.Add(result?.Data?.ParsedDocument?.Text ?? string.Empty);

    return pages;
}
C#

IronOCR 접근 방식:

// IronOCR: native PDF OCR with per-page structured access — no upload
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

using var input = new OcrInput();
input.LoadPdf("multi-page-invoice.pdf"); // reads locally — no HTTP

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

// Per-page access — not available from Klippa's combined response
foreach (var page in result.Pages)
{
    Console.WriteLine($"Page {page.PageNumber}: {page.Lines.Count()} lines");
    Console.WriteLine(page.Text);
}

// Or produce a searchable PDF from the scanned original
result.SaveAsSearchablePdf("searchable-output.pdf");
C#

IronOCR 변환 과정 없이 PDF 파일을 바로 읽을 수 있습니다. 각 페이지는 전체 줄, 단어 및 문자 계층 구조를 유지하며 개별적으로 접근할 수 있습니다. SaveAsSearchablePdf() 호출은 스캔한 문서에서 텍스트 레이어 PDF를 생성합니다 — Klippa가 제공하지 않는 기능입니다. PDF 입력 가이드는 로딩 옵션을 다루고, 검색 가능한 PDF 가이드는 보관 규정 준수를 위한 PDF/A를 포함한 출력 옵션을 다룹니다.

클리파 OCR API와IronOCR매핑 참조

Klippa는 타입이 지정된 SDK가 아니라 REST API입니다. 아래 매핑은 Klippa의 적분 표면을IronOCR에 해당하는 값으로 변환합니다.

클리파 컨셉IronOCR에 상응하는
HttpClientX-Auth-Key 헤더 포함IronTesseract 인스턴스 — 인증 설정 필요 없음
MultipartFormDataContentOcrInput.LoadImage(path) 혹은 OcrInput.LoadPdf(path)
POST /api/v1/parseDocumentIronTesseract.Read(input)
await _client.PostAsync(...)ocr.Read(input) — 동기식, await 필요 없음
response.EnsureSuccessStatusCode()필요 없음 - HTTP 응답 없음
JsonSerializer.Deserialize<KlippaResponse>(json)타입화된 OcrResult — 역직렬화 없음
KlippaResponse.Data.ParsedDocument.TextOcrResult.Text
KlippaResponse.Data.ParsedDocument.Amount사용자 정의 정규 표현식 OcrResult.Text 또는 OcrResult.Lines
KlippaResponse.Data.ParsedDocument.MerchantOcrResult.Pages[0].Lines[0].Text
Task.Delay을 가진 재시도 루프필요 없음 - 네트워크 장애 모드가 없음
CancellationTokenSource(TimeSpan.FromSeconds(30))필요 없음 - 로컬 실행
속도 제한 처리(HTTP 429)필요 없음 - 요금 제한 없음
클라우드 문서를 EU 서버로 라우팅로컬 프로세스 내 실행
KlippaService.Dispose() / HttpClient.Dispose()OcrInputusing 문을 통해 처리
구조화된 JSON 응답 필드OcrResult.Text + OcrResult.Pages + OcrResult.Words
SaaS API 구독IronOcr.License.LicenseKey 문자열 — 영구적

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

문제 1: HTTP 제거 후 비동기 전용 호출 사이트

Klippa: HTTP 호출에 비동기 방식이 필요하기 때문에 모든 Klippa 통합은 비동기 방식으로 이루어집니다. 컨트롤러, 서비스, 그리고 코드베이스 전반에 걸친 백그라운드 작업자들은 await ProcessDocumentAsync(...)을 호출합니다. HTTP 호출을 제거하면 await이 더 이상 필요 없지만, async 메서드 서명은 동일하게 유지됩니다.

해결책: IronOCR는 동기 및 비동기 API를 모두 제공합니다. 비동기 상태를 유지해야 하는 호출 사이트(ASP.NET Core 컨트롤러, CancellationToken을 가진 백그라운드 서비스)의 경우 ReadAsync을 사용하세요:

// Keep async method signatures — switch the implementation
public async Task<string> ProcessDocumentAsync(
    string filePath, CancellationToken cancellationToken = default)
{
    // Previously: await _httpClient.PostAsync(...)
    // Now: local call, same awaitable pattern
    var ocr = new IronTesseract();
    var result = await ocr.ReadAsync(filePath);
    return result.Text;
}
C#

비동기 OCR 가이드는 ASP.NET Core 및 호스트된 서비스 패턴에 대한 ReadAsyncCancellationToken 통합을 다룹니다.

문제 2: 의존성 주입 등록

Klippa: KlippaService 클래스가 DI에서 싱글톤 또는 스코프된 서비스로 등록되며 HttpClient을 래핑합니다. 이를 제거한다는 것은 DI 등록 및 모든 주입 지점을 업데이트하는 것을 의미합니다.

해결책: IronTesseract을 싱글톤으로 등록하세요(스레드 안전). 직접 주입하거나 기존 서비스 인터페이스를 반영하는 얇은 래퍼를 만드세요:

// In Program.cs or Startup.cs
builder.Services.AddSingleton<IronTesseract>();

// Or wrap for interface compatibility
builder.Services.AddSingleton<IOcrService, IronOcrService>();

public class IronOcrService : IOcrService
{
    private readonly IronTesseract _ocr;
    public IronOcrService(IronTesseract ocr) => _ocr = ocr;

    public string ReadDocument(string path) => _ocr.Read(path).Text;
}
C#

하나의 IronTesseract 인스턴스가 싱글톤으로 등록되어 동시 요청을 처리합니다. 각 Read() 호출은 스레드 안전합니다.

문제 3: JSON 사전 파싱 없이 구조화된 필드 추출

Klippa: Klippa는 amount, merchant, date, vat_amount을 타입화된 JSON 속성으로 반환합니다.IronOCR로 마이그레이션하면 해당 필드는 더 이상 사전 구문 분석된 상태로 제공되지 않습니다.

해결책: IronOCR의 OcrResult은 원시 텍스트와 단어 수준 좌표를 제공하여 동등한 추출을 구축합니다. 레이아웃이 예측 가능한 문서의 경우, 영역 기반 OCR은 특정 필드를 직접 대상으로 합니다.

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

// Target specific layout regions instead of relying on pre-parsed cloud fields
var totalRegion   = new CropRectangle(350, 580, 250, 50); // bottom-right total area
var merchantRegion = new CropRectangle(50, 30, 400, 60);  // top header area

using var merchantInput = new OcrInput();
merchantInput.LoadImage("receipt.jpg", merchantRegion);
var merchantName = new IronTesseract().Read(merchantInput).Text.Trim();

using var totalInput = new OcrInput();
totalInput.LoadImage("receipt.jpg", totalRegion);
var totalText = new IronTesseract().Read(totalInput).Text.Trim();
C#

영역 기반 OCR 가이드CropRectangle 사용법을 자세히 다룹니다. 영수증 및 송장 레이아웃 전반에 걸친 전체 패턴 추출을 위해, 영수증 스캔 튜토리얼은 완벽하게 작동하는 코드를 제공합니다.

문제 4: 상위 서비스에서 스트림 형태로 도착하는 문서

Klippa: Klippa는 파일을 HTTP 폼 콘텐츠로 래핑한 멀티파트 폼 업로드 방식으로 문서를 수신합니다. 애플리케이션이 S3, Azure Blob Storage 또는 내부 API에서 스트림 형태로 문서를 수신하는 경우, 해당 스트림을 바이트로 읽은 다음 해당 바이트를 Klippa에 업로드하고 있는 것입니다.

해결책: IronOCR는 Stream 객체를 직접 수용합니다. 바이트 변환 단계가 사라집니다.

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

// Stream from S3, Azure Blob, or any upstream source
public async Task<string> ProcessDocumentStreamAsync(Stream documentStream)
{
    using var input = new OcrInput();
    input.LoadImage(documentStream); // accepts Stream directly

    var ocr = new IronTesseract();
    var result = ocr.Read(input);
    return result.Text;
}
C#

ReadAllBytes 없고, MultipartFormDataContent 구성도 없으며, HTTP POST도 없습니다. 스트림은 바로 OcrInput으로 들어갑니다. 하천 유입 지침에는 하천 유형 및 처리 방식이 설명되어 있습니다.

문제 5: HTTP 모킹에 의존하는 통합 테스트

Klippa: Klippa 코드 통합 테스트는 HttpClient를 모의하거나 HTTP 인터셉터(e.g., WireMock, MockHttp)를 사용하여 API 응답을 시뮬레이션합니다. 해당 테스트는 OCR 로직이 아닌 HTTP 계층을 모킹하는 것입니다.

**해결책:**IronOCR테스트는 예상 출력값이 알려진 실제 문서를 사용합니다. 모킹 인프라가 필요하지 않습니다. 오프라인에서 실행되는 테스트:

[Fact]
public void ReadDocument_ReturnsExpectedText()
{
    IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
    var ocr = new IronTesseract();

    // Use a real test fixture — no HTTP mocking, runs fully offline
    var result = ocr.Read("test-fixtures/sample-invoice.jpg");

    Assert.Contains("Invoice", result.Text, StringComparison.OrdinalIgnoreCase);
    Assert.True(result.Confidence > 70);
}
C#

이전에는 실제 Klippa 연결이나 복잡한 HTTP 모의 설정이 필요했던 테스트가 이제 네트워크 액세스 없이 CI에서 실행됩니다.

이슈 6: Klippa가 서버 측에서 개선한 저품질 문서

Klippa: 클라우드 프로세싱은 인식 전에 이미지 향상을 적용합니다. 개발자는 이 설정을 구성할 필요가 없습니다. Klippa 서버에서 자동으로 처리됩니다. 마이그레이션 시 Klippa에서 자동으로 처리한 문서는IronOCR에서 명시적인 전처리를 하지 않으면 정확도가 떨어질 수 있습니다.

해결 방법: IronOCR의 전처리 필터를 명시적으로 적용합니다. 필터 세트는 클라우드 서비스가 서버 측에서 적용하는 것과 동일합니다.

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

using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");
input.Deskew();    // fix rotation from camera or scanner
input.DeNoise();   // remove compression noise
input.Contrast();  // boost faded ink
input.Binarize();  // clean background for clearer character edges

var result = new IronTesseract().Read(input);
Console.WriteLine($"Confidence: {result.Confidence}%");
C#

이미지 품질 보정 가이드는 모든 전처리 필터와 다양한 문서 손상 유형에 대한 필터 적용 순서를 다룹니다.

클리파 OCR 마이그레이션 체크리스트

사전 마이그레이션

코드베이스를 검토하여 Klippa 관련 코드를 모두 찾은 후, 필요한 코드를 삭제하십시오.

# Find all files containing Klippa HTTP integration code
grep -r "X-Auth-Key" --include="*.cs" .
grep -r "klippa.com" --include="*.cs" .
grep -r "KlippaService\|KlippaResponse\|KlippaResult\|KlippaData" --include="*.cs" .

# Find all files with MultipartFormDataContent (likely Klippa upload code)
grep -r "MultipartFormDataContent" --include="*.cs" .

# Find all JSON deserialization models that map to Klippa response fields
grep -r "parsed_document\|vat_amount\|merchant\|X-Auth-Key" --include="*.cs" .

# Find all async methods that wrap Klippa calls
grep -r "ParseDocumentAsync\|ProcessReceiptAsync\|UploadAndParseAsync" --include="*.cs" .

# Find test files with HTTP mocks for Klippa
grep -r "MockHttp\|WireMock\|klippa" --include="*.cs" .
SHELL

재고 관련 참고 사항:

  • Klippa 호출을 위한 HttpClient을 래핑하는 모든 클래스를 기록하세요
  • 모든 JSON 역직렬화 모델 클래스(KlippaResponse, KlippaParsedDocument 등)를 나열하세요
  • Klippa의 미리 파싱된 JSON 속성을 사용하는 모든 필드 매핑을 문서화합니다.
  • Klippa용으로 구축된 Polly 재시도 정책이나 사용자 지정 재시도 루프를 참고하십시오.

코드 마이그레이션

  1. IronOcr NuGet 패키지 (dotnet add package IronOcr) 설치
  2. 응용 프로그램 시작에 IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY" 추가
  3. Klippa 서비스 파일에서 System.Net.Http, System.Text.Json, Newtonsoft.Json 불러오기를 제거하세요
  4. KlippaService 클래스를 삭제하거나 그 본문을 IronTesseract 호출로 대체하여 인터페이스를 유지하세요
  5. IronTesseract을 DI 컨테이너에 싱글톤으로 등록하세요
  6. MultipartFormDataContent 업로드 블록을 OcrInput.LoadImage() 또는 OcrInput.LoadPdf()으로 교체하세요
  7. JSON 응답 모델 클래스(KlippaResponse, KlippaData, KlippaParsedDocument) 삭제
  8. 널 가능 JSON 탐색 체인(.Data?.ParsedDocument?.Text)을 result.Text으로 교체하세요
  9. 재시도 루프와 Klippa 호출 사이트의 CancellationTokenSource 타임아웃을 제거하세요
  10. 속도 제한 처리 제거 (HTTP 429 차단)
  11. await ProcessDocumentAsync(...)await ocr.ReadAsync(...) 또는 동기식 ocr.Read(...)로 교체하세요
  12. 저급 문서 입력에 대한 OcrInput 전처리 필터 (Deskew, DeNoise, Contrast) 추가
  13. HTTP 모의 테스트 인프라를 실제 문서 픽스처 테스트로 교체
  14. Klippa 호출에 적용되는 Polly 재시도 정책 또는 사용자 지정 재시도 미들웨어를 삭제합니다.

마이그레이션 이후

  • 텍스트 추출 결과가 알려진 테스트 문서의 예상 내용과 일치하는지 확인합니다.
  • 프로덕션 문서 유형에 대해 신뢰도 점수가 허용 가능한 임계값(일반적으로 70% 이상)을 초과하는지 확인합니다.
  • PDF 입력 테스트: 여러 페이지 PDF를 네이티브로 로드하고 result.Pages을 통한 페이지별 텍스트 접근을 확인하세요
  • 스트림 입력 테스트: MemoryStream을 전달하고 OcrInput.LoadImage(stream)이 올바른 출력을 생성하는지 확인하세요
  • 전처리 필터가 처리되지 않은 기준선에 비해 저품질 스캔의 정확도를 향상시키는지 확인합니다.
  • DI가 주입된 IronTesseract 싱글톤이 경쟁 없이 동시 요청을 처리하는지 확인
  • 통합 테스트는 오프라인(네트워크 연결 없이)에서 실행해야 합니다. 모든 테스트는 클라우드 액세스 없이도 통과해야 합니다.
  • 스캔된 문서 흐름을 위한 result.SaveAsSearchablePdf("output.pdf") 첨부물로 검색 가능한 PDF 출력 확인
  • ReadAsync을 ASP.NET Core 컨트롤러 컨텍스트에서 CancellationToken 전파와 함께 테스트
  • 지속적인 부하 하에서 메모리 누수가 없음을 확인하는 using var input = new OcrInput() 처리 패턴 확인

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

데이터 주권은 처음부터 보장됩니다. 마이그레이션 후에도 민감한 금융 문서, 신원 확인 이미지, 기밀 청구서는 귀사 인프라 외부로 유출되지 않습니다. 감사 범위에 제3자 처리업체가 없으며, 검토해야 할 데이터 보존 정책도 없고, 유지 관리해야 할 데이터 전송 계약도 없습니다. 이전에는 Klippa 사용에 문제를 일으켰던 HIPAA, ITAR, CMMC 및 FedRAMP 제약 조건이 기본적으로 충족됩니다. Docker , AWS 또는 Azure 에 배포하면 모든 것이 자체 인프라 경계 내에 유지됩니다.

인프라 복잡성이 제거되었습니다. 서비스 클래스, HTTP 클라이언트, 폼 업로드 코드, JSON 모델, 재시도 정책, 타임아웃 구성 등 이 모든 것은 네트워크 호출을 래핑하기 위해 존재했습니다. 네트워크 호출을 제거하면 모든 것이 함께 사라집니다. 결과적으로 코드베이스는 더 작아지고, 읽기 쉬워지며, 오류 발생 가능성이 줄어듭니다. DI를 통해 주입된 단일 IronTesseract 인스턴스가 전체 HTTP 통합 레이어를 대체합니다.

예측 가능한 비용: 볼륨에 무관합니다. $999 (Lite), $1,499 (Professional), 또는 $2,999 (Enterprise)로 제공되는 영구IronOCR라이선스는 무제한 문서 처리를 보장합니다. 한 달에 500건의 문서를 처리하든 50만 건을 처리하든 비용은 동일합니다. Klippa를 대규모로 사용할 때 비용을 증가시켰던 문서별 청구 방식은 이제 구조적으로 사라졌습니다. IronOCR 라이선스 페이지에는 모든 등급과 각 등급에 포함되는 내용이 자세히 나와 있습니다.

**문서 범위에 제한이 없습니다.**IronOCR텍스트가 포함된 모든 문서를 처리합니다. 스캔된 계약서, 기술 도면, 의료 양식, 구매 주문서, 수기로 작성된 노트, 스크린샷, TIFF 아카이브 — 동일한 API로 동일한 Read() 호출을 통해 처리됩니다. Klippa에서 교육받은 범주 외의 문서에 대해 별도의 시스템이 필요했던 전문 분야 제한이 사라졌습니다. 하나의 라이브러리, 하나의 통합 지점, 모든 문서 유형.

오프라인 및 제한된 네트워크 환경이 이제 지원됩니다. 은행 네트워크, 정부 시스템, 엣지 환경 또는 외부 트래픽 전송이 제한된 모든 인프라에 배포된 애플리케이션은 개방형 환경에서와 동일하게 실행됩니다. 연결 상태 확인이나 클라우드 엔드포인트에 대한 상태 점검 기능이 없으며, 인터넷 연결이 불가능할 때 성능 저하 모드도 지원하지 않습니다. 에어갭 방식으로 구축하면 수정 없이 작동합니다. Linux 배포 가이드Docker 배포 가이드는 이러한 환경에 대한 컨테이너 기반 배포 경로와 서버 측 배포 경로를 다룹니다.

이미지 향상에 대한 완벽한 제어. 클라우드 전처리는 블랙박스 방식이었습니다. Klippa가 전처리를 적용하면 사용자는 결과를 확인하고 조정할 매개변수가 없었습니다. IronOCR의 전처리 파이프라인은 명시적이고 조합 가능: Deskew(), DeNoise(), Contrast(), Binarize(), Sharpen(), Scale(), Dilate(), DeepCleanBackgroundNoise(). 각 필터는 선택 사항이며 주문해야 합니다. 정확도 향상은 측정 가능하고, 재현 가능하며, 사용자가 제어할 수 있습니다. 이미지 품질 보정 가이드전처리 기능 페이지 에서는 전체 필터 카탈로그와 각 필터 적용 시점에 대한 지침을 제공합니다.

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

관련 기사

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일 무료 체험판 키를 받으세요.
신용카드나 계정 생성은 필요하지 않습니다.