한글뷰어 기능수정

This commit is contained in:
koj729
2026-06-18 08:52:23 +09:00
parent cb0c42fbeb
commit 9268e4e6bc
38 changed files with 2544 additions and 211 deletions

View File

@@ -87,83 +87,107 @@ const worker = new Worker('convert-pdf', async (job) => {
const tempOutputPath = tempInputPath.replace(`.${ext}`, '.pdf');
console.log(`[Job ${job.id}] ⚙️ CLI 변환 실행: ${path.basename(exePath)}`);
// 5. CLI 실행을 통해 PDF 변환 수행
await new Promise((resolve, reject) => {
execFile(exePath, [tempInputPath, tempOutputPath], (err, stdout, stderr) => {
if (err) {
console.error(`[Job ${job.id}] ❌ 변환 CLI 실행 에러:`, err.message);
return reject(err);
}
console.log(`[Job ${job.id}] 📝 변환기 출력:`, stdout.trim());
resolve();
});
});
let previewKey = '';
let popupKey = '';
if (!fs.existsSync(tempOutputPath)) {
throw new Error(`변환 성공했으나 결과 PDF 파일이 존재하지 않습니다: ${tempOutputPath}`);
}
// 6. 생성된 PDF를 MinIO 스토리지에 업로드
console.log(`[Job ${job.id}] 📤 변환된 PDF MinIO 스토리지 업로드 중...`);
const pdfBuffer = fs.readFileSync(tempOutputPath);
// preview_key, popup_key 네이밍 규칙 적용
let previewKey = objectKey.replace('archive/origin/', 'archive/preview/').replace(/\.[^.]+$/, '.pdf');
let popupKey = objectKey.replace('archive/origin/', 'archive/popup/').replace(/\.[^.]+$/, '.pdf');
if (previewKey === objectKey) {
previewKey = `archive/preview/${path.basename(objectKey)}`.replace(/\.[^.]+$/, '.pdf');
}
if (popupKey === objectKey) {
popupKey = `archive/popup/${path.basename(objectKey)}`.replace(/\.[^.]+$/, '.pdf');
}
// preview_key 업로드
await s3.send(new PutObjectCommand({
Bucket: bucket,
Key: previewKey,
Body: pdfBuffer,
ContentType: 'application/pdf'
}));
// popup_key 업로드
await s3.send(new PutObjectCommand({
Bucket: bucket,
Key: popupKey,
Body: pdfBuffer,
ContentType: 'application/pdf'
}));
console.log(`[Job ${job.id}] 🚀 업로드 성공: \n - Preview Key: ${previewKey}\n - Popup Key: ${popupKey}`);
// 7. 데이터베이스 레코드 정보 업데이트 (preview_key, popup_key 반영)
console.log(`[Job ${job.id}] 🗄️ 데이터베이스 정보 갱신 중...`);
const envSetting = process.env.NODE_ENV || 'development';
const tbData = envSetting === 'production' ? 'tb_data' : '_test_tb_data';
if (type === 'archive') {
const updateQuery = `
UPDATE ver4.${tbData}
SET preview_key = $1, popup_key = $2, mod_date = NOW(), mod_activity = 'convertPdf'
WHERE data_id = $3
`;
await pool.query(updateQuery, [previewKey, popupKey, dataId]);
} else if (type === 'officialDoc') {
const updateQuery = `
UPDATE ver4.tb_official_doc_file
SET preview_key = $1, popup_key = $2, mod_date = NOW(), mod_activity = 'convertDocPdf'
WHERE doc_id = $3
`;
await pool.query(updateQuery, [previewKey, popupKey, dataId]);
}
console.log(`[Job ${job.id}] ✅ 데이터베이스 업데이트 완료.`);
// 8. 로컬 임시 파일 삭제
try {
fs.unlinkSync(tempInputPath);
fs.unlinkSync(tempOutputPath);
console.log(`[Job ${job.id}] 🧹 임시 파일 정리 완료.`);
} catch (cleanErr) {
console.warn(`[Job ${job.id}] ⚠️ 임시 파일 제거 실패:`, cleanErr.message);
// 5. CLI 실행을 통해 PDF 변환 수행
const conversionResult = await new Promise((resolve) => {
execFile(exePath, [tempInputPath, tempOutputPath], { encoding: 'buffer' }, (err, stdoutBuffer, stderrBuffer) => {
const decoder = new TextDecoder('euc-kr');
const stdout = decoder.decode(stdoutBuffer || Buffer.alloc(0)).trim();
const stderr = decoder.decode(stderrBuffer || Buffer.alloc(0)).trim();
resolve({ err, stdout, stderr });
});
});
if (conversionResult.stdout) {
console.log(`[Job ${job.id}] 📝 변환기 출력:\n${conversionResult.stdout}`);
}
if (conversionResult.stderr) {
console.error(`[Job ${job.id}] 📝 변환기 에러 출력:\n${conversionResult.stderr}`);
}
if (!fs.existsSync(tempOutputPath)) {
let errMsg = `PDF 변환 파일 생성에 실패했습니다. (결과 파일이 존재하지 않습니다.)`;
if (conversionResult.stdout) {
errMsg += `\n[변환기 출력]: ${conversionResult.stdout}`;
}
if (conversionResult.stderr) {
errMsg += `\n[변환기 에러]: ${conversionResult.stderr}`;
}
if (conversionResult.err) {
errMsg += `\n[실행 에러]: ${conversionResult.err.message}`;
}
throw new Error(errMsg);
}
// 6. 생성된 PDF를 MinIO 스토리지에 업로드
console.log(`[Job ${job.id}] 📤 변환된 PDF MinIO 스토리지 업로드 중...`);
const pdfBuffer = fs.readFileSync(tempOutputPath);
// preview_key, popup_key 네이밍 규칙 적용
previewKey = objectKey.replace('archive/origin/', 'archive/preview/').replace(/\.[^.]+$/, '.pdf');
popupKey = objectKey.replace('archive/origin/', 'archive/popup/').replace(/\.[^.]+$/, '.pdf');
if (previewKey === objectKey) {
previewKey = `archive/preview/${path.basename(objectKey)}`.replace(/\.[^.]+$/, '.pdf');
}
if (popupKey === objectKey) {
popupKey = `archive/popup/${path.basename(objectKey)}`.replace(/\.[^.]+$/, '.pdf');
}
// preview_key 업로드
await s3.send(new PutObjectCommand({
Bucket: bucket,
Key: previewKey,
Body: pdfBuffer,
ContentType: 'application/pdf'
}));
// popup_key 업로드
await s3.send(new PutObjectCommand({
Bucket: bucket,
Key: popupKey,
Body: pdfBuffer,
ContentType: 'application/pdf'
}));
console.log(`[Job ${job.id}] 🚀 업로드 성공: \n - Preview Key: ${previewKey}\n - Popup Key: ${popupKey}`);
// 7. 데이터베이스 레코드 정보 업데이트 (preview_key, popup_key 반영)
console.log(`[Job ${job.id}] 🗄️ 데이터베이스 정보 갱신 중...`);
const envSetting = process.env.NODE_ENV || 'development';
const tbData = envSetting === 'production' ? 'tb_data' : '_test_tb_data';
if (type === 'archive') {
const updateQuery = `
UPDATE ver4.${tbData}
SET preview_key = $1, popup_key = $2, mod_date = NOW(), mod_activity = 'convertPdf'
WHERE data_id = $3
`;
await pool.query(updateQuery, [previewKey, popupKey, dataId]);
} else if (type === 'officialDoc') {
const updateQuery = `
UPDATE ver4.tb_official_doc_file
SET preview_key = $1, popup_key = $2, mod_date = NOW(), mod_activity = 'convertDocPdf'
WHERE doc_id = $3
`;
await pool.query(updateQuery, [previewKey, popupKey, dataId]);
}
console.log(`[Job ${job.id}] ✅ 데이터베이스 업데이트 완료.`);
} finally {
// 8. 로컬 임시 파일 삭제
try {
if (fs.existsSync(tempInputPath)) {
fs.unlinkSync(tempInputPath);
}
if (fs.existsSync(tempOutputPath)) {
fs.unlinkSync(tempOutputPath);
}
console.log(`[Job ${job.id}] 🧹 임시 파일 정리 완료.`);
} catch (cleanErr) {
console.warn(`[Job ${job.id}] ⚠️ 임시 파일 제거 실패:`, cleanErr.message);
}
}
// 완료 후 completed 이벤트 리스너로 데이터 리턴