구글 머신러닝 키트 Barcode Scanning에서 IronBarcode로 마이그레이션
이 가이드는 다음 두 가지 상황 중 하나에 처한 팀을 위한 것입니다. 첫째, Android 애플리케이션을 .NET MAUI 또는 .NET 9로 포팅하면서 ML Kit의 바코드 스캐너를 관리형 대안으로 교체해야 하는 경우, 둘째, 크로스 플랫폼 바코드 관련 논의에서 Google ML Kit를 추천받았지만 NuGet 패키지를 추가하려고 했을 때 해당 패키지가 존재하지 않는다는 것을 발견한 경우입니다.
Google ML Kit 바코드 스캐닝은 안드로이드 및 iOS용 네이티브 라이브러리입니다. 모든 전송은 Kotlin/Java용 Maven 종속성(com.google.mlkit:barcode-scanning:17.3.0 번들 또는 com.google.android.gms:play-services-mlkit-barcode-scanning:18.3.1 번들 해제)으로, Swift용으로는 CocoaPod(GoogleMLKit/BarcodeScanning)으로 제공됩니다. ML Kit은 2020년 6월부터 독립형 제품으로 Firebase가 필요하지 않게 되었지만, 공식적인 .NET SDK, dotnet add package google-mlkit-barcode 또는 Google의 1차 C# API가 없습니다. 커뮤니티에서 유지 관리하는 Xamarin/MAUI 바인딩은 수년 동안 존재해왔지만 ML Kit가 기본 SDK를 업데이트할 때마다 버그가 발생합니다.
IronBarcode 는 NuGet 에서 설치할 수 있는 네이티브 .NET 라이브러리로, 표준 .NET 패턴과 통합되며 Windows, Linux, macOS, Docker, Azure 및 AWS에서 실행됩니다. 이 가이드는 Kotlin 또는 Java로 작성한 패턴을 동등한 C# 코드로 변환하는 방법을 보여줍니다.
포팅 컨텍스트
ML Kit에서IronBarcode로 포팅할 때 구문적인 변화뿐만 아니라 구조적인 변화도 몇 가지 있습니다.
콜백이 반환값이 됩니다. ML Kit은 Android의 Task API를 addOnSuccessListener 및 addOnFailureListener을 사용하여 활용합니다. IronBarcode의 BarcodeReader.Read()는 컬렉션을 동기적으로 반환합니다. 직접 반복문을 사용합니다. 콜백 등록도 없고, 스레드 조정도 필요 없습니다.
스캐너 객체 없음. ML Kit은 BarcodeScannerOptions 객체를 생성하고, 스캐너 인스턴스를 얻기 위해 BarcodeScanning.getClient(options)을 호출한 다음 scanner.process(inputImage)을 호출해야 합니다. IronBarcode는 정적 메서드를 사용합니다 — BarcodeReader.Read()은 진입점입니다. 관리하거나 폐기해야 할 인스턴스가 없습니다.
InputImage 생성 없음. ML Kit의 InputImage는 Android 특정 소스에서 구성되어야 합니다: InputImage.fromFilePath(context, uri), InputImage.fromBitmap(bitmap, rotation), 또는 InputImage.fromMediaImage(image, rotation). IronBarcode는 파일 경로 문자열, Stream, byte[], 또는 System.Drawing.Bitmap을 허용합니다. Android 컨텍스트도 없고, URI도 없고, 화면 회전 메타데이터도 없습니다.
Google Play 서비스가 없습니다. 비번들 ML Kit 모델은 Google Play 서비스를 통해 실행됩니다. 번들형 변형은 모델을 APK 내부에 담아서 (약 2.4 MB 추가) Play Services 검사를 피하지만, 어느 변형도 .NET 대상에서는 사용할 수 없습니다.IronBarcode그러한 종속성이 없으며 .NET 지원하는 모든 플랫폼에서 동일하게 실행됩니다.
.NET 에서의 빠른 설정
프로젝트에 Xamarin/MAUI ML Kit 바인딩 패키지가 있는 경우 모두 제거한 다음IronBarcode설치하세요.
라이선스 키는 애플리케이션 시작 시에 추가합니다 — 앱 유형에 따라 Program.cs, MauiProgram.cs, 또는 Startup.cs에서:
// NuGet: dotnet add package BarCode
using IronBarCode;
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"라이선스는 첫 번째 BarcodeReader.Read() 또는 BarcodeWriter.CreateBarcode() 호출 전에 언제든지 설정할 수 있습니다. 무료 체험이 가능합니다. 체험 모드에서는 생성된 바코드에 워터마크가 표시되지만, 읽기에는 제한이 없습니다.
바코드 읽기: Kotlin에서 C#으로
기본 단일 바코드 읽기
다음은 파일 URI에서 단일 QR 코드를 스캔하는 Kotlin으로 작성된 일반적인 ML Kit 읽기 예제입니다.
// Android Kotlin — ML Kit
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
.build()
val scanner = BarcodeScanning.getClient(options)
val inputImage = InputImage.fromFilePath(context, imageUri)
scanner.process(inputImage)
.addOnSuccessListener { barcodes ->
val barcode = barcodes.firstOrNull()
if (barcode != null) {
Log.d("MLKit", "Value: ${barcode.rawValue}")
Log.d("MLKit", "Format: ${barcode.format}")
}
}
.addOnFailureListener { e ->
Log.e("MLKit", "Scan failed: ${e.message}")
}
IronBarcode 사용한 C# 코드에서의 동일 기능:
using IronBarCode;
try
{
var results = BarcodeReader.Read("captured-image.jpg");
var barcode = results.FirstOrDefault();
if (barcode != null)
{
Console.WriteLine($"Value: {barcode.Value}");
Console.WriteLine($"Format: {barcode.Format}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Scan failed: {ex.Message}");
}Imports IronBarCode
Try
Dim results = BarcodeReader.Read("captured-image.jpg")
Dim barcode = results.FirstOrDefault()
If barcode IsNot Nothing Then
Console.WriteLine($"Value: {barcode.Value}")
Console.WriteLine($"Format: {barcode.Format}")
End If
Catch ex As Exception
Console.WriteLine($"Scan failed: {ex.Message}")
End Try결과는 반환 값으로 즉시 제공됩니다. barcode.Value는 barcode.rawValue에 대응합니다. barcode.Format는 barcode.format에 대응합니다. 오류 처리는 별도의 실패 리스너 대신 표준 try/catch 구문을 사용합니다.
멀티 바코드 판독
ML Kit은 단일 InputImage을 스캔하고 목록을 반환합니다. 한 이미지에서 여러 바코드가 있는 경우, 성공 리스너의 목록을 반복합니다:
// Android Kotlin — ML Kit, multiple barcodes
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_ALL_FORMATS)
.build()
val scanner = BarcodeScanning.getClient(options)
val inputImage = InputImage.fromFilePath(context, imageUri)
scanner.process(inputImage)
.addOnSuccessListener { barcodes ->
for (barcode in barcodes) {
val rawValue = barcode.rawValue
val format = barcode.format
processBarcode(rawValue, format)
}
}
.addOnFailureListener { e -> Log.e("MLKit", e.message ?: "Unknown error") }
IronBarcode를 사용하면 ExpectMultipleBarcodes = true를 BarcodeReaderOptions에 설정하고 결과 컬렉션을 반복합니다:
using IronBarCode;
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true
};
var results = BarcodeReader.Read("warehouse-shelf.jpg", options);
foreach (var barcode in results)
{
Console.WriteLine($"Format: {barcode.Format}, Value: {barcode.Value}");
ProcessBarcode(barcode.Value, barcode.Format);
}Imports IronBarCode
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True
}
Dim results = BarcodeReader.Read("warehouse-shelf.jpg", options)
For Each barcode In results
Console.WriteLine($"Format: {barcode.Format}, Value: {barcode.Value}")
ProcessBarcode(barcode.Value, barcode.Format)
Next형식 지정: setBarcodeFormats를 BarcodeReaderOptions에 할당합니다.
ML Kit은 setBarcodeFormats()를 통해 검색할 형식을 지정해야 합니다. 해당 옵션을 생략하면 ML Kit는 모든 형식을 검색합니다.IronBarcode같은 방식으로 작동합니다. 형식 제약 조건을 생략하면 모든 것을 검색하지만, 예상 유형을 지정하면 성능이 향상됩니다.
| ML 키트 코틀린 | IronBarcode C# |
|---|---|
Barcode.FORMAT_QR_CODE | BarcodeEncoding.QRCode |
Barcode.FORMAT_CODE_128 | BarcodeEncoding.Code128 |
Barcode.FORMAT_CODE_39 | BarcodeEncoding.Code39 |
Barcode.FORMAT_CODE_93 | BarcodeEncoding.Code93 |
Barcode.FORMAT_EAN_13 | BarcodeEncoding.EAN13 |
Barcode.FORMAT_EAN_8 | BarcodeEncoding.EAN8 |
Barcode.FORMAT_UPC_A | BarcodeEncoding.UPCA |
Barcode.FORMAT_UPC_E | BarcodeEncoding.UPCE |
Barcode.FORMAT_PDF417 | BarcodeEncoding.PDF417 |
Barcode.FORMAT_DATA_MATRIX | BarcodeEncoding.DataMatrix |
Barcode.FORMAT_AZTEC | BarcodeEncoding.Aztec |
Barcode.FORMAT_ITF | BarcodeEncoding.ITF |
Barcode.FORMAT_CODABAR | BarcodeEncoding.Codabar |
Barcode.FORMAT_ALL_FORMATS | ExpectBarcodeTypes 생략 |
IronBarcode 에서 형식 플래그 사용하기:
using IronBarCode;
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true,
ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128 | BarcodeEncoding.EAN13
};
var results = BarcodeReader.Read("product-image.jpg", options);Imports IronBarCode
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True,
.ExpectBarcodeTypes = BarcodeEncoding.QRCode Or BarcodeEncoding.Code128 Or BarcodeEncoding.EAN13
}
Dim results = BarcodeReader.Read("product-image.jpg", options)비트 단위 OR 연산은 ML Kit의 가변 인자 형식 목록과 동일한 방식으로 작동합니다.
결과 접근: rawValue 및 형식
ML Kit의 결과 객체는 rawValue (String?의 일종)와 format (Int 상수)를 노출합니다. IronBarcode의 결과는 Value (string의 일종)와 Format (BarcodeEncoding 열거형 값)를 노출합니다.
// ML 키트 코틀린 — result fields
val rawValue: String? = barcode.rawValue
val format: Int = barcode.format
val boundingBox: Rect? = barcode.boundingBox
val displayValue: String? = barcode.displayValue
//IronBarcode C#— result fields
string value = barcode.Value;
BarcodeEncoding format = barcode.Format;
int page = barcode.PageNumber; // populated for PDF / multi-page input
barcode.Value는 IronBarcode에서 항상 널이 아닌 문자열입니다 — 읽기가 성공했다면 값이 존재합니다. barcode.Format는 BarcodeEncoding 열거형 멤버로 직접 비교할 수 있습니다: if (barcode.Format == BarcodeEncoding.QRCode).
.NET 의 차이점은 무엇일까요?
콜백 대신 동기식 API를 사용합니다. 이것이 가장 중요한 구조적 변화입니다. ML Kit의 scanner.process()는 Android의 관점에서 Task<List<Barcode>>를 반환합니다 — 리스너를 체인으로 연결합니다. IronBarcode의 BarcodeReader.Read()는 인라인으로 결과를 반환합니다. MAUI 앱에서 UI 스레드 외부에서 실행해야 하는 경우 Task.Run()에 감싸세요:
using IronBarCode;
// In a MAUI ViewModel or page code-behind
var results = await Task.Run(() => BarcodeReader.Read(imagePath));
foreach (var barcode in results)
{
// update UI on main thread
MainThread.BeginInvokeOnMainThread(() =>
{
ResultLabel.Text = barcode.Value;
});
}Imports IronBarCode
Imports System.Threading.Tasks
Imports Microsoft.Maui.Dispatching
' In a MAUI ViewModel or page code-behind
Dim results = Await Task.Run(Function() BarcodeReader.Read(imagePath))
For Each barcode In results
' update UI on main thread
MainThread.BeginInvokeOnMainThread(Sub()
ResultLabel.Text = barcode.Value
End Sub)
Next컨텍스트 매개변수 없음. ML Kit의 InputImage를 구성하는 모든 호출은 Android Context가 필요합니다.IronBarcode파일 경로 또는 스트림만 필요합니다. 바코드 로직에서 컨텍스트 스레딩을 제거하면 코드가 상당히 단순화됩니다.
Google Play 서비스 없음. 표준 ML Kit 모델은 Play 서비스를 통해 실행됩니다 — BarcodeScanning.getClient()는 런타임 시 Play 서비스 가용성을 검사하고 사용 불가능 시 예외를 발생시킵니다.IronBarcode런타임 서비스 검사를 수행하지 않습니다. 이미지를 읽거나 표준 예외를 발생시킵니다.
표준 예외 처리. ML Kit의 addOnFailureListener는 Java Exception 하위 클래스를 수신합니다. .NET에서는 실패가 표준 System.Exception 예외로 드러나며, 일반적인 try/catch로 포착할 수 있습니다.
PDF 문서 읽기
ML Kit는 PDF를 지원하지 않습니다. 안드로이드 버전에 따라 InputImage.fromFilePath()가 .pdf URI와 함께 실패하거나 이미지를 래스터화하여 첫 페이지만 읽습니다. 문서 전송 시나리오(송장 처리, 물류 명세서, 양식 스캔 등)가 포함된 경우IronBarcode PDF를 기본적으로 지원합니다.
using IronBarCode;
// Read all barcodes from all pages of a PDF
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true
};
var results = BarcodeReader.Read("invoice-batch.pdf", options);
foreach (var barcode in results)
{
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Format} — {barcode.Value}");
}Imports IronBarCode
' Read all barcodes from all pages of a PDF
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True
}
Dim results = BarcodeReader.Read("invoice-batch.pdf", options)
For Each barcode In results
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Format} — {barcode.Value}")
Next이미지 추출 단계도 없고, 타사 PDF 라이브러리도 필요 없으며, 개별 렌더링을 통한 페이지 반복 루프도 없습니다. PDF 경로를 전달하면 모든 바코드 값과 해당 페이지 번호를 반환합니다.
새로운 기능: 세대
ML Kit는 바코드를 생성하지 않고, 단지 바코드를 읽기만 합니다. 이식된 애플리케이션에서 라벨, 티켓 또는 QR 코드를 생성해야 하는 경우IronBarcode동일한 패키지로 해당 기능을 제공합니다.
배송 라벨용 코드 128:
using IronBarCode;
BarcodeWriter.CreateBarcode("SHIP-2024-98341", BarcodeEncoding.Code128)
.ResizeTo(400, 120)
.SaveAsPng("shipping-label.png");Imports IronBarCode
BarcodeWriter.CreateBarcode("SHIP-2024-98341", BarcodeEncoding.Code128) _
.ResizeTo(400, 120) _
.SaveAsPng("shipping-label.png")QR 코드 생성:
using IronBarCode;
QRCodeWriter.CreateQrCode("https://example.com/track/98341", 500)
.SaveAsPng("tracking-qr.png");Imports IronBarCode
QRCodeWriter.CreateQrCode("https://example.com/track/98341", 500) _
.SaveAsPng("tracking-qr.png")로고와 색상이 포함된 QR 코드:
using IronBarCode;
QRCodeWriter.CreateQrCode("https://example.com/product/4821", 500)
.AddBrandLogo("company-logo.png")
.ChangeBarCodeColor(System.Drawing.Color.DarkBlue)
.SaveAsPng("product-qr.png");Imports IronBarCode
QRCodeWriter.CreateQrCode("https://example.com/product/4821", 500) _
.AddBrandLogo("company-logo.png") _
.ChangeBarCodeColor(System.Drawing.Color.DarkBlue) _
.SaveAsPng("product-qr.png")HTTP 응답으로 바코드를 바이트 배열로 반환합니다.
using IronBarCode;
// In an ASP.NET Corecontroller action
byte[] barcodeBytes = BarcodeWriter.CreateBarcode("ORDER-7734", BarcodeEncoding.QRCode)
.ToPngBinaryData();
return File(barcodeBytes, "image/png");
이러한 패턴 중 어느 것도 ML Kit에 해당하는 것이 없습니다. 모바일 전용 스캐너가 아닌 완전한 .NET 바코드 라이브러리를 사용하기 때문에 이러한 새로운 기능을 사용할 수 있습니다.
서버 측 배치 처리
ML Kit는 호출당 하나의 이미지를 처리하며, Android/iOS 런타임이 필요하고, 서버 측 실행 개념이 없습니다.IronBarcode반복문을 통해 파일을 처리하고, ASP.NET Core에서 실행되며, 정상적으로 확장됩니다.
using IronBarCode;
// Process a folder of scanned document images
var imageFiles = Directory.GetFiles("/data/scans", "*.jpg");
var allResults = new List<(string File, string Value, BarcodeEncoding Format)>();
foreach (var file in imageFiles)
{
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Faster,
ExpectMultipleBarcodes = false
};
var results = BarcodeReader.Read(file, options);
foreach (var barcode in results)
{
allResults.Add((file, barcode.Value, barcode.Format));
}
}
// Write results to CSV, database, etc.
foreach (var (file, value, format) in allResults)
{
Console.WriteLine($"{file}: [{format}] {value}");
}Imports IronBarCode
Imports System.IO
' Process a folder of scanned document images
Dim imageFiles = Directory.GetFiles("/data/scans", "*.jpg")
Dim allResults = New List(Of (File As String, Value As String, Format As BarcodeEncoding))()
For Each file In imageFiles
Dim options = New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Faster,
.ExpectMultipleBarcodes = False
}
Dim results = BarcodeReader.Read(file, options)
For Each barcode In results
allResults.Add((file, barcode.Value, barcode.Format))
Next
Next
' Write results to CSV, database, etc.
For Each result In allResults
Console.WriteLine($"{result.File}: [{result.Format}] {result.Value}")
Next폴더 속 이미지를 읽고, 바코드를 추출하고, 결과를 취합하는 이러한 패턴은 ML Kit으로는 불가능합니다. 이는 표준IronBarcode워크플로입니다.
기능 비교
| 기능 | 구글 머신러닝 키트 | IronBarcode |
|---|---|---|
| .NET NuGet 패키지 | None | BarCode |
| C# / .NET API | None | 예 |
| 바코드 판독 | 예 (안드로이드/iOS) | 예 (모든 플랫폼) |
| 바코드 생성 | 아니요 | 예 |
| QR 코드 생성 | 아니요 | 예 |
| QR 로고 삽입 | 아니요 | 예 |
| PDF 입력 | 아니요 | 예 |
| 여러 페이지로 구성된 문서 지원 | 아니요 | 예 |
| 카메라/프레임 입력 | 예 | 이미지 파일을 통해 |
| 서버 측 배포 | 아니요 | 예 |
| ASP.NET Core | 아니요 | 예 |
| Azure Functions | 아니요 | 예 |
| Docker/리눅스 | 아니요 | 예 |
| Google Play 서비스가 필요합니다. | 비번들형 변형만 | 아니요 |
| Firebase 종속성 | 아니요 (2020년 6월 이후 독립형) | 아니요 |
| 동기식 .NET API | 아니요 | 예 |
| 의존성 주입 친화적 | 아니요 | 예 (정적 API) |
ExpectMultipleBarcodes 옵션 | 결과 목록을 통해 | BarcodeReaderOptions |
| 형식 사양 | setBarcodeFormats() | ExpectBarcodeTypes |
| 속도/정확도 상충 관계 | 고정형(모델 기반) | ReadingSpeed 열거형 |
| 가격 | 무료 (온디바이스, 모바일 전용) | From $999 (Lite) perpetual |
| 플랫폼 | 안드로이드, iOS | 윈도우, 리눅스, macOS, Docker, Azure, AWS |
마이그레이션 체크리스트
안드로이드 코드베이스를 포팅하거나 비공식 Xamarin ML Kit 바인딩을 교체하는 경우, 프로젝트에서 다음 패턴을 검색하고 위의 변환을 적용하세요.
com.google.mlkit:barcode-scanning을(를) Gradle 파일에서 제거하고BarCodeNuGet을 추가하십시오.BarcodeScannerOptions.Builder()→new BarcodeReaderOptions { }BarcodeScanning.getClient(options)→ 제거 (IronBarcode에 스캐너 인스턴스 없음)InputImage.fromFilePath(context, uri)→ 파일 경로 문자열 인자InputImage.fromBitmap(bitmap, rotation)→BarcodeReader.Read(stream)또는 바이트 배열 오버로드scanner.process(inputImage)→BarcodeReader.Read(path, options).addOnSuccessListener { barcodes -> }→Read()반환값 반복.addOnFailureListener { e -> }→Read()주변의 try/catchbarcode.rawValue→barcode.Valuebarcode.format→barcode.FormatBarcode.FORMAT_QR_CODE→BarcodeEncoding.QRCodeBarcode.FORMAT_CODE_128→BarcodeEncoding.Code128Barcode.FORMAT_ALL_FORMATS→ExpectBarcodeTypes생략using Google.MLKit.BarcodeScanning;(Xamarin 바인딩) →using IronBarCode;IronBarCode.License.LicenseKey는MauiProgram.cs,Program.cs또는Startup.cs에 설정해야 합니다.
콜백 기반 코드에서 동기식 코드로의 구조적 변화가 주요 작업입니다. 형식 상수와 결과 필드 이름은 직접적인 대응 관계입니다. PDF 및 생성 지원 기능은 완전히 추가되는 방식이므로 마이그레이션이 필요 없고 새 코드만 작성하면 됩니다.

커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다.