콘텐츠로 이동

계약 / 바코드

바코드 도메인에는 네 가지 계약이 있습니다. 1D 인코더, 2D 인코더, 레지스트리에서 검색 가능한 제네릭 인코더, 그리고 GS1 데이터 파서입니다. 이 계약들은 인코더가 충족해야 하는 형태를 정의하며, 심볼로지 구현은 이 계약들에 대해 등록됩니다.

Terminal window
composer require nextpdf/core:^3

바코드 인코더는 페이로드 문자열을 PDF 작성기가 그릴 수 있는 모듈 행렬로 변환합니다. NextPDF는 차원에 따라 계약을 분리합니다. Barcode1DEncoderInterface는 선형 심볼로지(Code 128, EAN-13 등)를 인코딩하고 BarcodeData 값 객체를 반환합니다. Barcode2DEncoderInterface는 행렬 심볼로지(QR Code, Data Matrix)를 인코딩합니다. 이 인터페이스는 오류 정정 수준 같은 심볼로지별 매개변수를 위한 옵션 맵을 포함한 Barcode2DData 값 객체를 반환합니다.

BarcodeEncoderInterface는 제네릭 서비스 공급자 계약입니다. BarcodeEncoderRegistry로 검색할 수 있는 모든 2D 인코더가 이를 구현합니다. 이 계약은 흑백 Barcode2DData 또는 컬러 BarcodeColorData 행렬 중 하나를 반환하므로, 등록된 인코더는 별도의 인터페이스 없이 컬러 심볼을 생성할 수 있습니다. 인코더는 생성 시점 구성을 제외하면 무상태여야 합니다. 레지스트리는 등록된 타입마다 공유 인스턴스 하나를 제공하므로, 호출별 상태를 두면 결함이 됩니다.

Gs1DataParserInterface는 구조화된 데이터 계약입니다. 이 인터페이스는 GS1 요소 문자열을 타입이 지정된 객체로 파싱한 뒤, 그 객체를 QR Code, Data Matrix 또는 Code 128 캐리어용으로 다시 인코딩합니다. 이를 통해 GS1 문법을 심볼로지와 분리합니다. 파서는 Application Identifier를 한 번 검증합니다. 캐리어별 메서드는 동일한 파싱 구조를 각 대상에 맞게 포맷합니다. 네 개의 계약은 모두 stable입니다. BarcodeEncoderInterface는 3.0.0부터 안정적이며, 나머지는 1.0.0부터 안정적입니다. 새 메서드는 기본 구현과 함께만 추가됩니다.

타입종류주요 멤버안정성도입 버전
Barcode1DEncoderInterfaceinterfaceencode(string): BarcodeDatastable1.0.0
Barcode2DEncoderInterfaceinterfaceencode(string, array): Barcode2DDatastable1.0.0
BarcodeEncoderInterfaceinterfaceencode(string, array): Barcode2DData|BarcodeColorDatastable3.0.0
Gs1DataParserInterfaceinterfaceparse(), encodeForQrCode(), encodeForDataMatrix(), encodeForCode128()stable1.0.0

2D 계약의 $options 배열은 심볼로지별로 다릅니다(예: QR Code의 오류 정정 수준). 계약은 이 키를 제약하지 않습니다. 등록된 각 인코더가 자체 옵션 집합을 문서화합니다.

examples/10-barcodes.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Barcode\Barcode2DType;
use NextPDF\Barcode\BarcodeType;
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Barcode Examples');
$doc->addPage();
$doc->setFont('helvetica', '', 10);
$doc->cell(0, 6, 'Code 128:', newLine: true);
$doc->write1DBarcode('NEXTPDF-2026', BarcodeType::C128, x: 15, y: null, w: 80, h: 20);
$doc->ln(28);
$doc->cell(0, 6, 'QR Code (URL):', newLine: true);
$doc->write2DBarcode('https://nextpdf.dev', Barcode2DType::QRCode, x: 15, y: null, w: 40, h: 40);
$doc->save(__DIR__ . '/output/10-barcodes.pdf');

write1DBarcode()write2DBarcode()는 레지스트리를 통해 인코더를 찾아냅니다. 애플리케이션 코드가 계약을 직접 다루는 경우는 드뭅니다. 코드가 심볼로지를 지정하면 레지스트리가 해당 인코더를 제공합니다.

examples/contracts/barcode-production.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\Barcode2DEncoderInterface;
use NextPDF\Contracts\Gs1DataParserInterface;
use NextPDF\Exception\BarcodeException;
use Psr\Log\LoggerInterface;
final readonly class Gs1LabelService
{
public function __construct(
private Gs1DataParserInterface $parser,
private Barcode2DEncoderInterface $dataMatrix,
private LoggerInterface $logger,
) {}
/**
* Parse a GS1 element string and encode it as a Data Matrix.
*
* @param string $elementString A GS1 element string with Application Identifiers.
*/
public function encodeLabel(string $elementString): \NextPDF\Barcode\Barcode2DData
{
try {
$parsed = $this->parser->parse($elementString);
$payload = $this->parser->encodeForDataMatrix($parsed);
return $this->dataMatrix->encode($payload, ['errorCorrection' => 'high']);
} catch (BarcodeException $e) {
$this->logger->error('GS1 label encoding failed', [
'error' => $e->getMessage(),
]);
throw $e;
}
}
}

이 서비스는 파서와 인코더 계약에 의존합니다. catch 블록은 구체적인 BarcodeException을 로깅한 뒤 다시 던지며, 단순한 \Exception은 결코 던지지 않습니다.

  • 등록된 인코더는 공유됩니다. 인코더에 호출별 상태를 저장하면 동시 렌더링이 손상됩니다. 인코더는 생성자 구성을 제외하고 무상태로 유지하십시오.
  • BarcodeEncoderInterface::encode()는 컬러 또는 흑백 데이터를 반환할 수 있습니다. 이를 소비하는 코드는 흑백만 가정하지 말고 Barcode2DDataBarcodeColorData를 모두 처리해야 합니다.
  • 2D $options 배열은 계약에서 검증하지 않습니다. 알 수 없는 키는 대부분의 인코더에서 조용히 무시됩니다. 인코더 자체 문서를 참고하여 키 이름을 확인하십시오.
  • GS1 파싱은 문법에 엄격합니다. 알 수 없는 Application Identifier가 포함된 요소 문자열은 부분 파싱을 생성하지 않고 BarcodeException을 발생시킵니다. 업스트림 입력을 검증하십시오.
  • 1D 계약과 2D 계약은 서로 호환되지 않습니다. QR 페이로드를 1D 인코더에 전달하면 유효하지 않은 심볼이 생성됩니다. 레지스트리는 심볼로지 타입에 따라 라우팅하므로, 계약을 직접 호출하기보다 레지스트리를 사용하는 것이 좋습니다.

인코딩 비용은 계약이 아니라 페이로드 길이와 대상 행렬 크기에 따라 증가합니다. 짧은 Code 128 페이로드는 마이크로초 단위로 인코딩됩니다. 오류 정정 수준이 높은 밀집 QR Code는 가장 무거운 2D 사례입니다. 그래도 여러 심볼이 포함된 예제 페이지는 벽시계 기준 1500 ms 및 최대 64 MB라는 performance_budget 안에 충분히 들어옵니다. 행렬은 한 번 계산된 뒤 PDF 연산자로 그려집니다. 동일한 페이로드와 옵션은 항상 동일한 모듈 행렬을 산출하므로 재현성은 bitwise입니다. 레지스트리 조회는 O(1)입니다. 실제 작업은 심볼로지 알고리즘에서 발생합니다.

바코드 페이로드는 스캔된 URL, 일련번호, 추적 코드처럼 공격자의 영향을 받는 경우가 많습니다. 계약은 바이트를 인코딩할 뿐이며, 바이트를 해석하지 않습니다. 악성 URL을 인코딩한 QR Code도 유효한 QR Code이므로, 페이로드 신뢰는 인코더가 아니라 소비자의 책임입니다. 행렬 크기를 제한하고 과도하게 큰 심볼로 인한 서비스 거부를 방지하려면 인코딩 전에 페이로드 길이를 제한하십시오. GS1 파서는 잘못된 형식의 Application Identifier를 거부하여 주입 표면 하나를 제거합니다. 유효한 필드의 의미적 내용은 검증하지 않습니다. 디코딩된 바코드 데이터가 애플리케이션에 다시 들어오는 모든 지점에서는 이를 신뢰할 수 없는 입력으로 취급하십시오.

주장표준참조
QR Code 심볼은 QR Code 행렬 심볼로지 사양을 따릅니다.ISO/IEC 18004QR Code 심볼로지
Data Matrix 심볼은 Data Matrix 심볼로지 사양을 따릅니다.ISO/IEC 16022Data Matrix 심볼로지
Code 128 심볼은 Code 128 선형 심볼로지 사양을 따릅니다.ISO/IEC 15417Code 128 심볼로지
GS1 요소 문자열은 GS1 Application Identifier 문법에 따라 파싱됩니다.GS1 General SpecificationsApplication Identifier

이러한 표준은 번호와 절로 참조됩니다. 이 표준들은 검증 가능한 인용 코퍼스에 존재하지 않으므로 reference_id가 기록되지 않습니다. 엔진은 요구 사항을 의역하고 출처를 인용합니다. 권위 있는 인코딩 규칙은 공표된 표준을 참조하십시오.

Core는 인코더 계약을 정의하고 동결하며 일반 심볼로지를 제공합니다. Pro 및 Enterprise 에디션은 동일한 BarcodeEncoderInterface에 대해 추가 바코드 심볼로지를 위한 확장 인코더 집합을 등록하므로, 상업적 배포는 API 변경 없이 심볼로지 커버리지를 확보할 수 있습니다. Core는 BarcodeEncoderRegistry를 통해 등록된 인코더를 찾아냅니다. 계약 표면은 모든 에디션에서 동일합니다.

  • Contracts: 41 public interfaces (SPI) — SPI 개요 및 안정성 계층입니다.
  • Barcode — 이 계약들에 대해 등록된 심볼로지 구현입니다.
  • 계약 / 문서 — 인코딩된 행렬을 그리는 PdfDocumentInterface입니다.
  • 그래픽스 — 바코드 모듈을 렌더링하는 그리기 레이어입니다.
  • 예외 — 잘못된 형식의 GS1 입력에 대해 던져지는 BarcodeException입니다.