compat-legacy 문제 해결
한눈에 보기
섹션 제목: “한눈에 보기”대부분의 마이그레이션 문제는 몇 가지 패턴으로 분류됩니다. 아래 각 항목은 증상, 원인, 수정 방법을 나열합니다. 특정 메서드의 동작이 확실하지 않다면 /integrations/tcpdf-compat/method-coverage/ 및 리포지토리 내 권위 있는 매트릭스 docs/TCPDF_COVERAGE.md를 참고합니다.
프로세스가 이전에는 PDF 오류에서 중단되었지만, 이제 예외가 밖으로 전파됩니다
섹션 제목: “프로세스가 이전에는 PDF 오류에서 중단되었지만, 이제 예외가 밖으로 전파됩니다”증상. 이전에는 잘못된 렌더링에서 중단되던 코드가 이제 잡히지 않은 RuntimeException을 던지고, 요청 또는 작업에서 오류가 드러납니다.
원인. 레거시 TCPDF Error()는 die()를 호출합니다. 어댑터는 대신 RuntimeException을 던집니다. 이는 의도된 설계이며, 실패를 관찰할 수 있게 합니다.
수정. 렌더링 진입점을 try/catch로 감싸고 예외를 오류 계약에 매핑합니다. die() 동작을 복원하지 않습니다. /integrations/tcpdf-compat/production-usage/ § 실패 처리를 참고합니다.
new \TCPDF()가 여전히 실제 TCPDF 라이브러리로 해석됩니다
섹션 제목: “new \TCPDF()가 여전히 실제 TCPDF 라이브러리로 해석됩니다”증상. LegacyBootstrap::enableAliases()를 활성화했지만 출력이 여전히 레거시 TCPDF처럼 보이거나 동작에 변화가 없습니다.
원인. enableAliases()는 해당 이름의 클래스가 아직 존재하지 않는 경우에만 별칭을 등록합니다. tecnickcom/tcpdf를 여전히 오토로드할 수 있고 그 \TCPDF가 먼저 로드되면 별칭 등록이 건너뛰어지고 코드는 계속 레거시 TCPDF를 사용합니다.
수정. 마이그레이션 중에는 파일별 명시적 임포트(use NextPDF\Compat\Tcpdf\TCPDF;)를 선호하여 각 호출 지점이 모호하지 않게 합니다. 감사를 통과하면 tecnickcom/tcpdf를 제거합니다(/integrations/tcpdf-compat/migration/ 5 단계 참조). 동일한 프로세스에서 전역 별칭을 활성화한 상태로 두 라이브러리를 함께 실행하지 않습니다.
메서드가 “작동”하지만 전달한 매개변수가 무시됩니다
섹션 제목: “메서드가 “작동”하지만 전달한 매개변수가 무시됩니다”증상. 호출이 성공하고 PDF를 생성하지만, 전달한 옵션(이미지 링크, 정렬, DPI, 책갈피 색상 등)이 아무런 효과가 없습니다.
원인. 해당 메서드는 자동 무시 집합에 속합니다. 소스 호환성을 위해 매개변수를 받아들인 뒤 폐기합니다. 이는 버그가 아니라 문서화된 동작입니다. /integrations/tcpdf-compat/method-coverage/ §2 를 참고합니다.
수정. 이러한 호출을 모두 찾으려면 엄격 모드 감사를 실행합니다:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();$pdf->setStrictMode(true);$pdf->AddPage();$pdf->SetFont('helvetica', '', 12);
try { $pdf->Image('logo.png', 10, 10, 50, 0, '', 'https://example.com');} catch (TcpdfNotImplementedException $e) { // Message lists every ignored parameter and a migration hint. echo $e->getMessage(), "\n";}그런 다음 매개변수를 제거하거나 최신 API($pdf->getDocument())를 통해 다시 표현합니다. /integrations/tcpdf-compat/migration/ 4 단계와 같은 방식입니다.
MultiCell() 반환 값이 항상 1입니다
섹션 제목: “MultiCell() 반환 값이 항상 1입니다”증상. MultiCell()의 반환 값에 따라 분기하는 코드(예: 사용된 높이나 줄 수 계산)가 잘못 동작합니다.
원인. 어댑터의 MultiCell()는 호환성 자리표시자 1을 반환하며, 렌더링된 cell/line 수가 아닙니다. Write()도 마찬가지로 0을 반환합니다.
수정. 이러한 반환 값에 따라 분기하지 않습니다. 렌더링된 높이가 필요한 경우 getStringHeight() / getNumLines()로 계산하거나 그 로직을 최신 API로 옮깁니다.
setPDFVersion('1.4')가 PDF 1.4 파일을 생성하지 않았습니다
섹션 제목: “setPDFVersion('1.4')가 PDF 1.4 파일을 생성하지 않았습니다”증상. 이전 PDF 버전을 요청했지만 출력은 여전히 PDF 2.0입니다.
원인. 출력은 항상 PDF 2.0(ISO 32000-2)입니다. setPDFVersion()은 해당 없음 집합에 속하며, 어댑터는 통지를 발행하고 계속 진행합니다.
수정. 호출을 제거합니다. 다운스트림 소비자가 이전 PDF 버전을 요구하는 경우 해당 소비자 측 제약을 별도로 해결합니다. 어댑터는 하위 버전을 대상으로 할 수 없습니다.
setSignature()가 아무것도 하지 않았습니다 — PDF가 서명되지 않았습니다
섹션 제목: “setSignature()가 아무것도 하지 않았습니다 — PDF가 서명되지 않았습니다”증상. 인증서로 setSignature()를 호출했지만 출력 PDF에 서명이 없습니다.
원인. setSignature()는 이 어댑터를 통해서는 코어 엔진에 구현되어 있지 않습니다. 기본 모드에서는 무동작(no-op)이며, 엄격 모드에서는 예외를 던집니다.
수정. 서명에는 상용 NextPDF 에디션과 최신 서명 API가 필요합니다. /integrations/tcpdf-compat/security-and-operations/ § 디지털 서명을 참고합니다. 레거시 setSignature() 호출이 무언가에 서명할 것이라고 기대하지 않습니다.
Output()가 내 HTTP 응답이나 워커 출력을 손상시켰습니다
섹션 제목: “Output()가 내 HTTP 응답이나 워커 출력을 손상시켰습니다”증상. HTTP 응답에 바이너리 쓰레기가 섞이거나, 워커 로그가 PDF 바이트로 오염됩니다.
원인. 응답을 직접 제어하는 컨텍스트에서 출력 경로(I/D)로 쓰는 출력 대상을 사용했습니다. 어댑터는 레거시 TCPDF처럼 버퍼로 직접 출력하지는 않지만, I/D는 여전히 엔진 출력을 구동합니다.
수정. 직접 제어하는 워커와 핸들러에서 파일을 쓰려면 Output($path, 'F')를 사용하고, 바이트를 얻어 직접 내보내려면 Output($name, 'S')를 사용합니다. 대상 매핑(대소문자 구분 없음, 공백 제거)은 tests/Unit/Compat/Tcpdf/Bridge/OutputBridgeTest.php에서 검증됩니다:
| 코드 | 반환 | 부작용 |
|---|---|---|
S | PDF 바이트(%PDF…) | 없음 |
F | 빈 문자열 | 파일 씀 |
E | base64 MIME 본문 | 없음 |
FI / FD | 빈 문자열 | 파일을 쓴 다음 엔진 출력 |
I / D / 알 수 없음 | 빈 문자열 | 엔진 출력(인라인/다운로드) |
전환 후 정확한 PDF 바이트 단언이 실패합니다
섹션 제목: “전환 후 정확한 PDF 바이트 단언이 실패합니다”증상. 원시 PDF 바이트를 비교하는 스냅샷 테스트가 전반적으로 실패합니다.
원인. 엔진은 독립적인 PDF 2.0 구현입니다. 위임된 메서드에 대해 가시적 출력은 호환되지만 바이트는 다릅니다. 이는 예상된 동작입니다.
수정. 렌더링된 콘텐츠(추출된 텍스트), 구조(페이지 수, 페이지 크기) 또는 스모크 검사(str_starts_with($bytes, '%PDF'))에 대해 단언하도록 기준선을 다시 설정합니다. /integrations/tcpdf-compat/migration/ 4 단계를 참고합니다.
레거시 K_* / PDF_* 상수의 값이 잘못되었습니다
섹션 제목: “레거시 K_* / PDF_* 상수의 값이 잘못되었습니다”증상. 상수를 통해 설정한 사용자 지정 경로 또는 기본값이 적용되지 않습니다.
원인. 어댑터는 상수가 아직 정의되지 않은 경우에만 자동으로 정의하며, 이 작업은 최초 생성 시점에 이루어집니다. define()이 첫 어댑터가 생성된 이후에 실행되면 어댑터의 기본값이 이미 우선 적용됩니다.
수정. 모든 사용자 지정 K_* / PDF_* 상수는 어떤 어댑터 인스턴스가 생성되기 전에 부트스트랩에서 정의합니다. /integrations/tcpdf-compat/configuration/ § 구성 해석 순서를 참고합니다.
생성 시 엔진 버전 불일치
섹션 제목: “생성 시 엔진 버전 불일치”증상. 종속성 업데이트 후 생성에 실패하거나 예상과 다르게 동작합니다.
원인. 어댑터에는 nextpdf/core ^3.0이 필요합니다. 해당 범위를 벗어나 해결된 코어 버전은 지원되지 않습니다.
수정. composer show nextpdf/core를 실행하고 엔진을 ^3.0으로 고정합니다. /integrations/tcpdf-compat/install/ § 엔진 버전 확인을 참고합니다.
진단 빠른 참조
섹션 제목: “진단 빠른 참조”| 질문 | 확인할 위치 |
|---|---|
| 여기서 메서드 X는 실제로 무엇을 합니까? | /integrations/tcpdf-compat/method-coverage/, docs/TCPDF_COVERAGE.md |
| 호출 중 어느 것이 매개변수를 잃습니까? | 엄격 모드 감사(이 페이지; /integrations/tcpdf-compat/migration/) |
| 프로세스가 왜 오류에서 중단되지 않았습니까? | /integrations/tcpdf-compat/security-and-operations/ § 강화된 동작 |
| 출력이 왜 서명되지 않았습니까 / PDF/A가 아닙니까? | /integrations/tcpdf-compat/security-and-operations/ |
| 별칭과 명시적 임포트 충돌 | 이 페이지; /integrations/tcpdf-compat/boot-and-discovery/ |
관련 항목
섹션 제목: “관련 항목”- /integrations/tcpdf-compat/migration/ — 위 문제 대부분을 예방하는 단계별 마이그레이션
- /integrations/tcpdf-compat/method-coverage/ — 메서드별 동작 참조
- /integrations/tcpdf-compat/boot-and-discovery/ — 별칭 등록 및 충돌 회피
docs/TCPDF_COVERAGE.md— 권위 있는 커버리지 매트릭스