C#에서 PDF 파일의 바코드를 읽는 방법
BarcodeScanning.Native.Maui에서 IronBarcode로의 마이그레이션
이 가이드는 BarcodeScanning.Native.Maui에서IronBarcode로의 완벽한 마이그레이션 경로를 제공하며, 카메라 이벤트 패턴 교체, 네임스페이스 변경, 코드 마이그레이션 예제, 그리고 BarcodeScanning.Native.Maui에서 처리할 수 없는 시나리오(Windows MAUI, 파일 및 PDF 입력, 서버 측 처리, 바코드 생성) 처리 방법을 다룹니다.
BarcodeScanning.MAUI에서 마이그레이션해야 하는 이유
BarcodeScanning.Native.Maui에서 마이그레이션하는 팀에서 다음과 같은 문제가 발생한다고 보고합니다.
Windows MAUI 타겟 필요: BarcodeScanning.Native.Maui는 iOS 및 Android 네이티브 API를 래핑합니다. Windows 구현은 없으며 향후 계획도 없습니다. MAUI 앱이 iOS 및 Android 외에도 Windows를 대상으로 하는 경우, 플랫폼별 분기 없이 세 가지 대상 모두에서 작동하는 라이브러리가 필요합니다.
파일 또는 PDF 입력이 요구 사항에 추가되었습니다: BarcodeScanning.Native.Maui는 실시간 카메라 프레임만 허용합니다. 사용자가 갤러리에서 이미지를 업로드해야 하거나 서버 측 엔드포인트에서 PDF에서 바코드를 추출해야 하는 경우, 해당 라이브러리는 제공할 수 있는 코드 경로가 없습니다. 파일이나 PDF 바코드 시나리오에 따라 필요한 도구가 다릅니다.
iOS UPC-A 데이터 오류 발생: Apple의 Vision 프레임워크가 UPC-A 바코드(EAN-13 인코딩)에 대해 13자리 숫자를 반환합니다. BarcodeScanning.Native.Maui는 이를 수정 없이 그대로 전달합니다. UPC-A 코드가 앞에 0이 붙어서 저장될 경우, 재고 기록, 판매 시점 조회 또는 공급망 통합에 있어 아무런 오류 없이 문제가 발생할 수 있습니다.IronBarcode수동 정규화 없이 정확한 12자리 UPC-A 값을 반환합니다.
PDF417 스캔 기능이 불안정했습니다. 도서관 자체 GitHub 이슈 문서에도 PDF417이 "매우 문제가 많으며 대부분의 스캔이 이루어지지 않는다"고 기록되어 있습니다. 배송 라벨, 운전면허증, 탑승권 등의 경우 이는 직접적인 걸림돌이 됩니다.
바코드 생성이 필요합니다: BarcodeScanning.Native.Maui는 바코드를 생성할 수 없습니다.IronBarcode Code128, QR, DataMatrix 및 기타 형식을 이미지 파일 또는 바이트 배열로 생성합니다.
서버 측 처리 도입: BarcodeScanning.Native.Maui는 카메라 UI 컨트롤이므로 서버 프로세스에서 실행될 수 없습니다. 모바일 스캔과 함께 서버 측 바코드 판독이 필요한 경우,IronBarcode동일한 패키지와 API로 양쪽 모두를 지원합니다.
근본적인 문제
BarcodeScanning.Native.Maui는 바코드 판독 기능을 실시간 카메라 이벤트 모델에 완벽하게 연동합니다. 요구사항 중 하나라도 해당 모델에서 벗어나는 순간, 라이브러리는 아무것도 제공하지 않습니다.
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
var barcode = e.BarcodeResults.FirstOrDefault();
if (barcode != null)
ResultLabel.Text = barcode.DisplayValue;
}
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
var barcode = e.BarcodeResults.FirstOrDefault();
if (barcode != null)
ResultLabel.Text = barcode.DisplayValue;
}
Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
Dim barcode = e.BarcodeResults.FirstOrDefault()
If barcode IsNot Nothing Then
ResultLabel.Text = barcode.DisplayValue
End If
End Sub
IronBarcode 카메라 캡처, 파일, PDF, 바이트 배열 등 모든 종류의 데이터 입력을 허용하며 모든 플랫폼에서 실행됩니다.
using IronBarCode;
private async void ScanBarcodeButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
ResultLabel.Text = results.FirstOrDefault()?.Value ?? "No barcode found";
}
using IronBarCode;
private async void ScanBarcodeButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
ResultLabel.Text = results.FirstOrDefault()?.Value ?? "No barcode found";
}
Imports IronBarCode
Private Async Sub ScanBarcodeButton_Clicked(sender As Object, e As EventArgs)
Dim photo = Await MediaPicker.CapturePhotoAsync()
If photo Is Nothing Then Return
Using stream = Await photo.OpenReadAsync()
Using ms As New MemoryStream()
Await stream.CopyToAsync(ms)
Dim results = BarcodeReader.Read(ms.ToArray())
ResultLabel.Text = If(results.FirstOrDefault()?.Value, "No barcode found")
End Using
End Using
End Sub
IronBarcode와 BarcodeScanning.MAUI의 기능 비교
| 기능 | BarcodeScanning.MAUI | IronBarcode |
|---|---|---|
| 실시간 카메라 프레임 읽기 | 예 — CameraView 제어 | 아니요 (미디어피커를 사용하여 캡처한 다음 읽으세요) |
| 앱 내 카메라 뷰파인더 | 예 — 실시간 연속 | 아니요 — MediaPicker를 통해 시스템 카메라 UI를 사용합니다. |
| 이미지 파일에서 읽어옴 | 아니요 | 예 — BarcodeReader.Read(path) |
| 바이트 배열에서 읽기 | 아니요 | 예 — BarcodeReader.Read(bytes) |
| 스트림에서 읽어오기 | 아니요 | 예 — BarcodeReader.Read(stream) |
| PDF에서 읽기 | 아니요 | 예 — BarcodeReader.Read(pdf) |
| 바코드 생성 | 아니요 | 예 — BarcodeWriter + QRCodeWriter |
| Windows MAUI 지원 | 아니요 | 예 |
| iOS MAUI 지원 | 예 | 예 |
| 안드로이드 MAUI 지원 | 예 | 예 |
| macOS MAUI 지원 | 문서화되지 않음 | 예 |
| 서버 측 / ASP.NET | 아니요 | 예 |
| Docker / Azure / AWS Lambda | 아니요 | 예 |
| iOS UPC-A 정확도 | 13자리 숫자를 반환하는 버그가 있어 수동으로 정규화해야 합니다. | 정확한 12자리 UPC-A 코드를 반환합니다. |
| PDF417 신뢰성 | "대부분의 스캔은 발생하지 않습니다." (GitHub 이슈) | 지원됨 |
| 다중 바코드 감지 | 예 (매 프레임당 여러 번 e.BarcodeResults으로) |
예 (ExpectMultipleBarcodes 옵션) |
| 읽기 속도 제어 | None | ReadingSpeed.Faster / Balanced / Detailed / ExtremeDetail |
| 라이선스 | MIT (오픈 소스, 무료) | 상업용 - Lite $749, Plus $1,499, Professional $2,999, 무제한 $5,999 |
| .NET Framework 지원 | 아니요 (MAUI 섬에만 해당) | 예 — .NET Framework 4.6.2 이상 |
빠른 시작: BarcodeScanning.MAUI에서IronBarcode로 마이그레이션
1단계: NuGet 패키지 교체
BarcodeScanning.Native.Maui를 제거하세요:
dotnet remove package BarcodeScanning.Native.Maui
dotnet remove package BarcodeScanning.Native.Maui
IronBarcode 설치하세요:
dotnet add package IronBarcode
dotnet add package IronBarcode
단계 2: 네임스페이스 업데이트
모든 파일에서 BarcodeScanning 네임스페이스를 제거하세요.
// Remove
using BarcodeScanning;
// Remove
using BarcodeScanning;
Imports BarcodeScanning
IronBarcode 네임스페이스를 추가하세요:
// Add
using IronBarCode;
// Add
using IronBarCode;
Imports IronBarCode
XAML 파일에서, scanner: XML 네임스페이스 선언을 제거하십시오:
xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui"
xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui"
단계 3: 라이선스 초기화
애플리케이션 시작 시 라이선스 초기화를 추가하십시오 — MauiProgram.cs 또는 App.xaml.cs 에서:
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
코드 마이그레이션 예제
카메라 스캐닝: CameraView에서 MediaPicker로
CameraView 컨트롤은 연속 프레임 감지를 통해 실시간 뷰 파인더를 제공했습니다.IronBarcode대체는 MAUI의 MediaPicker 을 사용하여 시스템 카메라를 열고 사진을 캡처한 후 결과 이미지를 처리합니다.
바코드 스캐닝.MAUI 접근 방식 — XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui">
<StackLayout>
<scanner:CameraView x:Name="CameraView"
OnDetectionFinished="OnBarcodeDetected"
CameraEnabled="True"
BarcodeFormats="All"
VerticalOptions="FillAndExpand" />
<Label x:Name="ResultLabel" Text="Waiting for scan..." />
</StackLayout>
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui">
<StackLayout>
<scanner:CameraView x:Name="CameraView"
OnDetectionFinished="OnBarcodeDetected"
CameraEnabled="True"
BarcodeFormats="All"
VerticalOptions="FillAndExpand" />
<Label x:Name="ResultLabel" Text="Waiting for scan..." />
</StackLayout>
</ContentPage>
바코드 스캐닝.MAUI 접근 방식 — 코드 비하인드:
using BarcodeScanning;
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
var barcode = e.BarcodeResults.FirstOrDefault();
if (barcode != null)
MainThread.BeginInvokeOnMainThread(() =>
ResultLabel.Text = barcode.DisplayValue);
}
using BarcodeScanning;
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
var barcode = e.BarcodeResults.FirstOrDefault();
if (barcode != null)
MainThread.BeginInvokeOnMainThread(() =>
ResultLabel.Text = barcode.DisplayValue);
}
Imports BarcodeScanning
Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
Dim barcode = e.BarcodeResults.FirstOrDefault()
If barcode IsNot Nothing Then
MainThread.BeginInvokeOnMainThread(Sub()
ResultLabel.Text = barcode.DisplayValue
End Sub)
End If
End Sub
IronBarcode 접근 방식 — XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui">
<StackLayout>
<Button Text="Scan Barcode" Clicked="ScanButton_Clicked" />
<Label x:Name="ResultLabel" Text="Tap to scan..." />
</StackLayout>
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui">
<StackLayout>
<Button Text="Scan Barcode" Clicked="ScanButton_Clicked" />
<Label x:Name="ResultLabel" Text="Tap to scan..." />
</StackLayout>
</ContentPage>
IronBarcode 접근 방식 — 코드 비하인드:
using IronBarCode;
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
var first = results.FirstOrDefault();
ResultLabel.Text = first?.Value ?? "No barcode found";
}
using IronBarCode;
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
var first = results.FirstOrDefault();
ResultLabel.Text = first?.Value ?? "No barcode found";
}
Imports IronBarCode
Imports System.IO
Imports System.Linq
Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
Dim photo = Await MediaPicker.CapturePhotoAsync()
If photo Is Nothing Then Return
Using stream = Await photo.OpenReadAsync()
Using ms As New MemoryStream()
Await stream.CopyToAsync(ms)
Dim results = BarcodeReader.Read(ms.ToArray())
Dim first = results.FirstOrDefault()
ResultLabel.Text = If(first?.Value, "No barcode found")
End Using
End Using
End Sub
이 코드는 플랫폼별 분기 없이 iOS, Android 및 Windows MAUI에서 실행됩니다. 사용자 경험은 앱 내 실시간 뷰파인더에서 플랫폼의 기본 카메라 화면으로 변경되며, 이는 대부분의 비즈니스 애플리케이션에 적합합니다. IronBarcode MAUI 사용 설명서에는 추가 구성 옵션이 설명되어 있습니다.
한 번의 스캔으로 여러 개의 바코드 처리
바코드 스캐닝.MAUI 접근 방식:
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
foreach (var barcode in e.BarcodeResults)
{
MainThread.BeginInvokeOnMainThread(() =>
Console.WriteLine($"Found: {barcode.DisplayValue}"));
}
}
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
foreach (var barcode in e.BarcodeResults)
{
MainThread.BeginInvokeOnMainThread(() =>
Console.WriteLine($"Found: {barcode.DisplayValue}"));
}
}
Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
For Each barcode In e.BarcodeResults
MainThread.BeginInvokeOnMainThread(Sub()
Console.WriteLine($"Found: {barcode.DisplayValue}")
End Sub)
Next
End Sub
IronBarcode 접근 방식:
using IronBarCode;
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true
};
var results = BarcodeReader.Read(ms.ToArray(), options);
foreach (var result in results)
Console.WriteLine($"{result.Format}: {result.Value}");
}
using IronBarCode;
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true
};
var results = BarcodeReader.Read(ms.ToArray(), options);
foreach (var result in results)
Console.WriteLine($"{result.Format}: {result.Value}");
}
Imports IronBarCode
Imports System.IO
Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
Dim photo = Await MediaPicker.CapturePhotoAsync()
If photo Is Nothing Then Return
Using stream = Await photo.OpenReadAsync()
Using ms As New MemoryStream()
Await stream.CopyToAsync(ms)
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True
}
Dim results = BarcodeReader.Read(ms.ToArray(), options)
For Each result In results
Console.WriteLine($"{result.Format}: {result.Value}")
Next
End Using
End Using
End Sub
ExpectMultipleBarcodes = true 은 독자가 첫 번째 바코드를 찾은 후 계속 스캔하도록 지시합니다. 이 옵션을 사용하지 않으면 첫 번째 일치 항목에서 호출이 반환되므로 단일 바코드 시나리오에서는 더 빠릅니다.
iOS UPC-A 수정: 정규화 임시 해결 방법 제거
코드베이스에 UPC-A 앞에 0을 붙이는 임시 해결책이 있다면, 해당 부분을 완전히 제거하십시오.IronBarcode수동 조작 없이 정확한 12자리 값을 반환합니다.
바코드 스캐닝.MAUI 접근 방식 - 임시 해결책 마련됨:
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
var barcode = e.BarcodeResults.FirstOrDefault();
if (barcode == null) return;
var value = barcode.DisplayValue;
// Workaround: Apple Vision returns 13 digits for UPC-A
if (barcode.BarcodeFormat == BarcodeFormats.Upca && value.Length == 13)
value = value.Substring(1);
ProcessBarcode(value, barcode.BarcodeFormat.ToString());
}
private void OnBarcodeDetected(object sender, OnDetectionFinishedEventArg e)
{
var barcode = e.BarcodeResults.FirstOrDefault();
if (barcode == null) return;
var value = barcode.DisplayValue;
// Workaround: Apple Vision returns 13 digits for UPC-A
if (barcode.BarcodeFormat == BarcodeFormats.Upca && value.Length == 13)
value = value.Substring(1);
ProcessBarcode(value, barcode.BarcodeFormat.ToString());
}
Private Sub OnBarcodeDetected(sender As Object, e As OnDetectionFinishedEventArg)
Dim barcode = e.BarcodeResults.FirstOrDefault()
If barcode Is Nothing Then Return
Dim value = barcode.DisplayValue
' Workaround: Apple Vision returns 13 digits for UPC-A
If barcode.BarcodeFormat = BarcodeFormats.Upca AndAlso value.Length = 13 Then
value = value.Substring(1)
End If
ProcessBarcode(value, barcode.BarcodeFormat.ToString())
End Sub
IronBarcode 방식 — 별도의 해결책이 필요 없습니다:
using IronBarCode;
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
var first = results.FirstOrDefault();
if (first == null) return;
// result.Value is the correct 12-digit UPC-A — no normalization needed
ProcessBarcode(first.Value, first.Format.ToString());
}
using IronBarCode;
private async void ScanButton_Clicked(object sender, EventArgs e)
{
var photo = await MediaPicker.CapturePhotoAsync();
if (photo == null) return;
using var stream = await photo.OpenReadAsync();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
var first = results.FirstOrDefault();
if (first == null) return;
// result.Value is the correct 12-digit UPC-A — no normalization needed
ProcessBarcode(first.Value, first.Format.ToString());
}
Imports IronBarCode
Imports System.IO
Imports System.Linq
Imports System.Threading.Tasks
Private Async Sub ScanButton_Clicked(sender As Object, e As EventArgs)
Dim photo = Await MediaPicker.CapturePhotoAsync()
If photo Is Nothing Then Return
Using stream = Await photo.OpenReadAsync()
Using ms As New MemoryStream()
Await stream.CopyToAsync(ms)
Dim results = BarcodeReader.Read(ms.ToArray())
Dim first = results.FirstOrDefault()
If first Is Nothing Then Return
' result.Value is the correct 12-digit UPC-A — no normalization needed
ProcessBarcode(first.Value, first.Format.ToString())
End Using
End Using
End Sub
BarcodeFormats.Upca 과(와) Substring(1) 이(가) 쌍으로 일치하는 항목을 삭제하십시오 — 마이그레이션 후 해당 코드는 사용되지 않습니다.
파일 및 PDF 지원 추가
BarcodeScanning.Native.Maui에는 파일 또는 PDF 입력에 해당하는 기능이 없습니다. 이것이 마이그레이션 시점에 충족해야 하는 새로운 요구 사항이라면:
바코드 스캐닝.MAUI 접근 방식:
// 아니요 equivalent exists — BarcodeScanning.Native.Maui cannot read from files or PDFs
// 아니요 equivalent exists — BarcodeScanning.Native.Maui cannot read from files or PDFs
' 아니요 equivalent exists — BarcodeScanning.Native.Maui cannot read from files or PDFs
IronBarcode 접근 방식:
using IronBarCode;
// Read from a file the user picked with FilePicker
private async void ReadFileButton_Clicked(object sender, EventArgs e)
{
var file = await FilePicker.PickAsync(new PickOptions
{
PickerTitle = "Select image or PDF"
});
if (file == null) return;
var results = BarcodeReader.Read(file.FullPath);
foreach (var result in results)
ResultLabel.Text += $"\n{result.Format}: {result.Value}";
}
// Read barcodes from a PDF directly — no intermediate image step
private void ReadPdfBarcodes()
{
var results = BarcodeReader.Read("shipment-manifest.pdf");
foreach (var result in results)
Console.WriteLine($"{result.Format}: {result.Value}");
}
using IronBarCode;
// Read from a file the user picked with FilePicker
private async void ReadFileButton_Clicked(object sender, EventArgs e)
{
var file = await FilePicker.PickAsync(new PickOptions
{
PickerTitle = "Select image or PDF"
});
if (file == null) return;
var results = BarcodeReader.Read(file.FullPath);
foreach (var result in results)
ResultLabel.Text += $"\n{result.Format}: {result.Value}";
}
// Read barcodes from a PDF directly — no intermediate image step
private void ReadPdfBarcodes()
{
var results = BarcodeReader.Read("shipment-manifest.pdf");
foreach (var result in results)
Console.WriteLine($"{result.Format}: {result.Value}");
}
Imports IronBarCode
' Read from a file the user picked with FilePicker
Private Async Sub ReadFileButton_Clicked(sender As Object, e As EventArgs)
Dim file = Await FilePicker.PickAsync(New PickOptions With {
.PickerTitle = "Select image or PDF"
})
If file Is Nothing Then Return
Dim results = BarcodeReader.Read(file.FullPath)
For Each result In results
ResultLabel.Text &= vbCrLf & $"{result.Format}: {result.Value}"
Next
End Sub
' Read barcodes from a PDF directly — no intermediate image step
Private Sub ReadPdfBarcodes()
Dim results = BarcodeReader.Read("shipment-manifest.pdf")
For Each result In results
Console.WriteLine($"{result.Format}: {result.Value}")
Next
End Sub
IronBarcode PDF 읽기 설명서에는 여러 페이지로 구성된 PDF 지원 및 페이지 범위 선택에 대한 내용이 포함되어 있습니다.
서버 측 바코드 처리
백엔드 ASP.NET API도 바코드 처리가 필요한 경우, 동일한 BarcodeReader.Read() 호출이 수정 없이 실행됩니다. BarcodeScanning.Native.Maui에는 서버 측에 해당하는 기능이 없습니다.
바코드 스캐닝.MAUI 접근 방식:
// 아니요 equivalent exists — BarcodeScanning.Native.Maui is a camera UI control
// and cannot run in a server process
// 아니요 equivalent exists — BarcodeScanning.Native.Maui is a camera UI control
// and cannot run in a server process
' 아니요 equivalent exists — BarcodeScanning.Native.Maui is a camera UI control
' and cannot run in a server process
IronBarcode 접근 방식:
using IronBarCode;
// ASP.NET endpoint — reads barcodes from an uploaded file
[HttpPost("scan")]
public async Task<IActionResult> ScanBarcode(IFormFile file)
{
using var ms = new MemoryStream();
await file.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
var values = results.Select(r => new { r.Value, Format = r.Format.ToString() });
return Ok(values);
}
using IronBarCode;
// ASP.NET endpoint — reads barcodes from an uploaded file
[HttpPost("scan")]
public async Task<IActionResult> ScanBarcode(IFormFile file)
{
using var ms = new MemoryStream();
await file.CopyToAsync(ms);
var results = BarcodeReader.Read(ms.ToArray());
var values = results.Select(r => new { r.Value, Format = r.Format.ToString() });
return Ok(values);
}
Imports IronBarCode
Imports Microsoft.AspNetCore.Mvc
Imports System.IO
Imports System.Threading.Tasks
' ASP.NET endpoint — reads barcodes from an uploaded file
<HttpPost("scan")>
Public Async Function ScanBarcode(file As IFormFile) As Task(Of IActionResult)
Using ms As New MemoryStream()
Await file.CopyToAsync(ms)
Dim results = BarcodeReader.Read(ms.ToArray())
Dim values = results.Select(Function(r) New With {Key .Value = r.Value, Key .Format = r.Format.ToString()})
Return Ok(values)
End Using
End Function
모바일과 서버에서 동일한 패키지, 동일한 API, 동일한 동작을 제공합니다.
바코드 생성
BarcodeScanning.Native.Maui에는 생성 API가 없습니다.IronBarcode다양한 형식을 생성합니다.
바코드 스캐닝.MAUI 접근 방식:
// 아니요 equivalent exists — BarcodeScanning.Native.Maui cannot generate barcodes
// 아니요 equivalent exists — BarcodeScanning.Native.Maui cannot generate barcodes
' 아니요 equivalent exists — BarcodeScanning.Native.Maui cannot generate barcodes
IronBarcode 접근 방식:
using IronBarCode;
// QR code
QRCodeWriter.CreateQrCode("https://example.com/product/12345", 500)
.SaveAsPng("qr.png");
// Code128 barcode sized to specific dimensions
BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
.ResizeTo(400, 100)
.SaveAsPng("label.png");
// Get bytes for returning from an API or storing in a database
byte[] barcodeBytes = BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
.ToPngBinaryData();
using IronBarCode;
// QR code
QRCodeWriter.CreateQrCode("https://example.com/product/12345", 500)
.SaveAsPng("qr.png");
// Code128 barcode sized to specific dimensions
BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
.ResizeTo(400, 100)
.SaveAsPng("label.png");
// Get bytes for returning from an API or storing in a database
byte[] barcodeBytes = BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128)
.ToPngBinaryData();
Imports IronBarCode
' QR code
QRCodeWriter.CreateQrCode("https://example.com/product/12345", 500) _
.SaveAsPng("qr.png")
' Code128 barcode sized to specific dimensions
BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128) _
.ResizeTo(400, 100) _
.SaveAsPng("label.png")
' Get bytes for returning from an API or storing in a database
Dim barcodeBytes As Byte() = BarcodeWriter.CreateBarcode("ITEM-98765", BarcodeEncoding.Code128) _
.ToPngBinaryData()
IronBarcode 생성 문서에는 지원되는 모든 형식과 스타일 옵션이 설명되어 있습니다.
BarcodeScanning.MAUI API와IronBarcode매핑 참조
| BarcodeScanning.Native.Maui | IronBarcode |
|---|---|
CameraView XAML 컨트롤 |
제거 — Button + MediaPicker.CapturePhotoAsync() 사용 |
OnDetectionFinished 이벤트 |
BarcodeReader.Read(imageBytes) 반환 값 |
OnDetectionFinishedEventArg e |
BarcodeReader.Read() 로부터의 IEnumerable 결과 |
e.BarcodeResults |
BarcodeReader.Read() 의 반환 값 |
e.BarcodeResults.FirstOrDefault() |
results.FirstOrDefault() |
barcode.DisplayValue |
result.Value |
barcode.BarcodeFormat |
result.Format |
BarcodeFormats="All" |
자동 감지됨 - 별도의 설정이 필요 없습니다 |
CameraEnabled="True" |
await MediaPicker.CapturePhotoAsync() |
| iOS 및 Android 전용 | iOS, 안드로이드, 윈도우, macOS MAUI |
| 파일 입력 없음 | BarcodeReader.Read(filePath) |
| PDF 입력 없음 | BarcodeReader.Read("document.pdf") |
| 어떤 세대도 | BarcodeWriter.CreateBarcode() / QRCodeWriter.CreateQrCode() |
| iOS UPC-A는 13자리 숫자를 반환합니다. | 정확한 12자리 숫자를 반환합니다. 정규화는 필요하지 않습니다. |
| PDF417 신뢰할 수 없음 | 지원됨 |
일반적인 마이그레이션 문제와 해결책
문제 1: 라이브 뷰파인더 경험 상실
BarcodeScanning.MAUI: CameraView 컨트롤은 실시간 카메라 미리 보기를 직접 MAUI 페이지에 내장했습니다. 사용자는 카메라 영상을 보고 바코드를 조준할 수 있으며, 버튼을 누르지 않아도 자동으로 바코드가 감지됩니다.
솔루션: 대신 MediaPicker.CapturePhotoAsync() 이 플랫폼 카메라 화면을 나타냅니다. 대부분의 업무 흐름에서는 이것이 허용됩니다. 연속적인 실시간 미리 보기가 필요한 소비자 앱의 경우, 카메라 프레임을 BarcodeReader.Read() 으로 직접 전달할 수 있습니다.
using IronBarCode;
// Continuous scanning: pass camera frame bytes to BarcodeReader.Read()
// (frame capture depends on your MAUI camera frame source)
private void ProcessCameraFrame(byte[] frameBytes)
{
var results = BarcodeReader.Read(frameBytes);
if (results.Any())
{
var first = results.First();
MainThread.BeginInvokeOnMainThread(() =>
ResultLabel.Text = first.Value);
}
}
using IronBarCode;
// Continuous scanning: pass camera frame bytes to BarcodeReader.Read()
// (frame capture depends on your MAUI camera frame source)
private void ProcessCameraFrame(byte[] frameBytes)
{
var results = BarcodeReader.Read(frameBytes);
if (results.Any())
{
var first = results.First();
MainThread.BeginInvokeOnMainThread(() =>
ResultLabel.Text = first.Value);
}
}
Imports IronBarCode
' Continuous scanning: pass camera frame bytes to BarcodeReader.Read()
' (frame capture depends on your MAUI camera frame source)
Private Sub ProcessCameraFrame(frameBytes As Byte())
Dim results = BarcodeReader.Read(frameBytes)
If results.Any() Then
Dim first = results.First()
MainThread.BeginInvokeOnMainThread(Sub()
ResultLabel.Text = first.Value
End Sub)
End If
End Sub
이를 위해서는 카메라 프레임 소스를IronBarcode와 별도로 연결해야 합니다. 이 방법을 선택하기 전에 실시간 미리보기가 정말 필요한지, 아니면 시스템 카메라 UI로 충분한지 평가해 보세요.
문제 2: e.BarcodeResults 속성 이름 및 열거형 변경
BarcodeScanning.MAUI: barcode.DisplayValue 이 디코딩된 문자열을 반환합니다; barcode.BarcodeFormat 은 BarcodeScanning 라이브러리 열거형 값을 반환합니다.
솔루션: DisplayValue 을(를) result.Value 로 대체하고 barcode.BarcodeFormat 을(를) result.Format 로 대체하십시오. 반복 패턴은 동일합니다.
// Before
foreach (var barcode in e.BarcodeResults)
Console.WriteLine(barcode.DisplayValue);
// After
var results = BarcodeReader.Read(imageBytes);
foreach (var result in results)
Console.WriteLine(result.Value);
// Before
foreach (var barcode in e.BarcodeResults)
Console.WriteLine(barcode.DisplayValue);
// After
var results = BarcodeReader.Read(imageBytes);
foreach (var result in results)
Console.WriteLine(result.Value);
' Before
For Each barcode In e.BarcodeResults
Console.WriteLine(barcode.DisplayValue)
Next
' After
Dim results = BarcodeReader.Read(imageBytes)
For Each result In results
Console.WriteLine(result.Value)
Next
문제 3: UI 업데이트를 위한 스레드 마샬링
BarcodeScanning.MAUI: OnDetectionFinished 은 백그라운드 스레드에서 실행되므로 모든 UI 업데이트가 MainThread.BeginInvokeOnMainThread() 을(를) 필요로 합니다.
솔루션: MediaPicker + async 패턴을 사용하여 await 이후의 지속은 호출 컨텍스트에서 반환됩니다 — 일반적으로 메인 스레드. 결과 표시 주위의 MainThread.BeginInvokeOnMainThread() 래퍼는 일반적으로 제거할 수 있어 핸들러 코드를 간소화합니다.
4번째 문제: MAUI 카메라 권한
BarcodeScanning.MAUI: 패키지는 설정의 일부로써 AndroidManifest.xml 및 Info.plist 에 카메라 권한을 자동으로 추가합니다.
솔루션: IronBarcode가 MediaPicker 을(를) 사용함에 따라, 표준 MAUI 카메라 권한은 수동으로 필요합니다. 이들은 MediaPicker.CapturePhotoAsync() 에 필요한 MAUI 앱의 동일한 권한이며 일반적으로 이미 설정되어 있습니다. 장치에서 테스트하기 전에 android.permission.CAMERA 이(가) AndroidManifest.xml 에 선언되어 있고 NSCameraUsageDescription 이(가) Info.plist 에 설정되어 있는지 확인하십시오.
바코드스캐닝.MAUI 마이그레이션 체크리스트
이동 전 작업
변경하기 전에 다음 검색을 실행하여 BarcodeScanning.Native.Maui 사용 내역을 모두 찾으세요.
grep -rn "using BarcodeScanning" --include="*.cs" .
grep -rn "using BarcodeScanning" --include="*.xaml" .
grep -rn "CameraView" --include="*.cs" .
grep -rn "CameraView" --include="*.xaml" .
grep -rn "OnDetectionFinished" --include="*.cs" .
grep -rn "OnDetectionFinishedEventArg" --include="*.cs" .
grep -rn "e\.BarcodeResults" --include="*.cs" .
grep -rn "DisplayValue" --include="*.cs" .
grep -rn "BarcodeFormats\.Upca" --include="*.cs" .
grep -rn "scanner:" --include="*.xaml" .
grep -rn "using BarcodeScanning" --include="*.cs" .
grep -rn "using BarcodeScanning" --include="*.xaml" .
grep -rn "CameraView" --include="*.cs" .
grep -rn "CameraView" --include="*.xaml" .
grep -rn "OnDetectionFinished" --include="*.cs" .
grep -rn "OnDetectionFinishedEventArg" --include="*.cs" .
grep -rn "e\.BarcodeResults" --include="*.cs" .
grep -rn "DisplayValue" --include="*.cs" .
grep -rn "BarcodeFormats\.Upca" --include="*.cs" .
grep -rn "scanner:" --include="*.xaml" .
각 공격 기록을 문서화하십시오. XAML 사용(은 XAML 변경이 필요함)을 포함하는 파일과 코드 비하인드 변경만 포함하는 파일을 구분하십시오. 마이그레이션 후 삭제해야 하는 UPC-A 정규화 관련 임시 해결책을 모두 확인하십시오.
코드 업데이트 작업
BarcodeScanning.Native.MauiNuGet 패키지를 제거하십시오IronBarcodeNuGet 패키지를 설치하십시오MauiProgram.cs또는App.xaml.cs에IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";을 추가하십시오- 모든
.cs파일에서using BarcodeScanning;을(를)using IronBarCode;로 대체하십시오 - 모든 XAML 파일에서
xmlns:scanner="..."네임스페이스 선언을 제거하십시오 - XAML에서
scanner:CameraView컨트롤을MediaPicker.CapturePhotoAsync()을 발동하는Button으로 교체하십시오 - XAML에서
OnDetectionFinished="..."이벤트 연결을 제거하십시오 BarcodeReader.Read()을 사용하여OnDetectionFinished이벤트 핸들러를async버튼 클릭 핸들러로 교체하십시오- 전체에서
barcode.DisplayValue을(를)result.Value으로 대체하십시오 - 전체에서
barcode.BarcodeFormat을(를)result.Format로 대체하십시오 - 모든
BarcodeFormats.Upca+Substring(1)정규화 해결 방법을 삭제하십시오 - 다중 바코드 감지가 이전에
e.BarcodeResults이 여러 항목을 반환하는 것에 의존하던 곳에ExpectMultipleBarcodes = true을BarcodeReaderOptions에 추가하십시오 - 비동기 패턴으로 불필요해진 곳에서 결과 표시 코드의
MainThread.BeginInvokeOnMainThread()래퍼를 제거하십시오 AndroidManifest.xml및Info.plist카메라 권한이 존재하는지 확인하십시오
마이그레이션 후 테스트
- iOS 바코드 스캔 기능이 정상적으로 작동하고 UPC-A 값이 앞에 0이 없는 12자리 문자열로 반환되는지 확인합니다.
- 안드로이드 바코드 스캔이 애플리케이션에서 사용되는 모든 형식에 대해 올바른 값을 생성하는지 확인합니다.
- Windows가 빌드 대상인 경우 Windows MAUI 바코드 스캔 기능이 제대로 작동하는지 확인합니다.
- 실제 배송 라벨, 운전면허증 또는 탑승권 등을 사용하는 경우, PDF417 스캔 기능을 실제 문서와 비교하여 테스트하십시오.
ExpectMultipleBarcodes = true으로 다중 바코드 시나리오를 테스트하고 이미지의 모든 바코드가 반환되는지 확인하십시오- 모든 MAUI 대상에서 파일 선택기 스캔(
BarcodeReader.Read(filePath))이 작동하는지 확인하십시오 - 마이그레이션과 함께 추가된 새로운 기능이라면 PDF 바코드 읽기 기능을 확인하십시오.
- 백엔드 컴포넌트가 추가되었을 때 서버 측
BarcodeReader.Read()이 올바른 결과를 생성하는지 확인하십시오 - 기존 자동화 테스트를 실행하고 바코드 값 출력값을 마이그레이션 전 기준선과 비교합니다.
IronBarcode로 마이그레이션할 때의 주요 이점
완벽한 Windows MAUI 지원:IronBarcode동일한 코드와 패키지를 사용하여 iOS, Android, Windows 및 macOS의 네 가지 MAUI 대상 모두에서 실행됩니다. Windows에는 플랫폼 특정 바코드 구현이 필요하지 않으며, 애플리케이션 코드에서 #if WINDOWS 블록이 필요하지 않습니다.
어떤 입력 소스든: BarcodeReader.Read() 은 파일 경로, 바이트 배열, 스트림 및 PDF 문서를 허용합니다. 카메라 캡처, 파일 업로드, 갤러리 이미지, 서버 측 PDF 처리 등 모든 바코드 시나리오에서 동일한 결과 유형을 가진 동일한 정적 메서드를 사용합니다.
정확한 UPC-A 값:IronBarcode애플리케이션 내에 별도의 정규화 코드를 추가하지 않아도 iOS에서 정확한 12자리 UPC-A 값을 반환합니다. BarcodeScanning.Native.Maui의 동작으로 인해 이전 UPC-A 데이터에 선행 0이 추가되는 현상이 발생하지만, 이는 마이그레이션 후 읽은 값의 정확도에는 영향을 미치지 않습니다.
PDF417은 안정적으로 작동합니다. PDF417은 완벽하게 지원되며 안정적으로 읽을 수 있습니다. 배송 라벨, 운전면허증, 탑승권은 BarcodeScanning.Native.Maui의 GitHub 이슈에 기록된 "대부분의 스캔이 발생하지 않는" 제한 없이 스캔됩니다.
바코드 생성: BarcodeWriter.CreateBarcode() 와 QRCodeWriter.CreateQrCode() 은 Code128, QR, DataMatrix 등 형식을 PNG 파일이나 바이트 배열로 생성합니다. 생성과 읽기 기능은 추가적인 종속성 없이 동일한 패키지에서 사용할 수 있습니다.
서버 측 배포: 동일한 BarcodeReader.Read() 호출이 ASP.NET, Azure Functions, Docker 컨테이너 및 AWS Lambda에서 실행됩니다. 모바일과 서버 바코드 로직은 별도의 바코드 구현을 유지 관리할 필요 없이 동일한 API, 동일한 형식 지원 및 동일한 결과 유형을 공유할 수 있습니다.
자주 묻는 질문
BarcodeScanning.MAUI에서 IronBarcode로 마이그레이션해야 하는 이유는 무엇인가요?
일반적인 이유로는 라이선스 간소화(SDK + 런타임 키 복잡성 제거), 처리량 제한 제거, 네이티브 PDF 지원 확보, Docker/CI/CD 배포 개선, 프로덕션 코드의 API 상용구 감소 등이 있습니다.
BarcodeScanning.MAUI API 호출을 IronBarcode로 대체하려면 어떻게 해야 하나요?
인스턴스 생성 및 라이선스 상용구를 IronBarCode.License.LicenseKey = "key"로 대체합니다. 판독기 호출을 BarcodeReader.Read(경로)로, 쓰기 호출을 BarcodeWriter.CreateBarcode(데이터, 인코딩)로 바꿉니다. 정적 메서드는 인스턴스 관리가 필요하지 않습니다.
BarcodeScanning.MAUI에서 IronBarcode로 마이그레이션할 때 얼마나 많은 코드가 변경되나요?
대부분의 마이그레이션은 더 적은 코드 줄로 이루어집니다. 라이선스 상용구, 인스턴스 생성자, 명시적 형식 구성이 제거됩니다. 핵심 읽기/쓰기 작업이 더 간결한 결과 객체를 가진 더 짧은 IronBarcode에 매핑됩니다.
마이그레이션하는 동안 BarcodeScanning.MAUI와 IronBarcode를 모두 설치해야 하나요?
아니요. 대부분의 마이그레이션은 병렬 작업이 아닌 직접 교체 작업입니다. 한 번에 하나의 서비스 클래스를 마이그레이션하고, NuGet 참조를 교체하고, 인스턴스화 및 API 호출 패턴을 업데이트한 후 다음 클래스로 이동합니다.
IronBarcode의 NuGet 패키지 이름은 무엇인가요?
패키지는 'IronBarCode'(대문자 B와 C 포함)입니다. '설치-패키지 IronBarCode' 또는 '닷넷 추가 패키지 IronBarCode'로 설치합니다. 코드의 사용 지시어는 'using IronBarCode;'입니다.
IronBarcode는 BarcodeScanning.MAUI와 비교하여 Docker 배포를 어떻게 간소화하나요?
IronBarcode는 외부 SDK 파일이나 마운트된 라이선스 구성이 없는 NuGet 패키지입니다. Docker에서 IRONBARCODE_LICENSE_KEY 환경 변수를 설정하면 패키지가 시작 시 라이선스 유효성 검사를 처리합니다.
BarcodeScanning.MAUI에서 마이그레이션한 후 IronBarcode가 모든 바코드 형식을 자동으로 감지하나요?
예. IronBarcode는 지원되는 모든 형식에서 기호를 자동으로 감지합니다. 명시적인 바코드 유형 열거가 필요하지 않습니다. 형식이 이미 알려져 있고 성능이 중요한 경우 BarcodeReaderOptions를 사용하여 검색 공간을 최적화하여 제한할 수 있습니다.
IronBarcode는 별도의 라이브러리 없이 PDF에서 바코드를 판독할 수 있나요?
예. BarcodeReader.Read("document.pdf")는 기본적으로 PDF 파일을 처리합니다. 결과에는 발견된 각 바코드에 대한 페이지 번호, 형식, 값 및 신뢰도가 포함됩니다. 외부 PDF 렌더링 단계가 필요하지 않습니다.
IronBarcode는 병렬 바코드 처리를 어떻게 처리하나요?
IronBarcode의 정적 메서드는 상태 저장소가 없고 스레드에 안전합니다. 스레드별 인스턴스 관리 없이 파일 목록에 직접 Parallel.ForEach를 사용할 수 있습니다. BarcodeReaderOptions.MaxParallelThreads는 내부 스레드 예산을 제어합니다.
BarcodeScanning.MAUI에서 IronBarcode로 마이그레이션하면 어떤 결과 속성이 변경되나요?
일반적인 이름 변경: 바코드 값은 값으로, 바코드 유형은 형식으로 바뀝니다. IronBarcode 결과에는 신뢰도 및 페이지 번호도 추가됩니다. 솔루션 전반의 검색 및 바꾸기 기능은 기존 결과 처리 코드에서 이름 변경을 처리합니다.
CI/CD 파이프라인에서 IronBarcode 라이선싱을 설정하려면 어떻게 해야 하나요?
IRONBARCODE_LICENSE_KEY를 파이프라인 시크릿으로 저장하고 애플리케이션 시작 코드에 IronBarCode.License.LicenseKey를 할당하세요. 하나의 비밀은 개발, 테스트, 스테이징 및 프로덕션을 포함한 모든 환경에 적용됩니다.
IronBarcode는 사용자 지정 스타일로 QR 코드 생성을 지원하나요?
예. QRCodeWriter.CreateQrCode()는 변경바코드색()을 통한 사용자 지정 색상, 추가브랜드 로고()를 통한 로고 임베딩, 구성 가능한 오류 수정 수준, PNG, JPG, PDF, 스트림을 포함한 여러 출력 형식을 지원합니다.

