ERP-node/backend-node/src/app.ts

182 lines
6.9 KiB
TypeScript

import "dotenv/config";
import express from "express";
import cors from "cors";
import helmet from "helmet";
import compression from "compression";
import rateLimit from "express-rate-limit";
import path from "path";
import config from "./config/environment";
import { logger } from "./utils/logger";
import { errorHandler } from "./middleware/errorHandler";
// 라우터 임포트
import authRoutes from "./routes/authRoutes";
import adminRoutes from "./routes/adminRoutes";
import multilangRoutes from "./routes/multilangRoutes";
import tableManagementRoutes from "./routes/tableManagementRoutes";
import entityJoinRoutes from "./routes/entityJoinRoutes";
import screenManagementRoutes from "./routes/screenManagementRoutes";
import commonCodeRoutes from "./routes/commonCodeRoutes";
import dynamicFormRoutes from "./routes/dynamicFormRoutes";
import fileRoutes from "./routes/fileRoutes";
import companyManagementRoutes from "./routes/companyManagementRoutes";
import dataflowRoutes from "./routes/dataflowRoutes";
import dataflowDiagramRoutes from "./routes/dataflowDiagramRoutes";
import webTypeStandardRoutes from "./routes/webTypeStandardRoutes";
import buttonActionStandardRoutes from "./routes/buttonActionStandardRoutes";
import screenStandardRoutes from "./routes/screenStandardRoutes";
import templateStandardRoutes from "./routes/templateStandardRoutes";
import componentStandardRoutes from "./routes/componentStandardRoutes";
import layoutRoutes from "./routes/layoutRoutes";
import dataRoutes from "./routes/dataRoutes";
import testButtonDataflowRoutes from "./routes/testButtonDataflowRoutes";
import externalDbConnectionRoutes from "./routes/externalDbConnectionRoutes";
import multiConnectionRoutes from "./routes/multiConnectionRoutes";
import screenFileRoutes from "./routes/screenFileRoutes";
import dbTypeCategoryRoutes from "./routes/dbTypeCategoryRoutes";
import ddlRoutes from "./routes/ddlRoutes";
import entityReferenceRoutes from "./routes/entityReferenceRoutes";
import externalCallRoutes from "./routes/externalCallRoutes";
import externalCallConfigRoutes from "./routes/externalCallConfigRoutes";
import dataflowExecutionRoutes from "./routes/dataflowExecutionRoutes";
// import collectionRoutes from "./routes/collectionRoutes"; // 임시 주석
// import batchRoutes from "./routes/batchRoutes"; // 임시 주석
// import userRoutes from './routes/userRoutes';
// import menuRoutes from './routes/menuRoutes';
const app = express();
// 기본 미들웨어
app.use(helmet());
app.use(compression());
app.use(express.json({ limit: "10mb" }));
app.use(express.urlencoded({ extended: true, limit: "10mb" }));
// 정적 파일 서빙 (업로드된 파일들)
app.use(
"/uploads",
express.static(path.join(process.cwd(), "uploads"), {
setHeaders: (res, path) => {
// 파일 서빙 시 CORS 헤더 설정
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
res.setHeader(
"Access-Control-Allow-Headers",
"Content-Type, Authorization"
);
res.setHeader("Cache-Control", "public, max-age=3600");
},
})
);
// CORS 설정 - environment.ts에서 이미 올바른 형태로 처리됨
app.use(
cors({
origin: config.cors.origin, // 이미 배열 또는 boolean으로 처리됨
credentials: config.cors.credentials,
methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
allowedHeaders: [
"Content-Type",
"Authorization",
"X-Requested-With",
"Accept",
"Origin",
"Access-Control-Request-Method",
"Access-Control-Request-Headers",
],
preflightContinue: false,
optionsSuccessStatus: 200,
})
);
// Rate Limiting (개발 환경에서는 완화)
const limiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1분
max: config.nodeEnv === "development" ? 10000 : 100, // 개발환경에서는 10000으로 증가, 운영환경에서는 100
message: {
error: "너무 많은 요청이 발생했습니다. 잠시 후 다시 시도해주세요.",
},
skip: (req) => {
// 헬스 체크와 자주 호출되는 API들은 Rate Limiting 완화
return (
req.path === "/health" ||
req.path.includes("/table-management/") ||
req.path.includes("/external-db-connections/") ||
req.path.includes("/screen-management/") ||
req.path.includes("/multi-connection/") ||
req.path.includes("/dataflow-diagrams/")
);
},
});
app.use("/api/", limiter);
// 헬스 체크 엔드포인트
app.get("/health", (req, res) => {
res.status(200).json({
status: "OK",
timestamp: new Date().toISOString(),
uptime: process.uptime(),
environment: config.nodeEnv,
});
});
// API 라우터
app.use("/api/auth", authRoutes);
app.use("/api/admin", adminRoutes);
app.use("/api/multilang", multilangRoutes);
app.use("/api/table-management", tableManagementRoutes);
app.use("/api/table-management", entityJoinRoutes); // 🎯 Entity 조인 기능
app.use("/api/screen-management", screenManagementRoutes);
app.use("/api/common-codes", commonCodeRoutes);
app.use("/api/dynamic-form", dynamicFormRoutes);
app.use("/api/files", fileRoutes);
app.use("/api/company-management", companyManagementRoutes);
app.use("/api/dataflow", dataflowRoutes);
app.use("/api/dataflow-diagrams", dataflowDiagramRoutes);
app.use("/api/admin/web-types", webTypeStandardRoutes);
app.use("/api/admin/button-actions", buttonActionStandardRoutes);
app.use("/api/admin/template-standards", templateStandardRoutes);
app.use("/api/admin/component-standards", componentStandardRoutes);
app.use("/api/layouts", layoutRoutes);
app.use("/api/screen", screenStandardRoutes);
app.use("/api/data", dataRoutes);
app.use("/api/test-button-dataflow", testButtonDataflowRoutes);
app.use("/api/external-db-connections", externalDbConnectionRoutes);
app.use("/api/multi-connection", multiConnectionRoutes);
app.use("/api/screen-files", screenFileRoutes);
app.use("/api/db-type-categories", dbTypeCategoryRoutes);
app.use("/api/ddl", ddlRoutes);
app.use("/api/entity-reference", entityReferenceRoutes);
app.use("/api/external-calls", externalCallRoutes);
app.use("/api/external-call-configs", externalCallConfigRoutes);
app.use("/api/dataflow", dataflowExecutionRoutes);
// app.use("/api/collections", collectionRoutes); // 임시 주석
// app.use("/api/batch", batchRoutes); // 임시 주석
// app.use('/api/users', userRoutes);
// app.use('/api/menus', menuRoutes);
// 404 핸들러
app.use("*", (req, res) => {
res.status(404).json({
success: false,
message: "요청한 리소스를 찾을 수 없습니다.",
path: req.originalUrl,
});
});
// 에러 핸들러
app.use(errorHandler);
// 서버 시작
const PORT = config.port;
const HOST = config.host;
app.listen(PORT, HOST, () => {
logger.info(`🚀 Server is running on ${HOST}:${PORT}`);
logger.info(`📊 Environment: ${config.nodeEnv}`);
logger.info(`🔗 Health check: http://${HOST}:${PORT}/health`);
logger.info(`🌐 External access: http://39.117.244.52:${PORT}/health`);
});
export default app;