express를 호출하는 순간 반환되는 app 객체 하나로 라우팅, 미들웨어 등록, 서버 기동까지 모두 처리할 수 있다. Node.js의 http.createServer를 직접 다루는 것과 달리, Express는 이 객체를 중심으로 일관된 API를 제공한다. app 객체가 어떻게 구성되고, 요청이 어떤 경로로 흐르는지 파악하면 Express 애플리케이션의 전체 구조가 보인다.
const express = require('express');
const app = express();
express는 내부적으로 http.createServer에 전달할 수 있는 request handler 함수를 반환한다. 이 함수가 곧 app이며, 동시에 라우터와 미들웨어 스택을 내장한 객체이기도 하다.
express()
└─ returns app (Function + EventEmitter)
├─ app.listen() → http.Server 생성 및 바인딩
├─ app.use() → Middleware 스택에 등록
├─ app.get/post/... → Route 핸들러 등록
└─ app.settings → 설정 값 저장소
app: express가 반환하는 객체로, Node.js Function을 상속하며 http.Server의 request listener로 직접 사용할 수 있다.
app.listen(3000, () => {
console.log('Server running on port 3000');
});
내부적으로는 다음과 동일하다.
const http = require('http');
http.createServer(app).listen(3000);
app.listen은 편의 메서드일 뿐이며, HTTPS가 필요하면 https.createServer(options, app).listen(443)처럼 직접 서버를 생성해 app을 넘기면 된다.
Middleware는 요청-응답 사이클에서 순서대로 실행되는 함수다. app.use로 등록된 미들웨어는 모든 경로에 적용되며, 경로를 첫 번째 인자로 지정하면 해당 경로에만 적용된다.
// 모든 요청에 적용
app.use(express.json());
// /api 경로에만 적용
app.use('/api', authMiddleware);
Request
│
▼
[express.json()] ← app.use() 순서대로 실행
│
▼
[authMiddleware]
│
▼
[Route Handler] ← app.get(), app.post() 등
│
▼
Response
Middleware: (req, res, next) 시그니처를 가진 함수. next를 호출해야 다음 미들웨어로 제어가 넘어간다.
app.get, app.post, app.put, app.delete 등은 HTTP 메서드에 대응하는 라우트를 등록한다.
app.get('/users', (req, res) => {
res.json({ users: [] });
});
app.post('/users', (req, res) => {
const body = req.body;
res.status(201).json(body);
});
| 메서드 | 용도 |
|---|---|
app.get | 리소스 조회 |
app.post | 리소스 생성 |
app.put | 리소스 전체 수정 |
app.patch | 리소스 부분 수정 |
app.delete | 리소스 삭제 |
app.all | 모든 HTTP 메서드에 매칭 |
실제 프로젝트에서의 최소 구성은 다음과 같다.
const express = require('express');
const app = express();
// 기본 미들웨어
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 라우트
app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});
// 서버 시작
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
});
express.json은 Content-Type: application/json 요청의 body를 파싱해 req.body에 담아준다. express.urlencoded는 HTML 폼 데이터를 처리한다. 이 두 미들웨어는 대부분의 API 서버에서 필수적으로 등록된다.
extended: true: qs 라이브러리를 사용해 중첩 객체 파싱을 허용한다. false이면 Node.js 내장 querystring을 사용한다.