푸터 콘텐츠로 바로가기
동영상

C#으로 유니코드 및 국제 언어 바코드를 작성하는 방법 | IronPDF

ZXing.Net에서 IronBarcode로의 마이그레이션

이 가이드는 바코드를 읽고 생성하는 .NET 애플리케이션의 경우 ZXing .NET 에서IronBarcode로의 완전한 마이그레이션 과정을 다룹니다. ZXing.Net의 코어 패키지와 바인딩 패키지 제거, PdfiumViewer 작업 회피 제거 및 상태가 있는 BarcodeReader 인스턴스화를 IronBarcode의 정적 API로 대체합니다. 각 섹션에는 ZXing .NET 통합에서 가장 흔히 볼 수 있는 패턴을 기반으로 한 변경 전후 코드가 포함되어 있습니다.

ZXing .NET 에서 마이그레이션해야 하는 이유는 무엇일까요?

ZXing .NET 은 10년 넘게 무료 Apache 2.0 바코드 라이브러리로서 .NET 커뮤니티에 많은 도움을 제공해 왔습니다. 하지만 애플리케이션의 규모나 복잡성이 커짐에 따라 여러 아키텍처적 제약 조건이 운영 비용으로 이어집니다.

스레드 안전성 소유권: ZXing.Net의 BarcodeReader는 상태가 있는 객체입니다. 라이브러리 자체 문서에는 인스턴스를 스레드 간에 공유해서는 안 된다고 명시되어 있습니다. 실제로 이는 모든 동시 처리 경로, 즉 동시 요청을 처리하는 모든 컨트롤러 작업, 병렬 배치에 있는 모든 작업이 자체 리더를 할당, 구성 및 폐기해야 함을 의미합니다. 요청량이 증가함에 따라 이러한 할당 패턴은 상당한 메모리 부하를 발생시킵니다. ThreadLocal<BarcodeReader> 대안은 할당 빈도를 줄이지만 자체 폐기 복잡성을 도입합니다. 두 경우 모두 동시성 환경에서의 정확성은 호출자의 책임이며, 라이브러리가 보장하는 사항이 아닙니다.

포맷 지정 위험: ZXing.Net은 각 디코드 작업 전에 reader.Options.PossibleFormats이 채워져야 합니다. 해당 리스트에 없는 형식의 바코드는 null을 반환합니다 — 예외, 경고, 바코드가 있었지만 인식되지 않았다는 표시가 없습니다. 외부 파트너로부터 문서를 받는 애플리케이션의 경우, 이 조용한 누락 동작은 신뢰성 위험입니다: 잘못 배송된 주문, 놓친 환자 체크인 기록 또는 결코 기록되지 않는 감사 항목은 모두 이전 요구사항을 위해 구성된 형식 리스트에서 기인할 수 있으며, 업데이트되지 않았기 때문입니다.

PDF 처리상의 문제점: ZXing .NET 은 비트맵만 읽습니다. 원본 문서가 PDF 형식(송장, 선적 명세서, 규정 준수 인증서 등)인 경우, 호출자는 별도의 PDF 렌더링 라이브러리(가장 일반적인 것은 PdfiumViewer)를 통합하고, 페이지 열거 루프를 구현하고, DPI를 구성하고, 임시 파일을 관리하고, 성공 및 실패 경로 모두에서 정리 작업을 처리해야 합니다. 이는 ZXing .NET 이 읽을 수 없는 파일 형식(PDF)을 읽을 수 있는 파일 형식(비트맵)으로 변환하기 위해 통합당 30~50줄 정도의 인프라 코드로 구성됩니다. 해당 인프라는 자체적인 의존성, 배포 요구 사항 및 장애 유형을 가지고 있습니다.

플랫폼 바인딩 분산: ZXing.Net의 이미지 로딩 기능은 플랫폼별 바인딩 패키지로 분산되어 있습니다. Windows 바인딩에서는 System.Drawing.Bitmap을 사용합니다; 크로스 플랫폼 바인딩에서는 다른 제너릭 타입 매개변수와 다른 using 지시어로 SixLabors.ImageSharp을 사용합니다. Windows에서 시작하여 나중에 리눅스로 컨테이너화하는 프로젝트는 NuGet 참조와 이미지 로딩 코드를 모두 변경해야 합니다. 동일한 작업을 수행하는 두 개의 코드 경로는 버그 발생 가능성을 높이고 향후 스캐닝 레이어의 변경 작업에 마찰을 일으킵니다.

근본적인 문제

ZXing .NET 아키텍처를 가장 명확하게 보여주는 예는 단일 스레드 호출과 동시 호출 간의 차이입니다. ZXing .NET 에서 동시 처리를 하려면 병렬 작업마다 완전한 리더 객체를 생성해야 합니다.

// ZXing.Net: full reader instantiation and configuration on every parallel task
Parallel.ForEach(files, file =>
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    };

    using var bitmap = new Bitmap(file);
    var result = reader.Decode(bitmap);
    if (result != null)
        processed[file] = result.Text;
});
// ZXing.Net: full reader instantiation and configuration on every parallel task
Parallel.ForEach(files, file =>
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    };

    using var bitmap = new Bitmap(file);
    var result = reader.Decode(bitmap);
    if (result != null)
        processed[file] = result.Text;
});
Imports ZXing
Imports System.Drawing
Imports System.Threading.Tasks

Parallel.ForEach(files, Sub(file)
    Dim reader As New BarcodeReader()
    reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    }

    Using bitmap As New Bitmap(file)
        Dim result = reader.Decode(bitmap)
        If result IsNot Nothing Then
            processed(file) = result.Text
        End If
    End Using
End Sub)
$vbLabelText   $csharpLabel

IronBarcode 객체를 완전히 제거합니다. 정적 호출은 스레드 하나에서 실행되든 백 개의 스레드에서 실행되든 동일합니다.

// IronBarcode: static call, same code for single-threaded and concurrent use
Parallel.ForEach(files, file =>
{
    var result = BarcodeReader.Read(file).FirstOrDefault();
    if (result != null)
        processed[file] = result.Value;
});
// IronBarcode: static call, same code for single-threaded and concurrent use
Parallel.ForEach(files, file =>
{
    var result = BarcodeReader.Read(file).FirstOrDefault();
    if (result != null)
        processed[file] = result.Value;
});
Imports IronBarCode
Imports System.Threading.Tasks

Parallel.ForEach(files, Sub(file)
    Dim result = BarcodeReader.Read(file).FirstOrDefault()
    If result IsNot Nothing Then
        processed(file) = result.Value
    End If
End Sub)
$vbLabelText   $csharpLabel

IronBarcode와 ZXing .NET 의 기능 비교

기능 ZXing.Net IronBarcode
특허 Apache 2.0 (무료) 상업적
스레드 안전성 스레드 안전하지 않음 - 스레드마다 새 인스턴스가 필요합니다. 스레드 안전한 정적 API
형식 감지 수동 — PossibleFormats 목록 필요 자동 — 50개 이상의 형식
PDF 읽기 아니요 — PDF 뷰어 또는 유사한 프로그램이 필요합니다. 네이티브 — 단일 메서드 호출
플랫폼 지원 플랫폼별로 별도의 바인딩 패키지가 제공됩니다. 단일 패키지로 모든 플랫폼에서 사용 가능
이미지당 여러 개의 바코드 예 — DecodeMultiple 예 — 기본 동작
바코드 생성 Bitmap을 반환하며 수동 저장이 필요합니다 출력 기능이 내장된 Fluent API
QR 코드 로고 지원 아니요
QR 코드 색상 제어 아니요
손상된 바코드 복구 TryHarder 플래그 머신러닝 기반 이미지 보정
Docker 추가 종속성 libgdiplus이 필요할 수 있습니다 None
상업용 SLA 지원 아니요
NuGet 패키지 필요 2~3 (코어 + 바인딩 + 선택적 ImageSharp) 1

빠른 시작

1단계: ZXing .NET 패키지 제거

프로젝트에서 ZXing .NET 및 관련 패키지를 모두 제거하십시오.

dotnet remove package ZXing.Net
dotnet remove package ZXing.Net.Bindings.Windows.Compatibility
dotnet remove package ZXing.Net.Bindings.ImageSharp
dotnet remove package PdfiumViewer
dotnet remove package ZXing.Net
dotnet remove package ZXing.Net.Bindings.Windows.Compatibility
dotnet remove package ZXing.Net.Bindings.ImageSharp
dotnet remove package PdfiumViewer
SHELL

PdfiumViewer 네이티브 바이너리가 별도의 패키지로 설치된 경우:

dotnet remove package PdfiumViewer.Native.x64.v8-xfa
dotnet remove package PdfiumViewer.Native.x64.v8-xfa
SHELL

Dockerfile에 apt-get install -y libgdiplus가 포함되어 있으면 — 리눅스에서 Windows 바인딩을 통해 System.Drawing를 지원하기 위해 추가됨 — 마이그레이션 후 해당 줄을 제거할 수 있습니다.

2단계:IronBarcode설치

dotnet add package IronBarcode
dotnet add package IronBarcode
SHELL

추가적인 바인딩 패키지나 플랫폼별 종속성은 필요하지 않습니다. 동일한 NuGet 패키지가 Windows, Linux, macOS 및 Docker 컨테이너에서 실행됩니다. 배포 세부 정보는 IronBarcode Docker 및 Linux 설정 가이드에서 정확한 Dockerfile 패턴을 확인할 수 있습니다.

3단계: 네임스페이스 업데이트 및 라이선스 초기화

바코드 연산을 사용하는 모든 파일에서 ZXing 관련 네임스페이스를 모두 제거하십시오.

// Remove all of these:
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using ZXing.ImageSharp;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using PdfiumViewer;

// Add this single import:
using IronBarCode;
// Remove all of these:
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using ZXing.ImageSharp;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using PdfiumViewer;

// Add this single import:
using IronBarCode;
Imports IronBarCode
$vbLabelText   $csharpLabel

애플리케이션 시작 시, 바코드 관련 작업을 수행하기 전에 라이선스 초기화를 추가합니다.

// Program.cs or Startup.cs — initialise once at startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
// Program.cs or Startup.cs — initialise once at startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";
' Program.vb or Startup.vb — initialise once at startup
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

라이선스 키는 환경 변수, appsettings.json 또는 시크릿 관리자에서 로드할 수 있는 일반 문자열입니다. 찾아야 할 파일이 없고, 구성해야 할 경로도 없습니다.

코드 마이그레이션 예제

이미지에서 단일 바코드 읽기

이 예제는 가장 일반적인 ZXing .NET 사용 패턴(리더 인스턴스 생성, 형식 목록 구성, 비트맵 로드 및 디코딩)을 대체합니다.

ZXing .NET 접근 방식:

using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;

public string ReadSingleBarcode(string imagePath)
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    };

    using var bitmap = new Bitmap(imagePath);
    var result = reader.Decode(bitmap);

    return result?.Text ?? string.Empty;
}
using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;

public string ReadSingleBarcode(string imagePath)
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    };

    using var bitmap = new Bitmap(imagePath);
    var result = reader.Decode(bitmap);

    return result?.Text ?? string.Empty;
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Drawing

Public Function ReadSingleBarcode(imagePath As String) As String
    Dim reader = New BarcodeReader()
    reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.EAN_13
    }

    Using bitmap As New Bitmap(imagePath)
        Dim result = reader.Decode(bitmap)
        Return If(result?.Text, String.Empty)
    End Using
End Function
$vbLabelText   $csharpLabel

IronBarcode 접근 방식:

using IronBarCode;

public string ReadSingleBarcode(string imagePath)
{
    var result = BarcodeReader.Read(imagePath).FirstOrDefault();
    return result?.Value ?? string.Empty;
}
using IronBarCode;

public string ReadSingleBarcode(string imagePath)
{
    var result = BarcodeReader.Read(imagePath).FirstOrDefault();
    return result?.Value ?? string.Empty;
}
Imports IronBarCode

Public Function ReadSingleBarcode(imagePath As String) As String
    Dim result = BarcodeReader.Read(imagePath).FirstOrDefault()
    Return If(result?.Value, String.Empty)
End Function
$vbLabelText   $csharpLabel

포맷 목록, Bitmap 할당, 그리고 using 블록이 모두 제거되었습니다.IronBarcode파일 경로를 직접 입력받아 지원되는 모든 형식을 자동으로 감지합니다. 이전에 디코딩된 문자열을 반환하던 속성은 ZXing.Net에서는 result.Text이었습니다; IronBarcode에서는 result.Value입니다.

이미지에서 모든 바코드 읽기

이 예제는 ZXing.Net에서 조용한 누락을 방지하기 위해 철저한 포맷 목록이 필요한 DecodeMultiple를 대체합니다.

ZXing .NET 접근 방식:

using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;

public List<string> ReadAllBarcodes(string imagePath)
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.CODE_39,
        BarcodeFormat.EAN_13,
        BarcodeFormat.EAN_8,
        BarcodeFormat.UPC_A,
        BarcodeFormat.DATA_MATRIX,
        BarcodeFormat.PDF_417
    };
    reader.Options.TryHarder = true;

    using var bitmap = new Bitmap(imagePath);
    var results = reader.DecodeMultiple(bitmap);

    return results?.Select(r => r.Text).ToList() ?? new List<string>();
}
using ZXing;
using ZXing.Windows.Compatibility;
using System.Drawing;

public List<string> ReadAllBarcodes(string imagePath)
{
    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.CODE_39,
        BarcodeFormat.EAN_13,
        BarcodeFormat.EAN_8,
        BarcodeFormat.UPC_A,
        BarcodeFormat.DATA_MATRIX,
        BarcodeFormat.PDF_417
    };
    reader.Options.TryHarder = true;

    using var bitmap = new Bitmap(imagePath);
    var results = reader.DecodeMultiple(bitmap);

    return results?.Select(r => r.Text).ToList() ?? new List<string>();
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Drawing

Public Function ReadAllBarcodes(imagePath As String) As List(Of String)
    Dim reader = New BarcodeReader()
    reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.CODE_39,
        BarcodeFormat.EAN_13,
        BarcodeFormat.EAN_8,
        BarcodeFormat.UPC_A,
        BarcodeFormat.DATA_MATRIX,
        BarcodeFormat.PDF_417
    }
    reader.Options.TryHarder = True

    Using bitmap As New Bitmap(imagePath)
        Dim results = reader.DecodeMultiple(bitmap)
        Return If(results?.Select(Function(r) r.Text).ToList(), New List(Of String)())
    End Using
End Function
$vbLabelText   $csharpLabel

IronBarcode 접근 방식:

using IronBarCode;

public List<string> ReadAllBarcodes(string imagePath)
{
    return BarcodeReader.Read(imagePath)
        .Select(r => r.Value)
        .ToList();
}
using IronBarCode;

public List<string> ReadAllBarcodes(string imagePath)
{
    return BarcodeReader.Read(imagePath)
        .Select(r => r.Value)
        .ToList();
}
Imports IronBarCode

Public Function ReadAllBarcodes(imagePath As String) As List(Of String)
    Return BarcodeReader.Read(imagePath) _
        .Select(Function(r) r.Value) _
        .ToList()
End Function
$vbLabelText   $csharpLabel

BarcodeReader.Read는 항상 컬렉션을 반환하며 결과에서 null-guard가 제거됩니다. 정확도 대 속도 균형을 조정하려면 읽기 속도 옵션 가이드를 참조하십시오. 이 가이드는 포맷 범위를 좁히지 않고 ReadingSpeed 열거형을 다룹니다.

동시 배치 처리

이 예시는 스레드 안전성 차이를 가장 직접적으로 보여줍니다. ZXing .NET 은 병렬 작업마다 새로운 리더가 필요합니다.IronBarcode동시 실행 수준에 관계없이 동일한 정적 호출을 사용합니다.

ZXing .NET 접근 방식:

using ZXing;
using ZXing.Windows.Compatibility;
using System.Collections.Concurrent;
using System.Drawing;

public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
    var output = new ConcurrentDictionary<string, string>();

    Parallel.ForEach(filePaths, new ParallelOptions { MaxDegreeOfParallelism = 4 }, file =>
    {
        // ZXing.Net is not thread-safe — a new reader is required per parallel operation
        var reader = new BarcodeReader();
        reader.Options.PossibleFormats = new List<BarcodeFormat>
        {
            BarcodeFormat.QR_CODE,
            BarcodeFormat.CODE_128
        };

        using var bitmap = new Bitmap(file);
        var result = reader.Decode(bitmap);
        if (result != null)
            output[file] = result.Text;
    });

    return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
using ZXing;
using ZXing.Windows.Compatibility;
using System.Collections.Concurrent;
using System.Drawing;

public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
    var output = new ConcurrentDictionary<string, string>();

    Parallel.ForEach(filePaths, new ParallelOptions { MaxDegreeOfParallelism = 4 }, file =>
    {
        // ZXing.Net is not thread-safe — a new reader is required per parallel operation
        var reader = new BarcodeReader();
        reader.Options.PossibleFormats = new List<BarcodeFormat>
        {
            BarcodeFormat.QR_CODE,
            BarcodeFormat.CODE_128
        };

        using var bitmap = new Bitmap(file);
        var result = reader.Decode(bitmap);
        if (result != null)
            output[file] = result.Text;
    });

    return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports System.Collections.Concurrent
Imports System.Drawing

Public Function ProcessBatch(filePaths As IEnumerable(Of String)) As Dictionary(Of String, String)
    Dim output = New ConcurrentDictionary(Of String, String)()

    Parallel.ForEach(filePaths, New ParallelOptions With {.MaxDegreeOfParallelism = 4}, Sub(file)
        ' ZXing.Net is not thread-safe — a new reader is required per parallel operation
        Dim reader = New BarcodeReader()
        reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
            BarcodeFormat.QR_CODE,
            BarcodeFormat.CODE_128
        }

        Using bitmap As New Bitmap(file)
            Dim result = reader.Decode(bitmap)
            If result IsNot Nothing Then
                output(file) = result.Text
            End If
        End Using
    End Sub)

    Return output.ToDictionary(Function(kvp) kvp.Key, Function(kvp) kvp.Value)
End Function
$vbLabelText   $csharpLabel

IronBarcode 접근 방식:

using IronBarCode;
using System.Collections.Concurrent;

public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
    var output = new ConcurrentDictionary<string, string>();
    var options = new BarcodeReaderOptions { MaxParallelThreads = 4 };

    Parallel.ForEach(filePaths, file =>
    {
        var result = BarcodeReader.Read(file, options).FirstOrDefault();
        if (result != null)
            output[file] = result.Value;
    });

    return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
using IronBarCode;
using System.Collections.Concurrent;

public Dictionary<string, string> ProcessBatch(IEnumerable<string> filePaths)
{
    var output = new ConcurrentDictionary<string, string>();
    var options = new BarcodeReaderOptions { MaxParallelThreads = 4 };

    Parallel.ForEach(filePaths, file =>
    {
        var result = BarcodeReader.Read(file, options).FirstOrDefault();
        if (result != null)
            output[file] = result.Value;
    });

    return output.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
Imports IronBarCode
Imports System.Collections.Concurrent

Public Function ProcessBatch(filePaths As IEnumerable(Of String)) As Dictionary(Of String, String)
    Dim output = New ConcurrentDictionary(Of String, String)()
    Dim options = New BarcodeReaderOptions With {.MaxParallelThreads = 4}

    Parallel.ForEach(filePaths, Sub(file)
        Dim result = BarcodeReader.Read(file, options).FirstOrDefault()
        If result IsNot Nothing Then
            output(file) = result.Value
        End If
    End Sub)

    Return output.ToDictionary(Function(kvp) kvp.Key, Function(kvp) kvp.Value)
End Function
$vbLabelText   $csharpLabel

보호하거나 격리할 리더 인스턴스가 없습니다. 비동기 파이프라인 패턴 및 스레드 수 구성에 대한 자세한 내용은 비동기 및 멀티스레드 바코드 판독 가이드를 참조하십시오.

PDF에서 바코드 추출하기

이 예제는 PdfiumViewer 렌더 루프를 대체합니다. 기존 통합이 PdfiumViewer 대신 Ghostscript 또는 iText를 사용했다면, 이전 블록은 세부사항에서 다를 수 있지만 구조적으로 동일할 것입니다: ZXing.Net에 비트맵을 공급하는 페이지 열거 루프.

ZXing .NET 접근 방식:

using ZXing;
using ZXing.Windows.Compatibility;
using PdfiumViewer;
using System.Drawing;
using System.Drawing.Imaging;

public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
    var collected = new List<string>();

    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.PDF_417
    };

    using var document = PdfDocument.Load(pdfPath);
    for (int page = 0; page < document.PageCount; page++)
    {
        string temp = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png");
        try
        {
            using var rendered = document.Render(page, 200, 200, PdfRenderFlags.CorrectFromDpi);
            rendered.Save(temp, ImageFormat.Png);

            using var bmp = new Bitmap(temp);
            var decoded = reader.DecodeMultiple(bmp);
            if (decoded != null)
                collected.AddRange(decoded.Select(d => d.Text));
        }
        finally
        {
            if (File.Exists(temp))
                File.Delete(temp);
        }
    }

    return collected;
}
using ZXing;
using ZXing.Windows.Compatibility;
using PdfiumViewer;
using System.Drawing;
using System.Drawing.Imaging;

public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
    var collected = new List<string>();

    var reader = new BarcodeReader();
    reader.Options.PossibleFormats = new List<BarcodeFormat>
    {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.PDF_417
    };

    using var document = PdfDocument.Load(pdfPath);
    for (int page = 0; page < document.PageCount; page++)
    {
        string temp = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png");
        try
        {
            using var rendered = document.Render(page, 200, 200, PdfRenderFlags.CorrectFromDpi);
            rendered.Save(temp, ImageFormat.Png);

            using var bmp = new Bitmap(temp);
            var decoded = reader.DecodeMultiple(bmp);
            if (decoded != null)
                collected.AddRange(decoded.Select(d => d.Text));
        }
        finally
        {
            if (File.Exists(temp))
                File.Delete(temp);
        }
    }

    return collected;
}
Imports ZXing
Imports ZXing.Windows.Compatibility
Imports PdfiumViewer
Imports System.Drawing
Imports System.Drawing.Imaging

Public Function ExtractBarcodesFromPdf(pdfPath As String) As List(Of String)
    Dim collected As New List(Of String)()

    Dim reader As New BarcodeReader()
    reader.Options.PossibleFormats = New List(Of BarcodeFormat) From {
        BarcodeFormat.QR_CODE,
        BarcodeFormat.CODE_128,
        BarcodeFormat.PDF_417
    }

    Using document = PdfDocument.Load(pdfPath)
        For page As Integer = 0 To document.PageCount - 1
            Dim temp As String = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png")
            Try
                Using rendered = document.Render(page, 200, 200, PdfRenderFlags.CorrectFromDpi)
                    rendered.Save(temp, ImageFormat.Png)

                    Using bmp As New Bitmap(temp)
                        Dim decoded = reader.DecodeMultiple(bmp)
                        If decoded IsNot Nothing Then
                            collected.AddRange(decoded.Select(Function(d) d.Text))
                        End If
                    End Using
                End Using
            Finally
                If File.Exists(temp) Then
                    File.Delete(temp)
                End If
            End Try
        Next
    End Using

    Return collected
End Function
$vbLabelText   $csharpLabel

IronBarcode 접근 방식:

using IronBarCode;

public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
    return BarcodeReader.Read(pdfPath)
        .Select(r => r.Value)
        .ToList();
}
using IronBarCode;

public List<string> ExtractBarcodesFromPdf(string pdfPath)
{
    return BarcodeReader.Read(pdfPath)
        .Select(r => r.Value)
        .ToList();
}
Imports IronBarCode

Public Function ExtractBarcodesFromPdf(pdfPath As String) As List(Of String)
    Return BarcodeReader.Read(pdfPath) _
        .Select(Function(r) r.Value) _
        .ToList()
End Function
$vbLabelText   $csharpLabel

PDFiumViewer 종속성, 페이지 렌더링 루프, DPI 구성, 임시 파일 생성 및 정리 블록이 모두 제거되었습니다.IronBarcodePDF에서 바코드를 자동으로 읽어 모든 페이지를 자동으로 처리합니다.

바코드 생성

ZXing.Net 작성자는 호출자가 System.Drawing.Imaging를 사용하여 저장해야 하는 Bitmap을 반환합니다. IronBarcode는 내장된 출력 메서드와 함께 GeneratedBarcode을 반환합니다.

ZXing .NET 접근 방식:

using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using System.Drawing;
using System.Drawing.Imaging;

public void WriteCode128(string content, string outputPath)
{
    var writer = new BarcodeWriter
    {
        Format = BarcodeFormat.CODE_128,
        Options = new EncodingOptions
        {
            Width = 400,
            Height = 120,
            Margin = 10
        }
    };

    using var bitmap = writer.Write(content);
    bitmap.Save(outputPath, ImageFormat.Png);
}
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
using System.Drawing;
using System.Drawing.Imaging;

public void WriteCode128(string content, string outputPath)
{
    var writer = new BarcodeWriter
    {
        Format = BarcodeFormat.CODE_128,
        Options = new EncodingOptions
        {
            Width = 400,
            Height = 120,
            Margin = 10
        }
    };

    using var bitmap = writer.Write(content);
    bitmap.Save(outputPath, ImageFormat.Png);
}
Imports ZXing
Imports ZXing.Common
Imports ZXing.Windows.Compatibility
Imports System.Drawing
Imports System.Drawing.Imaging

Public Sub WriteCode128(content As String, outputPath As String)
    Dim writer = New BarcodeWriter With {
        .Format = BarcodeFormat.CODE_128,
        .Options = New EncodingOptions With {
            .Width = 400,
            .Height = 120,
            .Margin = 10
        }
    }

    Using bitmap = writer.Write(content)
        bitmap.Save(outputPath, ImageFormat.Png)
    End Using
End Sub
$vbLabelText   $csharpLabel

IronBarcode 접근 방식:

using IronBarCode;

public void WriteCode128(string content, string outputPath)
{
    BarcodeWriter.CreateBarcode(content, BarcodeEncoding.Code128)
        .ResizeTo(400, 120)
        .SaveAsPng(outputPath);
}
using IronBarCode;

public void WriteCode128(string content, string outputPath)
{
    BarcodeWriter.CreateBarcode(content, BarcodeEncoding.Code128)
        .ResizeTo(400, 120)
        .SaveAsPng(outputPath);
}
Imports IronBarCode

Public Sub WriteCode128(content As String, outputPath As String)
    BarcodeWriter.CreateBarcode(content, BarcodeEncoding.Code128) _
        .ResizeTo(400, 120) _
        .SaveAsPng(outputPath)
End Sub
$vbLabelText   $csharpLabel

파일에 저장하는 대신 바이너리 출력을 원할 경우, 반환된 GeneratedBarcode 객체에서 ToPngBinaryData()ToJpegBinaryData()가 사용할 수 있으며 어떠한 MemoryStream 배관도 필요하지 않습니다.

ZXing .NET API와IronBarcode매핑 참조

ZXing.Net IronBarcode 노트
new BarcodeReader() 정적 — 인스턴스 없음 BarcodeReader.Read(...)은 정적 호출입니다
reader.Options.PossibleFormats = new List<BarcodeFormat> { ... } 필요 없음 자동 감지 기능은 50개 이상의 모든 형식을 지원합니다.
reader.Options.TryHarder = true Speed = ReadingSpeed.Balanced BarcodeReaderOptions 통해 정확도 조정
reader.Decode(bitmap) BarcodeReader.Read(imagePath).FirstOrDefault() 파일 경로 전송 — Bitmap 구축 불필요
reader.DecodeMultiple(bitmap) BarcodeReader.Read(imagePath) 항상 컬렉션을 반환합니다. never null
result.Text result.Value 부동산 이름 변경됨
result.BarcodeFormat result.Format 부동산 이름 변경됨
BarcodeFormat.QR_CODE BarcodeEncoding.QRCode 열거형 명명 규칙 변경
BarcodeFormat.CODE_128 BarcodeEncoding.Code128 열거형 명명 규칙 변경
BarcodeFormat.EAN_13 BarcodeEncoding.EAN13 열거형 명명 규칙 변경
BarcodeFormat.DATA_MATRIX BarcodeEncoding.DataMatrix 열거형 명명 규칙 변경
BarcodeFormat.PDF_417 BarcodeEncoding.PDF417 열거형 명명 규칙 변경
새 바코드 작성기 { 형식 = ..., 옵션 = 새 EncodingOptions { ... } } BarcodeWriter.CreateBarcode(data, encoding) 정적 팩토리, 옵션 객체 없음
writer.Write(data)Bitmap를 반환합니다 .SaveAsPng(path) / .ToPngBinaryData() GeneratedBarcode에 내장된 출력
EncodingOptions { Width, Height } .ResizeTo(width, height) 플루언트 크기 조정 방법
PDF를 지원하지 않습니다. BarcodeReader.Read("file.pdf") PDF 기본 지원, 모든 페이지

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

문제 1: 바코드 판독기 인스턴스화 패턴

ZXing.Net: 호출자는 new BarcodeReader()을 생성하고 reader.Options.PossibleFormats를 설정하고 Bitmap을 로드하며 reader.Decode(bitmap) 또는 reader.DecodeMultiple(bitmap)을 호출하여 result.Text을 읽습니다.

해결책: 인스턴스 생성 부분을 완전히 제거합니다. 전체 패턴을 정적 호출로 대체하세요.

// Before: reader creation + format config + bitmap + decode + result.Text
// After:
var result = BarcodeReader.Read(imagePath).FirstOrDefault();
var value = result?.Value ?? string.Empty;
// Before: reader creation + format config + bitmap + decode + result.Text
// After:
var result = BarcodeReader.Read(imagePath).FirstOrDefault();
var value = result?.Value ?? string.Empty;
' Before: reader creation + format config + bitmap + decode + result.Text
' After:
Dim result = BarcodeReader.Read(imagePath).FirstOrDefault()
Dim value = If(result?.Value, String.Empty)
$vbLabelText   $csharpLabel

new BarcodeReader()의 모든 인스턴스를 찾기 위해 코드베이스를 검색합니다. 각각이 제거되는 것이지, 리팩토링되는 것이 아닙니다.

문제 2: PossibleFormats 블록 제거

ZXing .NET: 모든 디코딩 호출 앞에 reader.Options.PossibleFormats = new List가 붙습니다. { ... }`할당. 이러한 목록은 종종 길고 프로젝트별로 특화되어 있습니다.

해결책:PossibleFormats 할당 블록을 전부 삭제합니다.IronBarcode자동 형식 감지 기능을 수행합니다. 형식 목록은 허용되지 않으며 요구되지도 않습니다. TryHarder = true 플래그가 포맷 목록과 함께 설정되었던 경우, Speed = ReadingSpeed.Balanced 및 정확도 튜닝이 필요할 경우 BarcodeReaderOptions 객체로 교체하십시오.

문제 3: 바인딩 패키지 정리

ZXing.Net: ZXing.Net.Bindings.Windows.Compatibility를 사용하는 프로젝트는 입력 유형으로 System.Drawing.Bitmap을 참조하는 코드가 있습니다. ZXing.Net.Bindings.ImageSharp를 사용하는 프로젝트는 SixLabors.ImageSharp.Image<Rgba32>을 참조합니다. 바인딩 패키지가 제거되면 두 패턴 모두 제대로 작동하지 않습니다.

해결 방법: 바인딩 패키지를 모두 제거하고 이미지 로딩 코드를 모두 새로 작성하십시오. IronBarcode의 BarcodeReader.Read은 파일 경로 문자열, byte[], Stream 또는 Uri을 허용하며, Bitmap 또는 Image<t> 구축이 필요하지 않습니다. 단순히 Bitmap 로딩을 위해 존재했던 남은 using System.Drawing; 가져오기도 제거할 수 있습니다.

문제 4: result.Text를 result.Value로 변경

ZXing.Net: 디코딩된 바코드 값은 result.Text을 통해 접근합니다. 바코드 형식은 result.BarcodeFormat으로 접근합니다.

해결책: 코드베이스 전반에 걸쳐 result.Textresult.Value으로, result.BarcodeFormatresult.Format으로 대체합니다. 두 변경 사항은 간단한 속성 이름 변경이며, 동작상의 차이는 없습니다.

ZXing .NET 마이그레이션 체크리스트

이동 전 작업

변경 작업을 수행하기 전에 코드베이스를 검토하여 모든 ZXing .NET 참조를 찾으십시오.

grep -r "using ZXing" --include="*.cs" .
grep -r "new BarcodeReader" --include="*.cs" .
grep -r "PossibleFormats" --include="*.cs" .
grep -r "BarcodeFormat\." --include="*.cs" .
grep -r "reader\.Decode\|reader\.DecodeMultiple" --include="*.cs" .
grep -r "result\.Text\|result\.BarcodeFormat" --include="*.cs" .
grep -r "new BarcodeWriter\|writer\.Write\|EncodingOptions" --include="*.cs" .
grep -r "PdfiumViewer\|PdfDocument\.Load" --include="*.cs" .
grep -r "using System\.Drawing" --include="*.cs" .
grep -r "using ZXing" --include="*.cs" .
grep -r "new BarcodeReader" --include="*.cs" .
grep -r "PossibleFormats" --include="*.cs" .
grep -r "BarcodeFormat\." --include="*.cs" .
grep -r "reader\.Decode\|reader\.DecodeMultiple" --include="*.cs" .
grep -r "result\.Text\|result\.BarcodeFormat" --include="*.cs" .
grep -r "new BarcodeWriter\|writer\.Write\|EncodingOptions" --include="*.cs" .
grep -r "PdfiumViewer\|PdfDocument\.Load" --include="*.cs" .
grep -r "using System\.Drawing" --include="*.cs" .
SHELL

ZXing 바인딩 패키지 (Windows 대 ImageSharp)를 참조하는 파일을 문서화하고, ZXing 입력을 위해서만 사용된 System.Drawing.Bitmap 위치를 기록합니다. Dockerfile (존재하는 경우)에 대해 libgdiplus 설치 유무를 검토합니다.

코드 업데이트 작업

  1. ZXing.Net, ZXing.Net.Bindings.Windows.Compatibility, ZXing.Net.Bindings.ImageSharp, 그리고 PdfiumViewer NuGet 패키지를 제거합니다
  2. IronBarcode NuGet 패키지를 설치합니다
  3. 애플리케이션 시작 시 IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";을 추가합니다
  4. 모든 using ZXing*using SixLabors.ImageSharp* 가져오기를 using IronBarCode;으로 교체합니다
  5. 모든 new BarcodeReader() 인스턴스화를 제거합니다
  6. 모든 reader.Options.PossibleFormats = ... 블록을 삭제합니다
  7. reader.Decode(bitmap)BarcodeReader.Read(imagePath).FirstOrDefault()로 대체합니다
  8. reader.DecodeMultiple(bitmap)BarcodeReader.Read(imagePath)로 대체합니다
  9. result.Textresult.Value로 대체합니다
  10. result.BarcodeFormatresult.Format로 대체합니다
  11. BarcodeFormat.X 열거형 참조를 BarcodeEncoding.X 대응 항목으로 업데이트합니다
  12. 새 바코드 작성기 { 형식 = ..., 옵션 = 새 EncodingOptions { ... } 를 교체합니다. } }withBarcodeWriter.CreateBarcode(data, encoding).ResizeTo(w, h)`
  13. writer.Write(data) + bitmap.Save(...).SaveAsPng(path) 또는 .ToPngBinaryData()로 대체합니다
  14. 단지 ZXing.Net 비트맵 로딩을 위해 존재하던 모든 using System.Drawing; 가져오기를 제거합니다
  15. PDF 해결 방법으로 구현된 PDFiumViewer 페이지 렌더링 루프를 모두 제거하십시오.
  16. 리눅스에서 System.Drawing를 지원하기 위한 목적으로 Dockerfile에 추가된 경우, libgdiplus를 제거합니다

마이그레이션 후 테스트

  • 애플리케이션이 이전에 감지하도록 구성된 모든 바코드 형식이 성공적으로 감지되는지 확인하십시오.
  • 이전에 PossibleFormats 목록에서 제외되었던 바코드 형식을 포함한 이미지로 테스트하여 자동 감지가 이를 잡아내도록 확인합니다
  • 부하 상태에서 동시 처리 경로를 실행하고 경쟁 조건이나 null 결과가 발생하지 않는지 확인합니다.
  • 애플리케이션이 PDF 뷰어를 통해 PDF를 처리한 경우, 동일한 PDF 입력값을 제공하고 바코드 값이 일치하는지 확인하십시오.
  • 생성된 바코드(코드 128, QR 코드 등)가 올바른 출력 형식과 크기를 갖는지 확인하십시오.
  • Linux 또는 Docker 배포에서 이미지 읽기 및 PDF 읽기가 libgdiplus 없이 작동하는지 확인합니다
  • 전체 테스트 Suite 실행하고 결과를 마이그레이션 전 기준선과 비교합니다.

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

스레드 안전성 부담 제거: IronBarcode의 정적 API는 스레드별 인스턴스 패턴을 완전히 없앴습니다. 읽기를 인스턴스화 할 필요가 없으며, 스레드별로 설정해야 하는 포맷 목록도 없으며 관리할 ThreadLocal 풀도 없습니다. 동일한 호출은 단일 스레드 환경과 고도로 동시적인 환경 모두에서 올바르게 작동하며, 동시성 정확성은 호출자마다 위임되는 것이 아니라 라이브러리에서 제공합니다.

자동 포맷 감지: PossibleFormats 목록을 제거하면 개발 중 예상되지 않은 바코드 형식이 문서에 포함될 때 발생하는 조용한 실패의 범주가 제거됩니다. 외부 파트너로부터 문서를 처리하거나 진화하는 바코드 표준에 따라 작동하는 애플리케이션은 더 이상 안정성을 유지하기 위해 형식 목록을 관리할 필요가 없습니다.

네이티브 PDF 처리: PdfiumViewer의 렌더링 루프(페이지 열거, DPI 구성, 임시 파일 수명 주기 및 정리 코드)가 완전히 제거되었습니다. 이전에는 PDF 바코드를 처리하기 위해 두 개의 라이브러리(ZXing .NET 및 PDF 렌더러)가 필요했던 애플리케이션이 이제 하나의 라이브러리만 사용하게 되었습니다. 배포 종속성이 줄어들면 빌드 및 배포 과정이 모두 간소화됩니다.

단일 크로스 플랫폼 패키지: Windows와 Linux 배포판 간의 바인딩 패키지 구분이 사라집니다. 모든 타겟 플랫폼에서 동일한 BarcodeReader.Read(path) 호출이 컴파일되고 동일하게 동작하여, 이미지 로딩 코드에서 플랫폼 조건문이 불필요해지고, 크로스 플랫폼 개발 및 컨테이너화 워크플로우를 간소화합니다.

인프라 코드 감소: 이번 마이그레이션의 가장 중요한 결과는 바코드 작업을 수행하기 위한 것이 아니라 라이브러리의 아키텍처 요구 사항을 충족하기 위해 ZXing .NET 통합에 존재했던 주변 인프라(비트맵 로딩 블록, 형식 목록, PDF 뷰어 렌더링 루프, 스레드 로컬 풀)를 제거한 것입니다. 마이그레이션 후 남는 것은 바코드 로직 자체입니다. 탐지율 및 스캔 시나리오에 대한 추가적인 맥락을 확인하려면 ZXing .NET 과IronBarcode스캐너 비교에서 보다 포괄적인 분석을 참조하십시오.

참고해 주세요Ghostscript, PDFium, ZXing.NET, 및 iText는 각 소유자의 등록 상표입니다. 이 사이트는 Artifex Software, Chromium Project, Google, ZXing.NET 또는 iText Group과 관련이 없으며, 모든 제품 이름, 로고 및 브랜드는 각 소유자의 자산입니다. 비교는 정보 제공 목적으로만 사용되며, 작성 시점에 공개적으로 이용 가능한 정보를 반영합니다.

자주 묻는 질문

ZXing.Net에서 IronBarcode로 마이그레이션해야 하는 이유는 무엇인가요?

일반적인 이유로는 라이선스 간소화(SDK + 런타임 키 복잡성 제거), 처리량 제한 제거, 네이티브 PDF 지원 확보, Docker/CI/CD 배포 개선, 프로덕션 코드의 API 상용구 감소 등이 있습니다.

ZXing.Net API 호출을 IronBarcode로 대체하려면 어떻게 해야 하나요?

인스턴스 생성 및 라이선스 상용구를 IronBarCode.License.LicenseKey = "key"로 대체합니다. 판독기 호출을 BarcodeReader.Read(경로)로, 쓰기 호출을 BarcodeWriter.CreateBarcode(데이터, 인코딩)로 바꿉니다. 정적 메서드는 인스턴스 관리가 필요하지 않습니다.

ZXing.Net에서 IronBarcode로 마이그레이션할 때 얼마나 많은 코드가 변경되나요?

대부분의 마이그레이션은 더 적은 코드 줄로 이루어집니다. 라이선스 상용구, 인스턴스 생성자, 명시적 형식 구성이 제거됩니다. 핵심 읽기/쓰기 작업이 더 간결한 결과 객체를 가진 더 짧은 IronBarcode에 매핑됩니다.

마이그레이션하는 동안 ZXing.Net과 IronBarcode를 모두 설치해야 하나요?

아니요. 대부분의 마이그레이션은 병렬 작업이 아닌 직접 교체 작업입니다. 한 번에 하나의 서비스 클래스를 마이그레이션하고, NuGet 참조를 교체하고, 인스턴스화 및 API 호출 패턴을 업데이트한 후 다음 클래스로 이동합니다.

IronBarcode의 NuGet 패키지 이름은 무엇인가요?

패키지는 'IronBarCode'(대문자 B와 C 포함)입니다. '설치-패키지 IronBarCode' 또는 '닷넷 추가 패키지 IronBarCode'로 설치합니다. 코드의 사용 지시어는 'using IronBarCode;'입니다.

IronBarcode는 ZXing.Net과 비교하여 Docker 배포를 어떻게 간소화하나요?

IronBarcode는 외부 SDK 파일이나 마운트된 라이선스 구성이 없는 NuGet 패키지입니다. Docker에서 IRONBARCODE_LICENSE_KEY 환경 변수를 설정하면 패키지가 시작 시 라이선스 유효성 검사를 처리합니다.

ZXing.Net에서 마이그레이션한 후 IronBarcode가 모든 바코드 형식을 자동으로 감지하나요?

예. IronBarcode는 지원되는 모든 형식에서 기호를 자동으로 감지합니다. 명시적인 바코드 유형 열거가 필요하지 않습니다. 형식이 이미 알려져 있고 성능이 중요한 경우 BarcodeReaderOptions를 사용하여 검색 공간을 최적화하여 제한할 수 있습니다.

IronBarcode는 별도의 라이브러리 없이 PDF에서 바코드를 판독할 수 있나요?

예. BarcodeReader.Read("document.pdf")는 기본적으로 PDF 파일을 처리합니다. 결과에는 발견된 각 바코드에 대한 페이지 번호, 형식, 값 및 신뢰도가 포함됩니다. 외부 PDF 렌더링 단계가 필요하지 않습니다.

IronBarcode는 병렬 바코드 처리를 어떻게 처리하나요?

IronBarcode의 정적 메서드는 상태 저장소가 없고 스레드에 안전합니다. 스레드별 인스턴스 관리 없이 파일 목록에 직접 Parallel.ForEach를 사용할 수 있습니다. BarcodeReaderOptions.MaxParallelThreads는 내부 스레드 예산을 제어합니다.

ZXing.Net에서 IronBarcode로 마이그레이션하면 어떤 결과 속성이 변경되나요?

일반적인 이름 변경: 바코드 값은 값으로, 바코드 유형은 형식으로 바뀝니다. IronBarcode 결과에는 신뢰도 및 페이지 번호도 추가됩니다. 솔루션 전반의 검색 및 바꾸기 기능은 기존 결과 처리 코드에서 이름 변경을 처리합니다.

CI/CD 파이프라인에서 IronBarcode 라이선싱을 설정하려면 어떻게 해야 하나요?

IRONBARCODE_LICENSE_KEY를 파이프라인 시크릿으로 저장하고 애플리케이션 시작 코드에 IronBarCode.License.LicenseKey를 할당하세요. 하나의 비밀은 개발, 테스트, 스테이징 및 프로덕션을 포함한 모든 환경에 적용됩니다.

IronBarcode는 사용자 지정 스타일로 QR 코드 생성을 지원하나요?

예. QRCodeWriter.CreateQrCode()는 변경바코드색()을 통한 사용자 지정 색상, 추가브랜드 로고()를 통한 로고 임베딩, 구성 가능한 오류 수정 수준, PNG, JPG, PDF, 스트림을 포함한 여러 출력 형식을 지원합니다.

Curtis Chau
기술 문서 작성자

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

커티스는 개발 분야 외에도 사물 인터넷(IoT)에 깊은 관심을 가지고 있으며, 하드웨어와 소프트웨어를 통합하는 혁신적인 방법을 연구합니다. 여가 시간에는 게임을 즐기거나 디스코드 봇을 만들면서 기술에 대한 애정과 창의성을 결합합니다.

아이언 서포트 팀

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