Express REST API Tutorial for Node.js | Routing
이 글의 핵심
Express REST API tutorial: routes, JSON body parsing, middleware pipeline, CRUD APIs, error handling, and security basics—learn to build production-style Node.js backends step by step.
Introduction
What is Express.js?
Express.js is a fast, unopinionated web framework for Node.js. Highlights:
- Small API surface for HTTP servers
- Middleware pipeline for cross-cutting concerns
- Flexible routing (paths, verbs, parameters)
- Template engines (EJS, Pug, etc.)
- Huge middleware ecosystem Typical uses: REST APIs, server-rendered sites, microservices, proxies.
1. Install and hello server
npm init -y
npm install express
npm install --save-dev nodemon
// app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello, Express!');
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server: http://localhost:${PORT}`);
});
Basic skeleton
const express = require('express');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get('/', (req, res) => res.send('Home'));
app.get('/about', (req, res) => res.send('About'));
app.use((req, res) => {
res.status(404).send('Not found');
});
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Server error');
});
app.listen(3000, () => console.log('Listening on :3000'));
2. Routing
HTTP verbs
app.get('/users', (req, res) => res.json({ users: ['Alice', 'Bob'] }));
app.post('/users', (req, res) => {
const user = req.body;
res.status(201).json({ message: 'created', user });
});
app.put('/users/:id', (req, res) => {
const { id } = req.params;
res.json({ message: `updated ${id}`, body: req.body });
});
app.patch('/users/:id', (req, res) => {
const { id } = req.params;
res.json({ message: `patched ${id}`, body: req.body });
});
app.delete('/users/:id', (req, res) => {
const { id } = req.params;
res.json({ message: `deleted ${id}` });
});
app.all('/secret', (req, res) => res.send('Secret'));
Route parameters & query
app.get('/users/:id', (req, res) => {
res.send(`User id: ${req.params.id}`);
});
app.get('/users/:userId/posts/:postId', (req, res) => {
res.json(req.params);
});
app.get('/search', (req, res) => {
const { q, page = 1, limit = 10 } = req.query;
res.json({ q, page: parseInt(page, 10), limit: parseInt(limit, 10) });
});
Routers
// routes/users.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => res.json({ users: [] }));
router.get('/:id', (req, res) => res.json({ id: req.params.id }));
router.post('/', (req, res) => res.status(201).json({ ok: true }));
module.exports = router;
const usersRouter = require('./routes/users');
app.use('/api/users', usersRouter);
3. Middleware
function logger(req, res, next) {
console.log(`${req.method} ${req.url}`);
next();
}
app.use(logger);
app.use('/api', (req, res, next) => {
console.log('API prefix');
next();
});
Built-in
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'));
app.use('/static', express.static('public'));
Popular packages
npm install cors morgan helmet compression
const cors = require('cors');
const morgan = require('morgan');
const helmet = require('helmet');
const compression = require('compression');
app.use(cors());
app.use(morgan('dev'));
app.use(helmet());
app.use(compression());
Auth-style middleware (sketch)
function authenticate(req, res, next) {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'Token required' });
}
try {
// Replace with your JWT/session verification
req.user = verifyToken(token);
next();
} catch {
res.status(401).json({ error: 'Invalid token' });
}
}
4. REST API (in-memory CRUD)
const express = require('express');
const app = express();
app.use(express.json());
let users = [
{ id: 1, name: 'Alice', email: '[email protected]' },
{ id: 2, name: 'Bob', email: '[email protected]' }
];
let nextId = 3;
app.post('/api/users', (req, res) => {
const { name, email } = req.body;
if (!name || !email) {
return res.status(400).json({ error: 'name and email required' });
}
const user = { id: nextId++, name, email };
users.push(user);
res.status(201).json(user);
});
app.get('/api/users', (req, res) => {
const page = parseInt(req.query.page, 10) || 1;
const limit = parseInt(req.query.limit, 10) || 10;
const start = (page - 1) * limit;
const slice = users.slice(start, start + limit);
res.json({
users: slice,
total: users.length,
page,
totalPages: Math.ceil(users.length / limit)
});
});
app.get('/api/users/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
const user = users.find((u) => u.id === id);
if (!user) return res.status(404).json({ error: 'User not found' });
res.json(user);
});
app.put('/api/users/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
const { name, email } = req.body;
const idx = users.findIndex((u) => u.id === id);
if (idx === -1) return res.status(404).json({ error: 'User not found' });
users[idx] = { id, name, email };
res.json(users[idx]);
});
app.delete('/api/users/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
const idx = users.findIndex((u) => u.id === id);
if (idx === -1) return res.status(404).json({ error: 'User not found' });
users.splice(idx, 1);
res.status(204).send();
});
app.listen(3000);
HTTP status reference
| Code | Meaning | Typical use |
|---|---|---|
| 200 | OK | Successful GET/PUT |
| 201 | Created | POST created a resource |
| 204 | No Content | DELETE success |
| 400 | Bad Request | Validation failed |
| 401 | Unauthorized | Missing/invalid auth |
| 403 | Forbidden | Authenticated but not allowed |
| 404 | Not Found | Unknown route or id |
| 500 | Server Error | Unhandled exception |
5. Request and response
req.params, req.query, req.body (after parsers), req.headers, req.ip, res.send, res.json, res.status, res.redirect, res.cookie, res.render—see Express API.
6. Error handling
function asyncHandler(fn) {
return (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
}
app.get('/users/:id', asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id);
if (!user) throw new Error('Not found');
res.json(user);
}));
app.use((err, req, res, next) => {
const status = err.statusCode || 500;
res.status(status).json({
error: {
message: err.message,
...(process.env.NODE_ENV === 'development' && { stack: err.stack })
}
});
});
7. Examples in the Korean article
- Blog API — posts CRUD with query filters
- Multer — disk storage, file filter, size limits, error handling
- JWT + bcrypt — register/login sketch,
Bearermiddleware - EJS —
app.set('view engine','ejs'),res.render - Security — Helmet, CORS allowlist,
express-rate-limit, payload size limits - Production —
trust proxy, compression, morgan formats, PM2, Nginx reverse proxy
Code blocks match the original post; translate user-visible strings to English in your app.
8. Common issues
Headers already sent
Always return after sending an error response:
app.get('/users/:id', (req, res) => {
const user = users.find((u) => u.id === +req.params.id);
if (!user) return res.status(404).json({ error: 'Not found' });
res.json(user);
});
Middleware order
Register express.json() before routes that read req.body.
Missing next()
If a middleware does not end the response, it must call next().
Summary
Express gives you routing, middleware, and a thin layer over Node’s HTTP server—pair it with solid validation, auth, and error handling for production.
Next steps
- [File system (
fs)](/en/blog/nodejs-series-05-filesystem/ - Database integration
- Auth and security
Resources
Related posts
- TypeScript REST API project
- [Getting started with Node.js](/en/blog/nodejs-series-01-intro/
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. Express REST API tutorial: routes, JSON body parsing, middleware pipeline, CRUD APIs, error handling, and security basic… 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.
Q. 더 깊이 공부하려면?
A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- Node.js 비동기 프로그래밍 | Callback, Promise, Async/Await
- Node.js 데이터베이스 연동 | MongoDB, PostgreSQL, MySQL
- [Node.js JWT Authentication Complete Guide | bcrypt](/en/blog/nodejs-jwt-authentication-guide/
이 글에서 다루는 키워드 (관련 검색어)
Node.js, Express, REST API, Middleware, Backend, Tutorial 등으로 검색하시면 이 글이 도움이 됩니다.