Merge remote-tracking branch 'upstream/main'
Some checks failed
Build and Push Images / build-and-push (push) Failing after 53s
Some checks failed
Build and Push Images / build-and-push (push) Failing after 53s
This commit is contained in:
@@ -16,14 +16,17 @@ import { refreshTokenIfNeeded } from "./middleware/authMiddleware";
|
||||
// ============================================
|
||||
|
||||
// 처리되지 않은 Promise 거부 핸들러
|
||||
process.on("unhandledRejection", (reason: Error | any, promise: Promise<any>) => {
|
||||
logger.error("⚠️ Unhandled Promise Rejection:", {
|
||||
reason: reason?.message || reason,
|
||||
stack: reason?.stack,
|
||||
});
|
||||
// 프로세스를 종료하지 않고 로깅만 수행
|
||||
// 심각한 에러의 경우 graceful shutdown 고려
|
||||
});
|
||||
process.on(
|
||||
"unhandledRejection",
|
||||
(reason: Error | any, promise: Promise<any>) => {
|
||||
logger.error("⚠️ Unhandled Promise Rejection:", {
|
||||
reason: reason?.message || reason,
|
||||
stack: reason?.stack,
|
||||
});
|
||||
// 프로세스를 종료하지 않고 로깅만 수행
|
||||
// 심각한 에러의 경우 graceful shutdown 고려
|
||||
},
|
||||
);
|
||||
|
||||
// 처리되지 않은 예외 핸들러
|
||||
process.on("uncaughtException", (error: Error) => {
|
||||
@@ -38,13 +41,16 @@ process.on("uncaughtException", (error: Error) => {
|
||||
// SIGTERM 시그널 처리 (Docker/Kubernetes 환경)
|
||||
process.on("SIGTERM", () => {
|
||||
logger.info("📴 SIGTERM 시그널 수신, graceful shutdown 시작...");
|
||||
// 여기서 연결 풀 정리 등 cleanup 로직 추가 가능
|
||||
const { stopAiAssistant } = require("./utils/startAiAssistant");
|
||||
stopAiAssistant();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// SIGINT 시그널 처리 (Ctrl+C)
|
||||
process.on("SIGINT", () => {
|
||||
logger.info("📴 SIGINT 시그널 수신, graceful shutdown 시작...");
|
||||
const { stopAiAssistant } = require("./utils/startAiAssistant");
|
||||
stopAiAssistant();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
@@ -112,7 +118,9 @@ import departmentRoutes from "./routes/departmentRoutes"; // 부서 관리
|
||||
import tableCategoryValueRoutes from "./routes/tableCategoryValueRoutes"; // 카테고리 값 관리
|
||||
import codeMergeRoutes from "./routes/codeMergeRoutes"; // 코드 병합
|
||||
import numberingRuleRoutes from "./routes/numberingRuleRoutes"; // 채번 규칙 관리
|
||||
import entitySearchRoutes, { entityOptionsRouter } from "./routes/entitySearchRoutes"; // 엔티티 검색 및 옵션
|
||||
import entitySearchRoutes, {
|
||||
entityOptionsRouter,
|
||||
} from "./routes/entitySearchRoutes"; // 엔티티 검색 및 옵션
|
||||
import screenEmbeddingRoutes from "./routes/screenEmbeddingRoutes"; // 화면 임베딩 및 데이터 전달
|
||||
import screenGroupRoutes from "./routes/screenGroupRoutes"; // 화면 그룹 관리
|
||||
import popActionRoutes from "./routes/popActionRoutes"; // POP 액션 실행
|
||||
@@ -128,6 +136,7 @@ import cascadingHierarchyRoutes from "./routes/cascadingHierarchyRoutes"; // 다
|
||||
import categoryValueCascadingRoutes from "./routes/categoryValueCascadingRoutes"; // 카테고리 값 연쇄관계
|
||||
import categoryTreeRoutes from "./routes/categoryTreeRoutes"; // 카테고리 트리 (테스트)
|
||||
import processWorkStandardRoutes from "./routes/processWorkStandardRoutes"; // 공정 작업기준
|
||||
import aiAssistantProxy from "./routes/aiAssistantProxy"; // AI 어시스턴트 API 프록시 (같은 포트로 서비스)
|
||||
import auditLogRoutes from "./routes/auditLogRoutes"; // 통합 변경 이력
|
||||
import { BatchSchedulerService } from "./services/batchSchedulerService";
|
||||
// import collectionRoutes from "./routes/collectionRoutes"; // 임시 주석
|
||||
@@ -152,7 +161,7 @@ app.use(
|
||||
], // 프론트엔드 도메인 허용
|
||||
},
|
||||
},
|
||||
})
|
||||
}),
|
||||
);
|
||||
app.use(compression());
|
||||
app.use(express.json({ limit: "10mb" }));
|
||||
@@ -175,13 +184,13 @@ app.use(
|
||||
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
|
||||
res.setHeader(
|
||||
"Access-Control-Allow-Headers",
|
||||
"Content-Type, Authorization"
|
||||
"Content-Type, Authorization",
|
||||
);
|
||||
res.setHeader("Cross-Origin-Resource-Policy", "cross-origin");
|
||||
res.setHeader("Cache-Control", "public, max-age=3600");
|
||||
next();
|
||||
},
|
||||
express.static(path.join(process.cwd(), "uploads"))
|
||||
express.static(path.join(process.cwd(), "uploads")),
|
||||
);
|
||||
|
||||
// CORS 설정 - environment.ts에서 이미 올바른 형태로 처리됨
|
||||
@@ -201,7 +210,7 @@ app.use(
|
||||
],
|
||||
preflightContinue: false,
|
||||
optionsSuccessStatus: 200,
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
// Rate Limiting (개발 환경에서는 완화)
|
||||
@@ -318,6 +327,7 @@ app.use("/api/category-tree", categoryTreeRoutes); // 카테고리 트리 (테
|
||||
app.use("/api/process-work-standard", processWorkStandardRoutes); // 공정 작업기준
|
||||
app.use("/api/audit-log", auditLogRoutes); // 통합 변경 이력
|
||||
app.use("/api", screenEmbeddingRoutes); // 화면 임베딩 및 데이터 전달
|
||||
app.use("/api/ai/v1", aiAssistantProxy); // AI 어시스턴트 (동일 서비스 내 프록시 → AI 서비스 포트)
|
||||
app.use("/api/vehicle", vehicleTripRoutes); // 차량 운행 이력 관리
|
||||
app.use("/api/approval", approvalRoutes); // 결재 시스템
|
||||
// app.use("/api/collections", collectionRoutes); // 임시 주석
|
||||
@@ -414,15 +424,14 @@ async function initializeServices() {
|
||||
} catch (error) {
|
||||
logger.error(`❌ 메일 자동 삭제 스케줄러 시작 실패:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// 우아한 종료 처리
|
||||
process.on('SIGTERM', () => {
|
||||
logger.info('SIGTERM signal received: closing HTTP server');
|
||||
server.close(() => {
|
||||
logger.info('HTTP server closed');
|
||||
process.exit(0);
|
||||
});
|
||||
// AI 어시스턴트 서비스 함께 기동 (한 번에 킬 가능)
|
||||
try {
|
||||
const { startAiAssistant } = await import("./utils/startAiAssistant");
|
||||
startAiAssistant();
|
||||
} catch (error) {
|
||||
logger.warn("⚠️ AI 어시스턴트 기동 스킵:", error);
|
||||
}
|
||||
});
|
||||
|
||||
export default app;
|
||||
|
||||
Reference in New Issue
Block a user