서버 요청 수명주기 — listen부터 close까지
listen → accept → 파싱 → 라우팅 → 미들웨어 → 핸들러 → 응답 → close. 모든 웹 서버의 공통 뼈대.
Next.js·Express·FastAPI·Django — 이름만 다를 뿐 골격은 같다. 이 공통 흐름을 알면 어느 프레임워크든 빠르게 적응한다.
서버는 24시간 편의점 점원이다. 문을 열고(`listen`) 손님을 맞이하고(`accept`) 주문 내용을 파악(파싱)한 뒤, 어느 메뉴인지 고르고(라우팅), 재료 준비(미들웨어: 인증·로깅·CORS)를 거쳐 요리(핸들러)한 뒤 내주고(응답) 손님이 떠난다(close).
// 바닐라 Node.js — 가장 낮은 계층에서 본 서버
import http from "node:http";
const server = http.createServer((req, res) => {
// 1) 파싱은 Node가 대신 해줌 (req.method, req.url, req.headers)
console.log(`${req.method} ${req.url}`);
// 2) 라우팅 — 수동
if (req.url === "/" && req.method === "GET") {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello");
} else if (req.url === "/api/users" && req.method === "POST") {
// 3) 본문 스트리밍 수신
let body = "";
req.on("data", chunk => body += chunk);
req.on("end", () => {
const data = JSON.parse(body);
res.writeHead(201, { "Content-Type": "application/json" });
res.end(JSON.stringify({ id: Date.now(), ...data }));
});
} else {
res.writeHead(404);
res.end();
}
});
server.listen(3000, () => console.log("listening 3000"));
// 우아한 종료 — SIGTERM 받으면 새 연결 거부, 기존 처리 완료 대기
process.on("SIGTERM", () => server.close(() => process.exit(0)));Express/Next.js가 숨겨주는 것: 메서드·URL 파싱, 쿠키 파싱, JSON body 파싱, 에러 처리. 내부에는 이 바닐라가 돈다.
미들웨어(Middleware)는 요청·응답 사이에 끼워넣는 파이프라인 단계. 로깅·인증·CORS·에러 처리가 전부 미들웨어. Express/Koa/Next.js 공통 패턴.
// Express 스타일 미들웨어 체인
app.use(logger); // 1) 로깅 (모든 요청)
app.use(cors()); // 2) CORS 헤더 부착
app.use(express.json()); // 3) JSON body 파싱
app.use("/admin", requireAuth); // 4) /admin 하위에만 인증
app.get("/api/users", async (req, res, next) => {
try {
const users = await db.users.findAll();
res.json(users);
} catch (err) {
next(err); // 에러 미들웨어로 위임
}
});
app.use((err, req, res, next) => { // 5) 에러 미들웨어 (4개 인자로 식별)
console.error(err);
res.status(500).json({ error: "Internal" });
});"요청 흐름"을 다이어그램으로 그릴 줄 알면 디버깅이 쉬워진다. 어느 미들웨어에서 막혔는지 로그를 추가해 추적.
우아한 종료(Graceful Shutdown). 배포 시 서버를 내릴 때 진행 중 요청은 끝까지 처리하고 새 연결만 거부. SIGTERM 수신 → `server.close()` → 기존 요청 완료 대기 → 종료. 안 하면 사용자 요청이 503으로 끊긴다.
Next.js App Router의 route handler는 이 수명주기를 함수 한 개로 추상화한 것이다. `export async function GET(request) { return Response.json(...) }` 안쪽에서 Vercel/Node가 위 모든 단계를 대신 처리한다.
요청과 핸들러 사이에 끼워 넣어 로깅·인증·CORS 등을 처리하는 구성 요소의 이름은?
배포 시 진행 중 요청을 끝까지 처리하고 새 연결만 막는 종료 방식을 뭐라고 부르는가?