푸터 콘텐츠로 바로가기
다른 구성 요소와 비교

IronOCR 과 Nanonets OCR 비교

AWS Textract의 페이지당 가격 모델은 저볼륨에서는 저렴해 보일 수 있지만, 대규모에서는 비용이 무한히 누적됩니다. 귀하의 애플리케이션이 처리하는 모든 문서는 당신의 네트워크를 떠나 Amazon 데이터 센터로 이동하며, Amazon 인프라에 의해 처리되며, 그 청구서는 무한히 누적됩니다. .NET 환경에서 OCR 옵션을 검토 중인 팀에게 중요한 점은 Textract가 정확한 결과를 제공하는지 여부(물론 제공합니다)뿐만 아니라, 페이지당 비용 모델, 필수 클라우드 전송, 다중 페이지 문서를 위한 비동기 폴링 아키텍처가 귀사의 애플리케이션에 실제로 필요한 요건과 부합하는지 여부입니다.

AWS Textract이해하기

AWS Textract는 Amazon의 관리 문서 분석 서비스로, AWSSDK.Textract NuGet 패키지를 통해 .NET용 AWS SDK로 액세스할 수 있습니다. 이 서비스는 클라우드 API 방식으로 작동합니다. 애플리케이션에서 문서 데이터를 Amazon의 인프라로 전송하면 구조화된 결과를 수신하게 됩니다. 이 서비스를 이용하려면 AWS 계정, Textract 권한이 부여된 IAM 자격 증명, 그리고 모든 OCR 작업에 대한 인터넷 연결이 필요합니다.

Textract는 각각 별도로 요금이 부과되는 여러 가지 분석 모드를 제공합니다:

  • DetectDocumentText: 기본 텍스트 추출 (현재 페이지당 요금은 AWS Textract 가격 참조)
  • AnalyzeDocument (테이블): 기본 텍스트보다 높은 페이지당 요금의 구조화된 테이블 추출
  • AnalyzeDocument (양식): 키-값 양식 추출은 테이블 추출보다 높은 페이지당 요금을 가집니다
  • AnalyzeExpense: 페이지당 0.01달러에 청구서 및 영수증 분석
  • AnalyzeID: 신분증 정보 추출, 페이지당 $0.025
  • StartDocumentTextDetection / StartDocumentAnalysis: 다중 페이지 PDF 처리에 필요한 비동기 API로, S3 스테이징 버킷, 작업 폴링 및 결과 페이지 분할이 필수입니다.

결과 모델은 관계 ID를 사용하여 표, 양식 또는 구조화된 출력을 재구성하기 위해 순회해야 하는 Block 객체의 평면 목록을 사용합니다. 단순 테이블 추출에는 BlockType.TABLE 블록을 반복하고 RelationshipType.CHILD 관계 ID를 통해 자식 BlockType.CELL 블록을 찾은 다음 각 셀의 텍스트에 대한 BlockType.WORD 블록을 검색하는 작업이 필요합니다. 이 관계 그래프 모델은 복잡한 문서 구조를 처리할 수 있지만, 가벼운 구조는 아닙니다.

S3-Async 파이프라인

DetectDocumentTextAsync을 통한 단일 이미지 OCR은 요청에서 문서 바이트를 직접 전달할 수 있습니다. 다중 페이지 PDF는 불가능합니다. 모든 PDF에는 완전한 비동기 파이프라인이 필요합니다:

// AWS Textract: 다중 페이지 PDF requires S3 + async job
public async Task<string> ProcessPdfAsync(string pdfPath)
{
    // Step 1: Upload to S3 — credentials for two services required
    var key = $"uploads/{Guid.NewGuid()}.pdf";
    using (var fileStream = File.OpenRead(pdfPath))
    {
        await _s3Client.PutObjectAsync(new PutObjectRequest
        {
            BucketName = _bucketName,
            Key = key,
            InputStream = fileStream
        });
    }

    try
    {
        // Step 2: Start async Textract job
        var startResponse = await _textractClient.StartDocumentTextDetectionAsync(
            new StartDocumentTextDetectionRequest
            {
                DocumentLocation = new DocumentLocation
                {
                    S3Object = new S3Object { Bucket = _bucketName, Name = key }
                }
            });

        var jobId = startResponse.JobId;

        // Step 3: Poll every 5 seconds until complete
        GetDocumentTextDetectionResponse getResponse;
        do
        {
            await Task.Delay(5000);
            getResponse = await _textractClient.GetDocumentTextDetectionAsync(
                new GetDocumentTextDetectionRequest { JobId = jobId });
        } while (getResponse.JobStatus == JobStatus.IN_PROGRESS);

        if (getResponse.JobStatus != JobStatus.SUCCEEDED)
            throw new Exception($"Textract job failed: {getResponse.StatusMessage}");

        // Step 4: Paginate through result blocks
        var allText = new StringBuilder();
        string nextToken = null;
        do
        {
            var pageResponse = await _textractClient.GetDocumentTextDetectionAsync(
                new GetDocumentTextDetectionRequest
                {
                    JobId = jobId,
                    NextToken = nextToken
                });

            foreach (var block in pageResponse.Blocks.Where(b => b.BlockType == BlockType.LINE))
                allText.AppendLine(block.Text);

            nextToken = pageResponse.NextToken;
        } while (nextToken != null);

        return allText.ToString();
    }
    finally
    {
        // Step 5: 항상 clean up S3
        await _s3Client.DeleteObjectAsync(_bucketName, key);
    }
}
// AWS Textract: 다중 페이지 PDF requires S3 + async job
public async Task<string> ProcessPdfAsync(string pdfPath)
{
    // Step 1: Upload to S3 — credentials for two services required
    var key = $"uploads/{Guid.NewGuid()}.pdf";
    using (var fileStream = File.OpenRead(pdfPath))
    {
        await _s3Client.PutObjectAsync(new PutObjectRequest
        {
            BucketName = _bucketName,
            Key = key,
            InputStream = fileStream
        });
    }

    try
    {
        // Step 2: Start async Textract job
        var startResponse = await _textractClient.StartDocumentTextDetectionAsync(
            new StartDocumentTextDetectionRequest
            {
                DocumentLocation = new DocumentLocation
                {
                    S3Object = new S3Object { Bucket = _bucketName, Name = key }
                }
            });

        var jobId = startResponse.JobId;

        // Step 3: Poll every 5 seconds until complete
        GetDocumentTextDetectionResponse getResponse;
        do
        {
            await Task.Delay(5000);
            getResponse = await _textractClient.GetDocumentTextDetectionAsync(
                new GetDocumentTextDetectionRequest { JobId = jobId });
        } while (getResponse.JobStatus == JobStatus.IN_PROGRESS);

        if (getResponse.JobStatus != JobStatus.SUCCEEDED)
            throw new Exception($"Textract job failed: {getResponse.StatusMessage}");

        // Step 4: Paginate through result blocks
        var allText = new StringBuilder();
        string nextToken = null;
        do
        {
            var pageResponse = await _textractClient.GetDocumentTextDetectionAsync(
                new GetDocumentTextDetectionRequest
                {
                    JobId = jobId,
                    NextToken = nextToken
                });

            foreach (var block in pageResponse.Blocks.Where(b => b.BlockType == BlockType.LINE))
                allText.AppendLine(block.Text);

            nextToken = pageResponse.NextToken;
        } while (nextToken != null);

        return allText.ToString();
    }
    finally
    {
        // Step 5: 항상 clean up S3
        await _s3Client.DeleteObjectAsync(_bucketName, key);
    }
}
Imports System
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks
Imports Amazon.Textract
Imports Amazon.Textract.Model
Imports Amazon.S3
Imports Amazon.S3.Model

Public Class PdfProcessor
    Private _s3Client As IAmazonS3
    Private _textractClient As IAmazonTextract
    Private _bucketName As String

    Public Async Function ProcessPdfAsync(pdfPath As String) As Task(Of String)
        ' Step 1: Upload to S3 — credentials for two services required
        Dim key = $"uploads/{Guid.NewGuid()}.pdf"
        Using fileStream = File.OpenRead(pdfPath)
            Await _s3Client.PutObjectAsync(New PutObjectRequest With {
                .BucketName = _bucketName,
                .Key = key,
                .InputStream = fileStream
            })
        End Using

        Try
            ' Step 2: Start async Textract job
            Dim startResponse = Await _textractClient.StartDocumentTextDetectionAsync(
                New StartDocumentTextDetectionRequest With {
                    .DocumentLocation = New DocumentLocation With {
                        .S3Object = New S3Object With {.Bucket = _bucketName, .Name = key}
                    }
                })

            Dim jobId = startResponse.JobId

            ' Step 3: Poll every 5 seconds until complete
            Dim getResponse As GetDocumentTextDetectionResponse
            Do
                Await Task.Delay(5000)
                getResponse = Await _textractClient.GetDocumentTextDetectionAsync(
                    New GetDocumentTextDetectionRequest With {.JobId = jobId})
            Loop While getResponse.JobStatus = JobStatus.IN_PROGRESS

            If getResponse.JobStatus <> JobStatus.SUCCEEDED Then
                Throw New Exception($"Textract job failed: {getResponse.StatusMessage}")
            End If

            ' Step 4: Paginate through result blocks
            Dim allText = New StringBuilder()
            Dim nextToken As String = Nothing
            Do
                Dim pageResponse = Await _textractClient.GetDocumentTextDetectionAsync(
                    New GetDocumentTextDetectionRequest With {
                        .JobId = jobId,
                        .NextToken = nextToken
                    })

                For Each block In pageResponse.Blocks.Where(Function(b) b.BlockType = BlockType.LINE)
                    allText.AppendLine(block.Text)
                Next

                nextToken = pageResponse.NextToken
            Loop While nextToken IsNot Nothing

            Return allText.ToString()
        Finally
            ' Step 5: 항상 clean up S3
            Await _s3Client.DeleteObjectAsync(_bucketName, key)
        End Try
    End Function
End Class
$vbLabelText   $csharpLabel

일반적인 PDF 처리를 위한 최소 기능 구현 - 다섯 단계, 두 개의 AWS 서비스 클라이언트, finally 블록 내 정리 로직. 적절한 오류 처리, 속도 제한 재시도 로직, 타임아웃 관리 기능이 포함된 완성된 프로덕션 버전은 150~300줄 정도입니다.

IronOCR이해하기

IronOCR은 사용자의 인프라에서 완전히 실행되는 상 for .NET OCR 라이브러리입니다. 이 라이브러리는 자동 이미지 전처리, 네이티브 PDF 지원, 외부 서비스 호출이나 중간 단계 없이 직접 결과를 산출하는 동기식 API를 갖춘 최적화된 Tesseract 5 엔진을 포함하고 있습니다.

IronOCR 아키텍처의 주요 특징:

  • 로컬 처리 전용: 애플리케이션이 실행되는 컴퓨터 외부로 문서 데이터가 유출되지 않습니다.
  • 단일 NuGet 패키지: dotnet add package IronOcr은 네이티브 바이너리를 포함한 모든 것을 설치합니다.
  • 자동 전처리: 화질이 낮은 입력 데이터에 대해 기울기 보정, 노이즈 제거, 명암 대비 강화, 이진화 및 해상도 조정 작업이 자동으로 수행됩니다.
  • 네이티브 PDF 지원: S3 스테이징이나 비동기 작업 없이 파일 경로 또는 스트림을 통해 PDF를 직접 읽습니다.
  • 스레드 안전성: 단일 IronTesseract 인스턴스가 스레드 간의 동시 요청을 대기 없이 처리합니다.
  • 영구 라이선싱: $999 Lite / $1,499 Plus / $2,999 Professional / $5,999 Unlimited - 한 번의 결제, 페이지당 비용 없음, 사용량 측정 없음.
  • 125개 이상의 언어 팩: 별도의 NuGet 패키지로 설치되며, 로컬에서 로드되므로 네트워크 호출이 필요하지 않습니다.

기능 비교

기능 AWS Textract IronOCR
처리 위치 Amazon 클라우드 (필수) 로컬 / 온프레미스
다중 페이지 PDF S3 + 비동기 작업 필요 직접 동기식 호출
비용 모델 페이지당 (현재 가격에 대한 AWS 문의) 영구 라이선스, 페이지당 요금 없음
인터넷 연결 필요 항상 절대
인증 정보 설정 IAM 사용자/역할 + 선택적 S3 단일 라이선스 키 문자열
에어갭 배포 불가능 완전히 지원
암호화된 PDF 지원 지원되지 않음 내장형 (비밀번호 매개변수)

상세 기능 비교

기능 AWS Textract IronOCR
텍스트 추출
기본 OCR (이미지) 예 — DetectDocumentTextAsync 예 — ocr.Read(path)
다중 페이지 PDF S3 및 비동기 폴링 필요 직접 input.LoadPdf(path)
비밀번호로 보호된 PDF 지원되지 않음 input.LoadPdf(path, Password: "x")
스트림 입력 예 (요청 내 바이트 배열) 예 — input.LoadImage(stream)
구조화된 추출
테이블 추출 AnalyzeDocument + 블록 그래프 탐색 WORD 위치 기반 재구성
양식 필드 추출 AnalyzeDocument + KEY_VALUE_SET 블록 지역 기반 CropRectangle 지역
문장 단위 결과 Block BlockType.LINE에 의한 필터링 result.Lines 직접 수집
WORD 단위(좌표 포함) Block BlockType.WORD에 의한 필터링 result.Words .X, .Y, .Width 포함
신뢰도 점수 블록별 신뢰도 단어별 및 전체 result.Confidence
처리 모델
동기식 (이미지) 예 (단일 페이지만 가능) 예 (모든 문서 유형)
비동기 PDF 파일에 필수 항목입니다. 선택 사항 — Task.Run() 래퍼
일괄 처리 속도 제한 관리가 필요합니다(기본값 5 TPS). 제한되지 않은 Parallel.ForEach
전처리
자동 기울기 보정 노출되지 않음 input.Deskew()
노이즈 제거 내부(설정 불가) input.DeNoise()
명암 대비 강화 내부(설정 불가) input.Contrast()
해상도 향상 내부(설정 불가) input.EnhanceResolution(300)
이진화 내부 input.Binarize()
출력 형식
일반 텍스트
검색 가능한 PDF 아니요 result.SaveAsSearchablePdf(path)
hOCR 아니요 result.SaveAsHocrFile(path)
구조화된 JSON 블록 직렬화를 통해 result.Words / result.Lines
배포
온프레미스 아니요
에어갭 아니요
Docker 예 (AWS 자격 증명을 입력하면) 예 (자격증명 필요 없음)
AWS 람다 내부 지원 지원됨
Azure
Linux 예 (AWS 관리형) 예 — get-started/linux/
규정 준수
HIPAA AWS와의 BAA(비즈니스 계약)가 필요합니다. 외부 프로세서 없음
GDPR 데이터가 AWS 리전으로 전송됩니다. 데이터는 경계 내에 유지됩니다.
ITAR 특별 허가 없이는 금지됨 완전 온프레미스
에어갭 / CMMC 레벨 3 불가능 지원됨

대규모 생산 비용

페이지당 가격 모델은 AWS Textract의 핵심적인 구조적 제약 조건입니다. 페이지 당 작게 보이는 비용도 실제 문서 워크플로우에서는 상당한 축적으로 연결됩니다.

AWS Textract접근법

// Every call to this method costs money — per page, permanently
public async Task<string> DetectTextAsync(string imagePath)
{
    var imageBytes = File.ReadAllBytes(imagePath);  // Image leaves your network

    var request = new DetectDocumentTextRequest
    {
        Document = new Document
        {
            Bytes = new MemoryStream(imageBytes)
        }
    };

    var response = await _client.DetectDocumentTextAsync(request);  // per-page charge

    return string.Join("\n", response.Blocks
        .Where(b => b.BlockType == BlockType.LINE)
        .Select(b => b.Text));
}
// Every call to this method costs money — per page, permanently
public async Task<string> DetectTextAsync(string imagePath)
{
    var imageBytes = File.ReadAllBytes(imagePath);  // Image leaves your network

    var request = new DetectDocumentTextRequest
    {
        Document = new Document
        {
            Bytes = new MemoryStream(imageBytes)
        }
    };

    var response = await _client.DetectDocumentTextAsync(request);  // per-page charge

    return string.Join("\n", response.Blocks
        .Where(b => b.BlockType == BlockType.LINE)
        .Select(b => b.Text));
}
Imports System.IO
Imports System.Threading.Tasks

' Every call to this method costs money — per page, permanently
Public Async Function DetectTextAsync(imagePath As String) As Task(Of String)
    Dim imageBytes = File.ReadAllBytes(imagePath)  ' Image leaves your network

    Dim request = New DetectDocumentTextRequest With {
        .Document = New Document With {
            .Bytes = New MemoryStream(imageBytes)
        }
    }

    Dim response = Await _client.DetectDocumentTextAsync(request)  ' per-page charge

    Return String.Join(vbLf, response.Blocks _
        .Where(Function(b) b.BlockType = BlockType.LINE) _
        .Select(Function(b) b.Text))
End Function
$vbLabelText   $csharpLabel

AWS Textract 요금 페이지에서 현재 페이지 당 요금을 확인하세요. 다양한 API 기능(기본 텍스트 감지, 테이블 추출, 양식 추출)은 서로 다른 요금을 가지고 있습니다. 테이블 및 양식 필드가 포함된 문서는 기본 텍스트 감지보다 높은 요금이 발생하며, 상한선 없이 볼륨이 증가할수록 비용도 증가하며 미리 지불하는 방법이 없습니다.

페이지 볼륨이 높을 때 3년 총 비용은 상당할 수 있으며, 미터기는 계속 작동합니다.

IronOCR접근법

// One license. 아니요 per-page cost. Same code handles 1 page or 1,000,000.
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

var text = new IronTesseract().Read("document.jpg").Text;
// One license. 아니요 per-page cost. Same code handles 1 page or 1,000,000.
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

var text = new IronTesseract().Read("document.jpg").Text;
' One license. 아니요 per-page cost. Same code handles 1 page or 1,000,000.
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

Dim text = New IronTesseract().Read("document.jpg").Text
$vbLabelText   $csharpLabel

$2,999 Professional 라이선스는 10명의 개발자, 무제한 프로젝트, 무제한 페이지 볼륨을 포함합니다. 첫 해 이후에는 페이지 처리 비용이 전혀 발생하지 않습니다. 상당한 페이지 볼륨을 처리하는 팀의 경우,IronOCR라이선스는 지속적인 페이지 당 클라우드 요금과 비교했을 때 빠르게 비용을 회수합니다.

IronOCR 라이선스 페이지에는 등급 세부 정보, 사용량 기반 청구 시나리오를 위한 SaaS 구독 옵션 및 OEM 재배포 조건이 포함되어 있습니다.

데이터 주권 및 규정 준수

AWS Textract의 아키텍처는 문서가 인프라 내에 유지된다는 것을 보장할 수 없게 만듭니다. 모든 OCR 작업은 문서 내용을 아마존 서버로 전송합니다.

AWS Textract접근법

// This code sends PHI, legal documents, financial records — whatever is in
// the file — to Amazon Web Services infrastructure
public async Task<string> ProcessSensitiveDocumentAsync(string documentPath)
{
    var imageBytes = File.ReadAllBytes(documentPath);

    // Data crosses your security perimeter here
    var request = new DetectDocumentTextRequest
    {
        Document = new Document
        {
            Bytes = new MemoryStream(imageBytes)
        }
    };

    // Amazon processes it; you receive text back
    var response = await _client.DetectDocumentTextAsync(request);

    return string.Join("\n", response.Blocks
        .Where(b => b.BlockType == BlockType.LINE)
        .Select(b => b.Text));
}
// This code sends PHI, legal documents, financial records — whatever is in
// the file — to Amazon Web Services infrastructure
public async Task<string> ProcessSensitiveDocumentAsync(string documentPath)
{
    var imageBytes = File.ReadAllBytes(documentPath);

    // Data crosses your security perimeter here
    var request = new DetectDocumentTextRequest
    {
        Document = new Document
        {
            Bytes = new MemoryStream(imageBytes)
        }
    };

    // Amazon processes it; you receive text back
    var response = await _client.DetectDocumentTextAsync(request);

    return string.Join("\n", response.Blocks
        .Where(b => b.BlockType == BlockType.LINE)
        .Select(b => b.Text));
}
Imports System.IO
Imports System.Threading.Tasks
Imports Amazon.Textract
Imports Amazon.Textract.Model

Public Class DocumentProcessor
    Private _client As AmazonTextractClient

    Public Sub New(client As AmazonTextractClient)
        _client = client
    End Sub

    ' This code sends PHI, legal documents, financial records — whatever is in
    ' the file — to Amazon Web Services infrastructure
    Public Async Function ProcessSensitiveDocumentAsync(documentPath As String) As Task(Of String)
        Dim imageBytes = File.ReadAllBytes(documentPath)

        ' Data crosses your security perimeter here
        Dim request As New DetectDocumentTextRequest With {
            .Document = New Document With {
                .Bytes = New MemoryStream(imageBytes)
            }
        }

        ' Amazon processes it; you receive text back
        Dim response = Await _client.DetectDocumentTextAsync(request)

        Return String.Join(vbLf, response.Blocks _
            .Where(Function(b) b.BlockType = BlockType.LINE) _
            .Select(Function(b) b.Text))
    End Function
End Class
$vbLabelText   $csharpLabel

AWS는 HIPAA(미국 의료정보 보호법)에 따라 관련 기관을 위한 비즈니스 제휴 계약(BAA)을 제공하며, GovCloud 리전은 FedRAMP High 인증을 지원합니다. 이러한 프레임워크는 기본적인 아키텍처를 변경하지 않습니다. 문서들은 모든 작업마다 인프라에서 분리되어 나갑니다. ITAR(국제 무기 거래 규정)의 적용을 받는 기술 데이터의 경우, 이는 단순한 규정 준수 문제가 아니라 금지 사항입니다. CUI를 포함하는 CMMC 레벨 3 워크로드의 경우, 클라우드 전송에는 특정 권한이 필요하지만 대부분의 방위산업체는 이러한 권한을 보유하고 있지 않습니다. 연구 네트워크, 산업 제어 환경, 기밀 시설과 같은 외부 네트워크가 차단된 시스템의 경우 Textract는 사용할 수 없습니다.

AWS Textract는 여섯 지역에서 이용 가능: us-east-1, us-west-2, eu-west-1, eu-west-2, ap-southeast-1, ap-southeast-2. 이러한 지역 외부에 데이터 상주 요건이 있는 조직은 규정을 준수할 수 있는 선택지가 없습니다.

IronOCR접근법

// IronOCR: document bytes never leave this process
public string ProcessSensitiveDocument(string documentPath)
{
    // Processes entirely on local hardware — no network call
    var ocr = new IronTesseract();
    return ocr.Read(documentPath).Text;
}
// IronOCR: document bytes never leave this process
public string ProcessSensitiveDocument(string documentPath)
{
    // Processes entirely on local hardware — no network call
    var ocr = new IronTesseract();
    return ocr.Read(documentPath).Text;
}
' IronOCR: document bytes never leave this process
Public Function ProcessSensitiveDocument(documentPath As String) As String
    ' Processes entirely on local hardware — no network call
    Dim ocr As New IronTesseract()
    Return ocr.Read(documentPath).Text
End Function
$vbLabelText   $csharpLabel

IronOCR 로컬에서 실행되므로 PHI를 처리하는 의료 워크플로, 기밀 통신을 처리하는 법률 문서 시스템, 결제 카드 이미지를 처리하는 금융 애플리케이션 및 CUI를 처리하는 방위 산업체 파이프라인에 자연스럽게 통합됩니다. 감사해야 할 외부 처리업체도 없고, 협상해야 할 사업 제휴 계약(BAA)도 없으며, 충족해야 할 데이터 상주 제약 조건도 없습니다. 규정 준수 범위는 귀사 자체의 인프라입니다.

AWS 인프라에 배포하지만 로컬 처리가 필요한 팀의 경우,IronOCR Textract에 대한 의존성 없이 AWS EC2 및 Lambda에서 실행됩니다 . 즉, 처리는 Amazon의 관리형 서비스가 아닌 사용자의 AWS 계정 경계 내에서 이루어집니다.

비동기 폴링과 동기 처리의 차이점

Textract의 동기식(단일 이미지) API와 비동기식(다중 페이지 PDF) API 간의 아키텍처적 차이는 사소한 API 세부 사항이 아닙니다. 이는 서비스 구축 방식, 오류 처리 방식, 그리고 유지보수 담당자가 읽고 이해해야 하는 코드의 양에 영향을 미칩니다.

AWS Textract접근법

// Full production-grade async processor for Textract PDF handling
public class TextractAsyncProcessor
{
    private readonly AmazonTextractClient _textractClient;
    private readonly AmazonS3Client _s3Client;
    private readonly string _bucketName;
    private readonly TimeSpan _pollInterval = TimeSpan.FromSeconds(5);
    private readonly TimeSpan _maxWaitTime = TimeSpan.FromMinutes(10);

    public async Task<DocumentResult> ProcessDocumentAsync(
        string localFilePath,
        CancellationToken cancellationToken = default)
    {
        var s3Key = $"textract-uploads/{Guid.NewGuid()}{Path.GetExtension(localFilePath)}";

        try
        {
            // Phase 1: Upload to S3
            await UploadToS3Async(localFilePath, s3Key, cancellationToken);

            // Phase 2: Start Textract job
            var jobId = await StartTextractJobAsync(s3Key, cancellationToken);

            // Phase 3: Poll until complete (up to 10 minutes)
            var pollResult = await PollForCompletionAsync(jobId, cancellationToken);

            if (!pollResult.Success)
                throw new Exception($"Textract job failed: {pollResult.ErrorMessage}");

            // Phase 4: Retrieve paginated results
            return await GetAllResultsAsync(jobId, cancellationToken);
        }
        finally
        {
            // Phase 5: S3 cleanup — must succeed or storage costs accumulate
            await DeleteFromS3Async(s3Key, cancellationToken);
        }
    }

    private async Task<(bool Success, string ErrorMessage)> PollForCompletionAsync(
        string jobId, CancellationToken cancellationToken)
    {
        var startTime = DateTime.UtcNow;
        int pollCount = 0;

        while (DateTime.UtcNow - startTime < _maxWaitTime)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var response = await _textractClient.GetDocumentTextDetectionAsync(
                new GetDocumentTextDetectionRequest { JobId = jobId }, cancellationToken);

            pollCount++;

            switch (response.JobStatus)
            {
                case JobStatus.SUCCEEDED: return (true, null);
                case JobStatus.FAILED: return (false, response.StatusMessage ?? "Unknown error");
                case JobStatus.IN_PROGRESS:
                    await Task.Delay(_pollInterval, cancellationToken);
                    break;
                default:
                    throw new Exception($"Unknown job status: {response.JobStatus}");
            }
        }

        return (false, "Job timed out");
    }
}
// Full production-grade async processor for Textract PDF handling
public class TextractAsyncProcessor
{
    private readonly AmazonTextractClient _textractClient;
    private readonly AmazonS3Client _s3Client;
    private readonly string _bucketName;
    private readonly TimeSpan _pollInterval = TimeSpan.FromSeconds(5);
    private readonly TimeSpan _maxWaitTime = TimeSpan.FromMinutes(10);

    public async Task<DocumentResult> ProcessDocumentAsync(
        string localFilePath,
        CancellationToken cancellationToken = default)
    {
        var s3Key = $"textract-uploads/{Guid.NewGuid()}{Path.GetExtension(localFilePath)}";

        try
        {
            // Phase 1: Upload to S3
            await UploadToS3Async(localFilePath, s3Key, cancellationToken);

            // Phase 2: Start Textract job
            var jobId = await StartTextractJobAsync(s3Key, cancellationToken);

            // Phase 3: Poll until complete (up to 10 minutes)
            var pollResult = await PollForCompletionAsync(jobId, cancellationToken);

            if (!pollResult.Success)
                throw new Exception($"Textract job failed: {pollResult.ErrorMessage}");

            // Phase 4: Retrieve paginated results
            return await GetAllResultsAsync(jobId, cancellationToken);
        }
        finally
        {
            // Phase 5: S3 cleanup — must succeed or storage costs accumulate
            await DeleteFromS3Async(s3Key, cancellationToken);
        }
    }

    private async Task<(bool Success, string ErrorMessage)> PollForCompletionAsync(
        string jobId, CancellationToken cancellationToken)
    {
        var startTime = DateTime.UtcNow;
        int pollCount = 0;

        while (DateTime.UtcNow - startTime < _maxWaitTime)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var response = await _textractClient.GetDocumentTextDetectionAsync(
                new GetDocumentTextDetectionRequest { JobId = jobId }, cancellationToken);

            pollCount++;

            switch (response.JobStatus)
            {
                case JobStatus.SUCCEEDED: return (true, null);
                case JobStatus.FAILED: return (false, response.StatusMessage ?? "Unknown error");
                case JobStatus.IN_PROGRESS:
                    await Task.Delay(_pollInterval, cancellationToken);
                    break;
                default:
                    throw new Exception($"Unknown job status: {response.JobStatus}");
            }
        }

        return (false, "Job timed out");
    }
}
Imports System
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Imports Amazon.Textract
Imports Amazon.S3
Imports Amazon.Textract.Model

' Full production-grade async processor for Textract PDF handling
Public Class TextractAsyncProcessor
    Private ReadOnly _textractClient As AmazonTextractClient
    Private ReadOnly _s3Client As AmazonS3Client
    Private ReadOnly _bucketName As String
    Private ReadOnly _pollInterval As TimeSpan = TimeSpan.FromSeconds(5)
    Private ReadOnly _maxWaitTime As TimeSpan = TimeSpan.FromMinutes(10)

    Public Async Function ProcessDocumentAsync(localFilePath As String, Optional cancellationToken As CancellationToken = Nothing) As Task(Of DocumentResult)
        Dim s3Key = $"textract-uploads/{Guid.NewGuid()}{Path.GetExtension(localFilePath)}"

        Try
            ' Phase 1: Upload to S3
            Await UploadToS3Async(localFilePath, s3Key, cancellationToken)

            ' Phase 2: Start Textract job
            Dim jobId = Await StartTextractJobAsync(s3Key, cancellationToken)

            ' Phase 3: Poll until complete (up to 10 minutes)
            Dim pollResult = Await PollForCompletionAsync(jobId, cancellationToken)

            If Not pollResult.Success Then
                Throw New Exception($"Textract job failed: {pollResult.ErrorMessage}")
            End If

            ' Phase 4: Retrieve paginated results
            Return Await GetAllResultsAsync(jobId, cancellationToken)
        Finally
            ' Phase 5: S3 cleanup — must succeed or storage costs accumulate
            Await DeleteFromS3Async(s3Key, cancellationToken)
        End Try
    End Function

    Private Async Function PollForCompletionAsync(jobId As String, cancellationToken As CancellationToken) As Task(Of (Success As Boolean, ErrorMessage As String))
        Dim startTime = DateTime.UtcNow
        Dim pollCount As Integer = 0

        While DateTime.UtcNow - startTime < _maxWaitTime
            cancellationToken.ThrowIfCancellationRequested()

            Dim response = Await _textractClient.GetDocumentTextDetectionAsync(New GetDocumentTextDetectionRequest With {.JobId = jobId}, cancellationToken)

            pollCount += 1

            Select Case response.JobStatus
                Case JobStatus.SUCCEEDED
                    Return (True, Nothing)
                Case JobStatus.FAILED
                    Return (False, If(response.StatusMessage, "Unknown error"))
                Case JobStatus.IN_PROGRESS
                    Await Task.Delay(_pollInterval, cancellationToken)
                Case Else
                    Throw New Exception($"Unknown job status: {response.JobStatus}")
            End Select
        End While

        Return (False, "Job timed out")
    End Function
End Class
$vbLabelText   $csharpLabel

이것은 생성하고 잊어버릴 수 있는 정형화된 문구가 아닙니다. Textract 작업이 실행 도중에 실패하더라도 S3 정리 작업은 반드시 실행되어야 합니다. 작업이 10분 후에 시간 초과되면 호출자는 명확한 오류 메시지를 받아야 합니다. 폴링 중에 네트워크 연결이 끊어지면 재시도 전략은 중복 작업을 생성해서는 안 됩니다. 이러한 각 오류 모드에는 명시적인 처리가 필요하며, 위에 표시된 구조는 최소한의 책임감 있는 구현 방식입니다.

배치 처리에는 또 다른 계층이 추가됩니다: Textract의 기본 StartDocumentTextDetection TPS 제한은 초당 5 요청입니다. 100개의 문서를 처리하려면 SemaphoreSlim 제동, 비율 보충 타이머, ProvisionedThroughputExceededException을 위한 재시도 로직이 필요합니다.

IronOCR접근법

// IronOCR: same synchronous API regardless of document type or size
public string ProcessDocument(string filePath)
{
    using var input = new OcrInput();

    if (Path.GetExtension(filePath).Equals(".pdf", StringComparison.OrdinalIgnoreCase))
        input.LoadPdf(filePath);
    else
        input.LoadImage(filePath);

    return new IronTesseract().Read(input).Text;
}
// IronOCR: same synchronous API regardless of document type or size
public string ProcessDocument(string filePath)
{
    using var input = new OcrInput();

    if (Path.GetExtension(filePath).Equals(".pdf", StringComparison.OrdinalIgnoreCase))
        input.LoadPdf(filePath);
    else
        input.LoadImage(filePath);

    return new IronTesseract().Read(input).Text;
}
Imports System.IO

' IronOCR: same synchronous API regardless of document type or size
Public Function ProcessDocument(filePath As String) As String
    Using input As New OcrInput()
        If Path.GetExtension(filePath).Equals(".pdf", StringComparison.OrdinalIgnoreCase) Then
            input.LoadPdf(filePath)
        Else
            input.LoadImage(filePath)
        End If

        Return New IronTesseract().Read(input).Text
    End Using
End Function
$vbLabelText   $csharpLabel

폴링 루프도 없고, 작업 ID 추적도 없고, S3 버킷도 없고, 결과 페이지네이션도 없습니다. 동일한 코드가 JPEG 이미지 한 장과 200페이지짜리 PDF 파일을 모두 처리합니다. 처리가 완료되거나 오류가 발생합니다. 중간 단계인 "진행 중" 상태를 관리할 필요가 없습니다. 배치 처리의 경우, IronOCR는 스레드 안전성을 제공하며, 단일 IronTesseract 인스턴스가 Parallel.ForEach을 잠금이나 세마포어 없이 처리합니다.

IronTesseract 설정 가이드는 구성 방법을 다루고, PDF 입력 가이드는 페이지 범위 선택, 암호로 보호된 PDF, 데이터베이스 또는 HTTP 응답에서 가져온 PDF에 대한 스트림 기반 입력 방법을 설명합니다.

자격 증명 관리 간접비

AWS Textract를 사용하여 OCR 작업을 시작하려면 단일 페이지를 처리하기 전에 IAM 구성을 수행해야 합니다.

AWS Textract접근법

DetectDocumentTextAsync를 호출하기 전에 개발자는 다음을 수행해야 합니다:

  1. AWS 계정을 생성하거나 기존 계정에 대한 액세스 권한을 얻으세요.
  2. textract:DetectDocumentTexttextract:AnalyzeDocument 권한이 있는 IAM 사용자 또는 역할 생성
  3. 액세스 키 ID와 비밀 액세스 키를 생성하고 안전하게 저장합니다.
  4. 자격 증명 확인 구성 - 환경 변수, AWS 자격 증명 파일 또는 EC2 인스턴스 프로필
  5. PDF를 처리하는 경우: S3 버킷 생성, 버킷 정책 구성, s3:PutObjects3:DeleteObject 권한 추가
  6. 보안 표준을 충족하기 위해 자격 증명 순환 정책을 시행합니다.
  7. 각 배포 환경에 자격 증명을 안전하게 저장하십시오. (Docker 비밀 키, Kubernetes 비밀 키, AWS Secrets Manager 또는 CI/CD 파이프라인 변수)
// Every environment needs these configured before this constructor succeeds
public TextractOcrService()
{
    // Reads credentials from environment, ~/.aws/credentials, or IAM role
    _client = new AmazonTextractClient(Amazon.RegionEndpoint.USEast1);
}
// Every environment needs these configured before this constructor succeeds
public TextractOcrService()
{
    // Reads credentials from environment, ~/.aws/credentials, or IAM role
    _client = new AmazonTextractClient(Amazon.RegionEndpoint.USEast1);
}
' Every environment needs these configured before this constructor succeeds
Public Sub New()
    ' Reads credentials from environment, ~/.aws/credentials, or IAM role
    _client = New AmazonTextractClient(Amazon.RegionEndpoint.USEast1)
End Sub
$vbLabelText   $csharpLabel

자격 증명이 만료되거나 회전되거나 잘못 구성된 경우, 모든 OCR 호출은 AmazonTextractExceptionErrorCode == "AccessDeniedException"를 동반한 실패로 끝납니다. 실제 운영 시스템에서는 자격 증명 오류에 대한 특정 예외 처리 블록을 구현하고 IAM 정책 변경 사항을 모니터링해야 합니다.

IronOCR접근법

// One-time setup at application startup
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Or from environment — recommended for deployments
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
// One-time setup at application startup
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Or from environment — recommended for deployments
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
' One-time setup at application startup
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

' Or from environment — recommended for deployments
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
$vbLabelText   $csharpLabel

라이선스 키는 고정된 문자열입니다. 이 라이선스는 작동 중에 만료되지 않으며, 교체가 필요하지 않고, 관리 권한도 필요하지 않습니다. 문서를 처리하는 Docker컨테이너는 AWS 자격 증명 주입, 실행 컨텍스트에 바인딩된 IAM 역할 또는 토큰 갱신을 위한 AWS STS 네트워크 액세스가 필요하지 않습니다.

Textract에서 IronOCR로 이동할 때 자격 증명 오버헤드를 완전히 줄입니다: 세 개의 NuGet 패키지 제거 (AWSSDK.Textract, AWSSDK.S3, AWSSDK.Core), 모든 AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_DEFAULT_REGION 환경 변수를 제거하고, IAM 역할 및 S3 버킷 구성 해체. 이미지 입력 ​​가이드스트림 입력 가이드는 Textract의 바이트 배열 및 S3 객체 문서 모델을 대체하는 모든 입력 방식을 다룹니다.

API 매핑 참조

AWS TextractAPI IronOCR에 상응하는
AmazonTextractClient IronTesseract
AmazonS3Client 필요하지 않음
DetectDocumentTextRequest OcrInput
DetectDocumentTextResponse OcrResult
AnalyzeDocumentRequest OcrInput 및 영역을 위한 CropRectangle 포함
StartDocumentTextDetectionRequest OcrInput — 동기식, 시작 필요 없음
GetDocumentTextDetectionRequest 필수 사항이 아닙니다. 결과는 즉시 나타납니다.
Document.Bytes input.LoadImage(bytes) 또는 input.LoadImage(stream)
S3Object (문서 스테이징) 파일 경로 문자열 또는 스트림
Block (BlockType.LINE) result.Lines
Block (BlockType.WORD) result.Words
Block (BlockType.TABLE) 단어 위치 그룹화 result.Words 통해
Block (BlockType.KEY_VALUE_SET) CropRectangle 지역 추출
Block.Confidence word.Confidence / result.Confidence
JobStatus.SUCCEEDED 해당 없음 — 동기식 반환
JobStatus.IN_PROGRESS 해당 사항 없음 — 비동기 상태 없음
response.NextToken (페이지매김) 해당 사항 없음 — 결과가 페이지별로 표시되지 않습니다.
ProvisionedThroughputExceededException 해당 사항 없음 - TPS 제한 없음
client.DetectDocumentTextAsync(request) ocr.Read(path)
client.AnalyzeDocumentAsync(request) ocr.Read(input)
client.StartDocumentTextDetectionAsync(request) ocr.Read(input)
client.GetDocumentTextDetectionAsync(request) 적용 안 됨

팀이 AWS Textract에서IronOCR로 마이그레이션을 고려할 때

월별 청구서가 예산 항목이 될 때

Textract를 소량으로 사용하기 시작한 팀은 종종 특정 상황에 직면합니다. 분기별 예산 검토에서 OCR 처리에 대한 AWS 청구서가 나타나고 누군가가 이 비용이 고정 비용인지 묻는 순간입니다. 그렇지 않습니다. 페이지 볼륨이 높을 때 연간 Textract 비용이 상당할 수 있습니다 — AWS Textract 요금 페이지에서 현재 요금을 확인하세요.IronOCR Professional 라이선스는 $2,999 한 번의 결제로 중간에서 높은 페이지 볼륨에서 빠르게 비용을 상쇄합니다.

규정 준수 요건으로 인해 클라우드 처리가 차단되는 경우

의료기관들이 문서 디지털화 워크플로우를 구현하는 과정에서 HIPAA(미국 의료정보 보호법)에 따른 개인 건강 정보(PHI)를 클라우드 서비스를 통해 전송하려면 사업 제휴 계약(BAA) 및 추가적인 법률 검토가 필요하다는 사실을 프로젝트 도중에 알게 되거나, 보안팀에서 클라우드 전송 자체를 금지한다는 사실을 알게 되는 경우가 종종 있습니다. 기술 도면, 사양 또는 기타 기밀 정보(CUI)를 취급하는 방위 산업체는 ITAR및 CMMC 규정으로 인해 AWS Textract를 사용할 수 없습니다. 기밀 유지 대상인 의사소통을 처리하는 법률 회사들도 비슷한 우려를 가지고 있습니다. 이는 이론적인 규정 준수 예외 사례가 아니라, 조달 검토, 보안 감사 및 계약 협상에서 정기적으로 발생하는 문제입니다.IronOCR로컬에서 처리하므로 문서 데이터에 대한 규정 준수 문제는 Amazon 인프라가 규정 범위에 해당하는지 여부가 아니라 자체 인프라가 규정 범위에 해당하는지 여부로 귀결됩니다.

비동기 PDF 처리의 복잡성이 허용치를 초과할 때

5단계로 구성된 S3 비동기 파이프라인(업로드, 작업 시작, 폴링, 결과 페이지네이션, 정리)은 기술적으로 구현하기 어렵지 않습니다. 유지 관리, 테스트 및 운영이 어렵습니다. 모든 단계가 실패 지점입니다. S3 업로드 실패 시 재시도 로직이 필요합니다. Textract 작업 실패의 경우 일시적인 오류와 영구적인 오류를 구분해야 합니다. 폴링 시간 초과는 취소 처리와 별도로 시간 초과 처리를 해야 합니다. 결과 페이지네이션에는 여러 API 호출에 걸쳐 상태를 누적해야 합니다. S3 정리 실패는 고아 객체가 누적되어 비용이 발생하기 때문에 경고가 필요합니다. 이 파이프라인을 실제 운영 환경에 배포한 팀은 일반적으로 구축에 투자한 시간보다 유지 관리에 더 많은 엔지니어링 시간을 투자합니다.IronOCR동등물 — input.LoadPdf(path)ocr.Read(input) — 모든 다섯 단계 및 관련 오류 모드를 제거합니다.

배포 환경에 인터넷 접속이 불가능한 경우

격리된 네트워크 세그먼트에서 실행되는 Docker컨테이너, 외부 인터넷 연결이 없는 온프레미스 서버, 에어갭 연구 환경, 엄격한 네트워크 제어가 적용되는 산업 시스템은 모두 한 가지 공통점을 가지고 있습니다. 바로 AWS Textract를 사용할 수 없다는 것입니다.IronOCR표준 NuGet 패키지로 설치되며 설치 후에는 네트워크 호출 없이 작동합니다. 이러한 환경에서 .NET 애플리케이션을 실행하는 팀은 Textract 옵션을 사용할 수 없으므로 로컬에서 처리하는 라이브러리가 필요합니다. Docker 배포 가이드Linux 배포 가이드는 컨테이너 환경에 필요한 구체적인 구성 방법을 다룹니다.

속도 제한으로 인해 배치 워크플로가 중단되는 경우

기본 StartDocumentTextDetection TPS 제한은 초당 5 요청입니다. DetectDocumentText 동기식 호출도 비율 제한을 받습니다. 수백 또는 수천 개의 문서를 처리하는 배치 작업은 SemaphoreSlim 제동, ProvisionedThroughputExceededException에 대한 지수적 백오프, 비율 보충 타이머를 구현해야 합니다. AWS는 TPS 제한 증가 요청을 지원하지만, 이에 대한 타당성 검토가 필요하며 승인이 보장되는 것은 아닙니다.IronOCR로컬 CPU가 허용하는 최대 속도로 작동합니다. 32코어 서버는 속도 제한 설정이나 서비스 계층 협상 없이 32개의 문서를 동시에 처리할 수 있습니다.

일반적인 마이그레이션 고려사항

블록 그래프를 직접 컬렉션으로 대체

Textract는 모든 결과를 평면 List<Block>으로 표현하며, 줄, 단어, 셀, 표, 키-값 쌍은 BlockType에 의해 구별되고 관계 ID 배열로 연결됩니다.IronOCR직접 입력된 데이터를 수집합니다.

// Textract: filter flat block list by type
var lines = response.Blocks.Where(b => b.BlockType == BlockType.LINE);
var words = response.Blocks.Where(b => b.BlockType == BlockType.WORD);

// IronOCR: direct access to typed collections
var result = ocr.Read(imagePath);
var lines = result.Lines;   // IEnumerable<OcrResult.OcrResultLine>
var words = result.Words;   // IEnumerable<OcrResult.OcrResultWord>
foreach (var word in result.Words)
    Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) confidence {word.Confidence}%");
// Textract: filter flat block list by type
var lines = response.Blocks.Where(b => b.BlockType == BlockType.LINE);
var words = response.Blocks.Where(b => b.BlockType == BlockType.WORD);

// IronOCR: direct access to typed collections
var result = ocr.Read(imagePath);
var lines = result.Lines;   // IEnumerable<OcrResult.OcrResultLine>
var words = result.Words;   // IEnumerable<OcrResult.OcrResultWord>
foreach (var word in result.Words)
    Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) confidence {word.Confidence}%");
' Textract: filter flat block list by type
Dim lines = response.Blocks.Where(Function(b) b.BlockType = BlockType.LINE)
Dim words = response.Blocks.Where(Function(b) b.BlockType = BlockType.WORD)

' IronOCR: direct access to typed collections
Dim result = ocr.Read(imagePath)
Dim lines = result.Lines   ' IEnumerable(Of OcrResult.OcrResultLine)
Dim words = result.Words   ' IEnumerable(Of OcrResult.OcrResultWord)
For Each word In result.Words
    Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) confidence {word.Confidence}%")
Next
$vbLabelText   $csharpLabel

구조화된 결과 가이드result.Pages, result.Paragraphs, result.Lines, result.Words 및 레이아웃 인식 문서 처리를 위한 좌표 액세스를 다룹니다.

S3 단계 PDF 처리 방식을 PDF 직접 로드 방식으로 대체

탐지 작업을 시작하기 전에 S3에 업로드되는 Textract 코드는 PDF 파일을 직접 로드하는 것으로 대체할 수 있습니다. 스테이징 버킷도 없고, 업로드 타이밍 설정도 없고, 정리 로직도 없습니다.

// Textract: upload to S3 → start job → poll → paginate → cleanup (50+ lines)
//IronOCR equivalent:
public string ProcessPdf(string pdfPath)
{
    var ocr = new IronTesseract();
    using var input = new OcrInput();
    input.LoadPdf(pdfPath);
    return ocr.Read(input).Text;
}

// Specific page ranges (no Textract equivalent without async job per range)
public string ProcessPdfPages(string pdfPath, int startPage, int endPage)
{
    var ocr = new IronTesseract();
    using var input = new OcrInput();
    input.LoadPdfPages(pdfPath, startPage, endPage);
    return ocr.Read(input).Text;
}
// Textract: upload to S3 → start job → poll → paginate → cleanup (50+ lines)
//IronOCR equivalent:
public string ProcessPdf(string pdfPath)
{
    var ocr = new IronTesseract();
    using var input = new OcrInput();
    input.LoadPdf(pdfPath);
    return ocr.Read(input).Text;
}

// Specific page ranges (no Textract equivalent without async job per range)
public string ProcessPdfPages(string pdfPath, int startPage, int endPage)
{
    var ocr = new IronTesseract();
    using var input = new OcrInput();
    input.LoadPdfPages(pdfPath, startPage, endPage);
    return ocr.Read(input).Text;
}
Imports IronOcr

Public Class PdfProcessor
    ' Textract: upload to S3 → start job → poll → paginate → cleanup (50+ lines)
    ' IronOCR equivalent:
    Public Function ProcessPdf(pdfPath As String) As String
        Dim ocr As New IronTesseract()
        Using input As New OcrInput()
            input.LoadPdf(pdfPath)
            Return ocr.Read(input).Text
        End Using
    End Function

    ' Specific page ranges (no Textract equivalent without async job per range)
    Public Function ProcessPdfPages(pdfPath As String, startPage As Integer, endPage As Integer) As String
        Dim ocr As New IronTesseract()
        Using input As New OcrInput()
            input.LoadPdfPages(pdfPath, startPage, endPage)
            Return ocr.Read(input).Text
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

Textract에서 신뢰도가 낮은 문서에 대한 전처리 추가

Textract의 전처리 과정은 내부적으로 이루어지며 구성할 수 없습니다. 스캔한 문서의 결과가 좋지 않을 경우, 재시도하거나 신뢰도가 낮은 결과물을 받아들이는 것 외에는 다른 선택지가 없습니다.IronOCR전처리 파이프라인을 직접 노출합니다.

// For documents that returned low-confidence results from Textract
using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");

input.Deskew();              // Fix rotation from scanner misalignment
input.DeNoise();             // Remove scanner noise artifacts
input.Contrast();            // Boost faint text
input.EnhanceResolution(300); // Scale to optimal OCR resolution

var result = new IronTesseract().Read(input);
Console.WriteLine($"Confidence: {result.Confidence}%");
// For documents that returned low-confidence results from Textract
using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");

input.Deskew();              // Fix rotation from scanner misalignment
input.DeNoise();             // Remove scanner noise artifacts
input.Contrast();            // Boost faint text
input.EnhanceResolution(300); // Scale to optimal OCR resolution

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

Dim input As New OcrInput()
input.LoadImage("low-quality-scan.jpg")

input.Deskew()              ' Fix rotation from scanner misalignment
input.DeNoise()             ' Remove scanner noise artifacts
input.Contrast()            ' Boost faint text
input.EnhanceResolution(300) ' Scale to optimal OCR resolution

Dim result = New IronTesseract().Read(input)
Console.WriteLine($"Confidence: {result.Confidence}%")
$vbLabelText   $csharpLabel

이미지 품질 교정 가이드이미지 필터 튜토리얼은 전체 사전 처리 파이프라인과 특정 문서 유형에 가장 적합한 조합을 문서화합니다. 신뢰도 점수 해석과 요소별 신뢰도 접근은 신뢰도 점수 가이드result.Confidence 속성과 단어별 신뢰도 값을 다룹니다.

비동기에서 동기 패턴으로의 전환 처리

기존 Textract 코드는 필수적으로 async Task<t>로 구성됩니다. SDK는 비동기 전용이기 때문입니다.IronOCR작업은 동기식으로 진행됩니다. 이미 비동기 호출 체인을 가진 애플리케이션 코드를 위해,IronOCR호출을 Task.Run에 감싸 비동기 경계를 유지하세요.

// Preserves async call site for minimal refactoring
public async Task<string> ExtractTextAsync(string path)
{
    return await Task.Run(() => new IronTesseract().Read(path).Text);
}
// Preserves async call site for minimal refactoring
public async Task<string> ExtractTextAsync(string path)
{
    return await Task.Run(() => new IronTesseract().Read(path).Text);
}
Imports System.Threading.Tasks

' Preserves async call site for minimal refactoring
Public Async Function ExtractTextAsync(path As String) As Task(Of String)
    Return Await Task.Run(Function() New IronTesseract().Read(path).Text)
End Function
$vbLabelText   $csharpLabel

이것은 편의를 위한 포장일 뿐 필수 사항은 아닙니다. 호출 코드가 이미 백그라운드 스레드에서 실행 중인 서버 측 처리의 경우, 동기 호출을 직접 사용하는 것이 좋습니다.

IronOCR의 추가 기능

위의 비교 항목 외에도IronOCR AWS Textract에는 없는 기능을 제공합니다.

  • OCR 중 바코드 읽기: ocr.Configuration.ReadBarCodes = true을 설정하고 문서의 바코드는 텍스트와 함께 한 번에 추출됩니다 — 별도의 바코드 스캔 단계 없음
  • 장시간 작업 진행 상황 추적 : 외부 서비스를 폴링하지 않고 여러 페이지를 처리하는 작업의 진행 상황 이벤트를 구독할 수 있습니다.
  • 스캔 문서 처리 : 양면 스캔 및 다양한 방향의 페이지를 포함하여 일반적인 사무실 스캐너 출력에 최적화된 파이프라인
  • 다중 언어 동시 추출: 읽기 시 언어 팩을 결합하세요 — OcrLanguage.French + OcrLanguage.German — API 계층 변경 없음
  • 여권 및 신분증 판독 : 신분증의 기계 판독 가능 영역을 위한 전용 파이프라인을 통해 수동 영역 정의 없이 구조화된 필드를 추출합니다.

.NET 호환성 및 미래 준비

IronOCR .NET 8 및 .NET 9를 대상으로 하며, .NET Standard 2.0 프로젝트 및 .NET Framework 4.6.2부터 4.8까지의 호환성을 적극적으로 지원합니다. 이 라이브러리는 Windows x64, Windows x86, Linuxx64 및 macOS용 네이티브 바이너리를 단일 NuGet 패키지를 통해 제공하며, 런타임 식별자 전환이나 플랫폼별 패키지 참조가 필요하지 않습니다. AWS Textract의 AWSSDK.Textract 패키지는 동일한 최신 .NET 타겟을 지원하지만, 배포 모델은 전체 AWS SDK 종속성 트리, IAM 자격 증명 인프라, 이 기사 전반에 문서화된 아키텍처 제약을 포함합니다.IronOCR Tesseract 5 엔진 업데이트 및 .NET 런타임 개선 사항을 반영하는 정기적인 릴리스를 통해 활발한 개발을 지속하고 있으며, .NET 10이 출시되면 해당 버전과의 호환성도 제공할 예정입니다.

결론

AWS Textract와IronOcr.NET 애플리케이션에서 문서로부터 텍스트를 추출하는 동일한 문제를 해결하지만, 근본적으로 호환되지 않는 아키텍처적 가정을 기반으로 합니다. Textract는 문서가 네트워크를 벗어날 수 있고, 클라우드 서비스 비용이 볼륨에 비례하여 증가하며, 여러 페이지로 구성된 PDF 파일의 경우 S3 스테이징을 사용하는 5단계 비동기 파이프라인이 필요하다고 가정합니다.IronOCR문서가 처리된 위치에 그대로 유지되고, 라이선스 비용이 처리량과 무관하며, PDF 처리에 필요한 코드가 이미지 처리에 필요한 코드와 동일하게 세 줄이어야 한다고 가정합니다.

비용 산술이 가장 명확한 분기점입니다. 볼륨이 낮을 때 Textract의 페이지당 수수료는 관리가 용이합니다. 볼륨이 증가함에 따라 연간 비용이 상당히 증가합니다. 높은 페이지 볼륨에서 테이블 추출과 함께, 다년 간의 Textract 비용은 심지어 IronOCR의 Unlimited 라이선스 비용 $5,999을 크게 초과할 수 있습니다. 초기 수학은 유지됩니다: 페이지 당 모델은 빠르게 산정되며, 멈추지 않습니다.

데이터 주권은 두 번째 구조적 제약 조건입니다. 의료, 법률, 금융 및 정부 업무의 경우, 문서 처리 장소는 선호도의 문제가 아니라 규정 준수 요건입니다.IronOCR구성 설정이 아닌 설계상 로컬에서 처리됩니다. 활성화할 수 있는 "로컬 모드"는 없습니다. 로컬 처리만 가능합니다. 따라서 규정 준수에 대한 답변은 간단합니다. 문서가 다른 곳으로 이동할 곳이 없으므로 문서는 자체 인프라 내에 그대로 유지됩니다.

실제 규모로 OCR을 평가하는 팀이나 문서 데이터가 내부 인프라 외부로 유출될 수 없는 환경에서 운영하는 팀을 위해 IronOCR의 문서는 완벽한 API 참조, Docker, AWS,Azure및 Linux배포 가이드, 그리고 기본 이미지 읽기부터 검색 가능한 PDF 생성 및 다국어 추출에 이르기까지 모든 OCR 사용 사례를 다루는 튜토리얼을 제공합니다.

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

자주 묻는 질문

Amazon Textract란 무엇인가요?

Amazon Textract는 개발자와 기업이 이미지와 문서에서 텍스트를 추출하는 데 사용하는 OCR 솔루션입니다. 이 솔루션은 .NET 애플리케이션 개발용 IronOCR과 함께 평가된 여러 OCR 옵션 중 하나입니다.

IronOCR은 .NET 개발자를 위한 Amazon Textract와 어떻게 다른가요?

IronOCR은 IronTesseract를 핵심 엔진으로 사용하는 NuGet 네이티브 .NET OCR 라이브러리입니다. Amazon Textract에 비해 배포가 간편하고(SDK 설치 프로그램 없음), 정액제 요금이 적용되며, COM 인터롭이나 클라우드 종속성이 없는 깔끔한 C# API를 제공합니다.

IronOCR이 Amazon Textract보다 설정이 더 쉬운가요?

IronOCR은 단일 NuGet 패키지를 통해 설치됩니다. SDK 설치 프로그램, 복사할 라이선스 파일, 등록할 COM 구성 요소 또는 관리해야 할 별도의 런타임 바이너리가 없습니다. 전체 OCR 엔진이 패키지에 번들로 제공됩니다.

Amazon Textract와 IronOCR에는 어떤 정확도 차이가 있나요?

IronOCR은 표준 비즈니스 문서, 송장, 영수증, 스캔 양식에 대해 높은 인식 정확도를 달성합니다. 품질이 많이 저하된 문서나 일반적이지 않은 스크립트의 경우 정확도는 소스 품질에 따라 달라집니다. IronOCR에는 이미지 전처리 필터가 포함되어 있어 저품질 입력에 대한 인식률을 향상시킵니다.

IronOCR은 PDF 텍스트 추출을 지원하나요?

예. IronOCR은 한 번의 호출로 원본 PDF와 스캔한 PDF 이미지 모두에서 텍스트를 추출합니다. 또한 여러 페이지의 TIFF 파일, 이미지, 스트림도 지원합니다. 스캔한 PDF의 경우 OCR은 페이지별 결과 개체를 사용하여 페이지별로 적용됩니다.

Amazon Textract 라이선싱은 IronOCR과 어떻게 다른가요?

IronOCR은 페이지당 또는 스캔당 요금이 없는 정액제 영구 라이선스를 사용합니다. 대량의 문서를 처리하는 조직은 문서 양에 관계없이 동일한 라이선스 비용을 지불합니다. 자세한 내용과 볼륨 가격은 IronOCR 라이선스 페이지에서 확인할 수 있습니다.

IronOCR 어떤 언어를 지원하나요?

IronOCR은 별도의 NuGet 언어 팩을 통해 127개 언어를 지원합니다. 언어를 추가하려면 '닷넷 추가 패키지 IronOcr.Languages.{Language}' 명령 하나만 있으면 됩니다. 수동으로 파일을 배치하거나 경로를 구성할 필요가 없습니다.

.NET 프로젝트에 IronOCR 설치하는 방법은 무엇인가요?

NuGet을 통해 설치합니다: 패키지 관리자 콘솔에서 '설치-패키지 IronOcr' 또는 CLI에서 '닷넷 추가 패키지 IronOcr'을 실행합니다. 추가 언어 팩도 같은 방법으로 설치됩니다. 기본 SDK 인스톨러가 필요하지 않습니다.

IronOCR은 Amazon Textract와 달리 Docker 및 컨테이너화된 배포에 적합한가요?

예. IronOCR은 NuGet 패키지를 통해 Docker 컨테이너에서 작동합니다. 라이선스 키는 환경 변수를 통해 설정됩니다. OCR 엔진 자체에는 라이선스 파일, SDK 경로 또는 볼륨 마운트가 필요하지 않습니다.

Amazon Textract와 비교하여 구매하기 전에 IronOCR을 사용해 볼 수 있나요?

예. IronOCR 평가판 모드는 문서를 처리하고 출력물에 워터마크 오버레이가 포함된 OCR 결과를 반환합니다. 라이선스를 구매하기 전에 자신의 문서에서 정확성을 확인할 수 있습니다.

IronOCR은 텍스트 추출과 함께 바코드 판독을 지원하나요?

IronOCR은 텍스트 추출과 OCR에 중점을 둡니다. 바코드 판독을 위해 Iron Software는 동반 라이브러리로 IronBarcode를 제공합니다. 두 가지 모두 개별적으로 또는 Iron Suite 번들의 일부로 사용할 수 있습니다.

Amazon Textract에서 IronOCR로 쉽게 마이그레이션할 수 있나요?

Amazon Textract에서 IronOCR로의 마이그레이션에는 일반적으로 초기화 시퀀스를 IronTesseract 인스턴스화로 대체하고, COM 수명 주기 관리를 제거하고, API 호출을 업데이트하는 작업이 포함됩니다. 대부분의 마이그레이션은 코드 복잡성을 크게 줄여줍니다.

칸나오팟 우돈판트
소프트웨어 엔지니어
카나팟은 소프트웨어 엔지니어가 되기 전 일본 홋카이도 대학교에서 환경 자원학 박사 학위를 취득했습니다. 학위 과정 중에는 생물생산공학과 소속 차량 로봇 연구실에서 활동하기도 했습니다. 2022년에는 C# 기술을 활용하여 Iron Software의 엔지니어링 팀에 합류했고, 현재 IronPDF 개발에 집중하고 있습니다. 카나팟은 IronPDF에 사용되는 대부분의 코드를 직접 작성하는 개발자로부터 배울 수 있다는 점에 만족하며, 동료들과의 소통을 통해 배우는 것 외에도 Iron Software에서 일하는 즐거움을 누리고 있습니다. 코딩이나 문서 작업을 하지 않을 때는 주로 PS5로 게임을 하거나 The Last of Us를 다시 시청하는 것을 즐깁니다.

아이언 서포트 팀

저희는 주 5일, 24시간 온라인으로 운영합니다.
채팅
이메일
전화해