diff --git a/INDEX.md b/INDEX.md index 4ddaad9..f7565ce 100644 --- a/INDEX.md +++ b/INDEX.md @@ -149,6 +149,7 @@ DB 도메인별: | [pagination-policy.md](dev/standards/pagination-policy.md) | 페이지네이션 표준 | | [options-column-policy.md](dev/standards/options-column-policy.md) | JSON options 컬럼 정책 | | [pdf-font-policy.md](dev/standards/pdf-font-policy.md) | PDF 생성 시 폰트 정책 (DomPDF) | +| [pdf-troubleshooting-guide.md](dev/guides/pdf-troubleshooting-guide.md) | PDF 생성 트러블슈팅 (Puppeteer + DomPDF) | | [email-policy.md](dev/standards/email-policy.md) | 멀티테넌시 이메일 발송 정책 | | [blade-react-policy.md](dev/standards/blade-react-policy.md) | Blade + React(JSX) 혼용 시 이중 중괄호 충돌 방지 정책 | | [bending-item-code-policy.md](standards/bending-item-code-policy.md) | 절곡 재공품 품목코드 체계 (BD-XX-nn, 2계층 구조) | diff --git a/dev/guides/pdf-troubleshooting-guide.md b/dev/guides/pdf-troubleshooting-guide.md new file mode 100644 index 0000000..0994cfc --- /dev/null +++ b/dev/guides/pdf-troubleshooting-guide.md @@ -0,0 +1,153 @@ +# PDF 생성 트러블슈팅 가이드 + +> **작성일**: 2026-03-22 +> **대상**: MNG (DomPDF), React (Puppeteer) + +--- + +## 1. 개요 + +SAM에서 PDF를 생성하는 경로는 2가지: + +| 경로 | 기술 | 사용처 | 서버 | +|------|------|--------|------| +| MNG → DomPDF | PHP `barryvdh/laravel-dompdf` | 급여명세서, 문서 출력 등 | API/MNG 서버 | +| React → Puppeteer | Node.js `puppeteer` + Chromium | 검사성적서, 작업일지 등 | React 서버 | + +--- + +## 2. React Puppeteer PDF 이슈 + +### 2.1 `PDF 생성 API 오류` (500 에러) + +**증상**: 검사성적서/작업일지에서 PDF 버튼 클릭 시 "PDF 생성 중 오류가 발생했습니다" 토스트 + +**원인**: Puppeteer가 Chromium 바이너리를 찾지 못함 + +**해결**: +```bash +# 1. 서버에 Chromium 설치 확인 +which chromium-browser # → /usr/bin/chromium-browser + +# 2. .env.local에 경로 설정 +echo 'PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser' >> /home/webservice/react/.env.local + +# 3. React 프로세스 재시작 (Jenkins 재배포 또는 수동) +``` + +**관련 코드**: `react/src/app/api/pdf/generate/route.ts` + +```typescript +const browser = await puppeteer.launch({ + executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || undefined, + // ... +}); +``` + +### 2.2 Puppeteer 메모리 부족 + +**증상**: PDF 생성 시 서버 응답 없음 또는 타임아웃 + +**원인**: Chromium 프로세스가 서버 메모리를 과도하게 사용 + +**해결**: `route.ts`의 puppeteer launch args에 메모리 제한 추가 + +```typescript +args: [ + '--no-sandbox', + '--disable-setuid-sandbox', + '--disable-dev-shm-usage', + '--disable-gpu', + '--single-process', // 메모리 절약 + '--no-zygote', // 메모리 절약 +] +``` + +### 2.3 이미지가 PDF에 누락 + +**증상**: 화면에는 보이는 이미지가 PDF에서 빈 영역 + +**원인**: Puppeteer가 외부 리소스 요청을 차단 (`setRequestInterception`) + +**해결**: `DocumentViewer.tsx`의 `convertImagesToBase64()`가 이미지를 base64로 인라인 변환. R2 presigned URL 만료 시 변환 실패 가능. 이미지 로드 실패 시 fallback 처리 필요. + +--- + +## 3. MNG DomPDF 이슈 + +> **정책 문서**: `dev/standards/pdf-font-policy.md` + +### 3.1 한글 깨짐 (???) + +**원인**: DomPDF에 한글 폰트 미등록 + +**해결**: `ensureKoreanFont()` 호출 후 PDF 생성. 상세 → `pdf-font-policy.md` 참조 + +### 3.2 font-weight 800+ 오류 + +**원인**: Pretendard 폰트가 DomPDF에 `normal`/`bold`만 등록됨 + +**해결**: `font-weight: 800` 이상 사용 금지. `normal` 또는 `bold`만 사용 + +### 3.3 운영서버 폰트 캐시 권한 오류 + +**증상**: 운영서버에서만 PDF 생성 실패 + +**원인**: `vendor/dompdf/dompdf/lib/fonts/` 캐시 디렉토리 권한 문제 (Jenkins 배포 시 소유자 불일치) + +**해결**: +```bash +# 운영서버 +chmod -R 775 /home/webservice/mng/current/vendor/dompdf/dompdf/lib/fonts/ +chown -R www-data:www-data /home/webservice/mng/current/vendor/dompdf/dompdf/lib/fonts/ +``` + +--- + +## 4. 서버별 환경 설정 + +### 개발서버 + +| 항목 | 값 | +|------|------| +| Chromium 경로 | `/usr/bin/chromium-browser` | +| React .env.local | `PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser` | +| React 프로세스 | `next start -H 0.0.0.0 -p 3001` (hskwon 계정) | +| DomPDF 폰트 | `resources/fonts/Pretendard-Regular.ttf`, `Bold.ttf` | + +### 운영서버 + +| 항목 | 값 | +|------|------| +| Chromium 경로 | 확인 필요 (`which chromium-browser`) | +| React .env.local | `PUPPETEER_EXECUTABLE_PATH` 설정 필요 | +| React 프로세스 | Jenkins 배포 관리 | +| DomPDF 폰트 | API/MNG 각각 `resources/fonts/` 번들 | + +--- + +## 5. 체크리스트 + +### PDF 기능 배포 시 +- [ ] 서버에 Chromium 설치 확인 (`which chromium-browser`) +- [ ] `.env.local`에 `PUPPETEER_EXECUTABLE_PATH` 설정 +- [ ] React 프로세스 재시작 후 PDF 생성 테스트 +- [ ] DomPDF 폰트 캐시 디렉토리 권한 확인 (운영서버) + +### PDF 오류 진단 순서 +1. 브라우저 콘솔에서 에러 메시지 확인 +2. React 서버 로그 확인 (`/tmp/react-next.log` 또는 pm2 logs) +3. Puppeteer: Chromium 경로, 메모리, 이미지 인라인 순서로 점검 +4. DomPDF: 폰트 등록, font-weight, 캐시 권한 순서로 점검 + +--- + +## 관련 문서 + +- `dev/standards/pdf-font-policy.md` — DomPDF 폰트 정책 +- `react/src/app/api/pdf/generate/route.ts` — Puppeteer PDF API +- `react/src/components/document-system/viewer/DocumentViewer.tsx` — PDF 버튼 핸들러 + +--- + +**최종 업데이트**: 2026-03-22