반응형
Replicate 에서 Training 하면서 겪은 일
외부 API를 활용하여 , AI 이미지 학습을 시키고 있는 와중에 , 학습을 하는 시간이 생각보다 길어져서 , 이걸 클라이언트 화면에서 화면을 구현하는데 있어서 주기적으로 상태 체크하는 방법을 찾던 중, Cron, SetInterval 같은 스케쥴링을 생각을 했었다. 위에 두 방식으로 하는걸로 생각했을때 , 즉각적인 상태 반영이 불가능 하는 방면, 불필요한 부하가 걱정이 되어서 , 고민이 깊어질 시기 동료 개발자에게 현재 고충에 있어서 물어보게 되었다.
Socket.io 를 활용한 ** 하트비트 **
이게 왜 실시간 상태를 체크하는게 중요한 이유가 있었다. Replicate 에서는 학습, 생성된 이미지에 있어서 결과 이미지 URL 을 제공하지만
제한 시간이라는게 존재했다.
이걸 Cron , SetInterval 을 통해서 가능한 시간내로 핸들링을 하면 결과 URL 을 DB 에 저장하는데 있어서 해결은 할 수 있지만 기능상
문제가 생길것만 같아서 동료에게 Socket.io 를 활용한 ** HearBeat ** 방법을 생각해보면 된다고 해서 구글에서 사례들을 찾아보며
나와 같은 상황인 개발자분들이 굉장히 많았다.
- 설계 및 구현
2.1 설계 목표
- 클라이언트는 Socket.IO를 통해 서버에 주기적으로 상태 확인 요청(heartbeat)을 보냄
- 서버는 받은 요청을 처리하고, 외부 API 호출이나 데이터베이스 상태 확인 작업을 수행.
- 처리 결과를 클라이언트로 즉시 전송.
2.2 기술 스택
- Next.js : API Route를 사용하여 Socket.IO 서버를 설정.
- Socket.IO : 클라이언트와 서버 간 실시간 통신 구현
- Node.js : 서버 환경에서 상태 확인 및 외부 API 호출
2.3 구현 코드
1) 서버 설정 (API Route)
다음 코드는 Next.js src/pages/api/socket/index.ts
import { Server as SocketIOServer } from "socket.io";
import type { NextApiRequest, NextApiResponse } from "next";
export default function handler(req: NextApiRequest, res: NextApiResponse)
{ const server = res.socket?.server; // Socket.IO 서버 초기화 if (server && !server?.io)
{ console.log("Initializing Socket.IO server...");
const io = new SocketIOServer(server,
{ path: "/api/socket", cors: { origin: "*", // 제한된 도메인만 허용하도록 수정 권장 }, });
server.io = io;
// 클라이언트 연결 처리
io.on("connection", (socket) => {
console.log("Client connected:", socket.id);
// 클라이언트에서 하트비트 이벤트 수신
socket.on("heartbeat", (data) => { console.log("Heartbeat received:", data);
// 상태값 처리 후 클라이언트에 결과 전송
socket.emit("statusUpdate", { message: "Status updated", data, }); });
// 연결 해제 이벤트
socket.on("disconnect", () => { console.log("Client disconnected:", socket.id); }); }); }
else {
console.log("Socket.IO server is already running.");
}
res.end();
}
2)클라이언트 설정
다음 코드는 Next.js src/pages/StatusChecker.tsx
import { useEffect } from "react";
import { io, Socket } from "socket.io-client";
let socket: Socket;
const StatusChecker = () => {
useEffect(() => {
// Socket.IO 클라이언트 연결
socket = io("http://localhost:3000",
{ path: "/api/socket", });
// 서버로 하트비트 전송 (5초마다)
const interval = setInterval(() => {
socket.emit("heartbeat", { clientId: "12345" });
}, 5000);
// 서버로부터 상태 업데이트 수신
socket.on("statusUpdate", (data) => {
console.log("Status update from server:", data);
});
// 연결 해제 및 타이머 정리
return () => { clearInterval(interval); socket.disconnect(); };
}, []);
return
}
Socket.IO 기반 상태 체크 클라이언트
;
};
export default StatusChecker;
3. Socket.IO와 CRON 작업 비교
| 특징 | CRON 작업 | Socket.IO |
|---|---|---|
| 실시간성 | 작업 완료 후 알림을 기다려야 함 | 즉시 상태를 업데이트 및 전달 가능 |
| 주기적 작업 설정 | 서버에서 작업 주기 고정 | 클라이언트 주도로 유연하게 설정 가능 |
| 서버 부하 | 작업량이 많아질 경우 부하 발생 가능 | 연결 유지 비용은 있으나 이벤트 기반 처리 |
| 구현 복잡도 | 단순히 스케줄링 설정 | 클라이언트-서버 간 양방향 통신 구현 필요 |
이 방식을 선택한 이유
- 실시간성 필요: 작업 상태가 업데이트되면 즉시 클라이언트에 반영해야 했기 때문에, CRON 작업보다는 Socket.IO가 적합했습니다.
- 유연성: 클라이언트에서 하트비트를 전송하여 필요할 때만 작업을 수행할 수 있으므로 서버 리소스를 효율적으로 사용할 수 있었습니다.
- 확장성: 여러 클라이언트가 연결된 상태에서도 이벤트 기반으로 각각의 상태를 관리할 수 있습니다.
반응형
'개발 > Next.js' 카테고리의 다른 글
| Next.js + Graphql (0) | 2025.08.22 |
|---|