feat: 소켓으로 마인크래프트 서버 상태 실시간 감지

- 백엔드: 3초마다 서버 상태 확인, 변경 시 브로드캐스트
- 프론트엔드: minecraft_servers 이벤트로 UI 자동 업데이트
- 외부에서 서버 시작/종료해도 UI에 반영
This commit is contained in:
caadiq 2025-12-29 17:46:07 +09:00
parent 2a62dc6739
commit fe86d02a72
3 changed files with 51 additions and 1 deletions

View file

@ -1346,4 +1346,6 @@ router.get("/servers/status/:serverPath(*)", async (req, res) => {
}
});
// 서버 상태 함수들 export (소켓 브로드캐스트용)
export { getServerList, getRunningServer, getContainerStatus };
export default router;

View file

@ -17,7 +17,11 @@ import {
import apiRoutes from "./routes/api.js";
import authRoutes from "./routes/auth.js";
import linkRoutes from "./routes/link.js";
import adminRoutes from "./routes/admin.js";
import adminRoutes, {
getServerList,
getRunningServer,
getContainerStatus,
} from "./routes/admin.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@ -153,11 +157,48 @@ async function refreshLogs() {
}
}
// 마인크래프트 서버 상태 캐시 (변경 감지용)
let lastServerStatusHash = "";
// 마인크래프트 서버 상태 갱신 및 브로드캐스트
async function refreshServerStatus() {
try {
const servers = await getServerList();
const runningContainer = await getRunningServer();
// 각 서버의 상태 확인
const serversWithStatus = await Promise.all(
servers.map(async (server) => {
const status = await getContainerStatus(server.path);
return {
...server,
running: status === "running",
status,
};
})
);
// 상태 변경 감지 (해시 비교)
const currentHash = JSON.stringify({ serversWithStatus, runningContainer });
if (currentHash !== lastServerStatusHash) {
lastServerStatusHash = currentHash;
io.emit("minecraft_servers", {
servers: serversWithStatus,
runningContainer,
});
}
} catch (error) {
// 오류 무시 (서버 디렉토리가 없을 수 있음)
}
}
// 1초마다 데이터 갱신
setInterval(refreshAndBroadcast, 1000);
setInterval(refreshLogs, 1000);
setInterval(refreshServerStatus, 3000); // 서버 상태는 3초마다
refreshAndBroadcast();
refreshLogs();
refreshServerStatus();
// SPA 라우팅 - 모든 경로에 대해 index.html 제공
app.get("*", (req, res) => {

View file

@ -1272,6 +1272,13 @@ export default function Admin({ isMobile = false }) {
}
});
//
socket.on("minecraft_servers", (data) => {
if (data?.servers) {
setServers(data.servers);
}
});
//
socket.emit("get_worlds");