본문으로 건너뛰기
Previous
Next
Express REST API Tutorial for Node.js | Routing

Express REST API Tutorial for Node.js | Routing

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'));
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

CodeMeaningTypical use
200OKSuccessful GET/PUT
201CreatedPOST created a resource
204No ContentDELETE success
400Bad RequestValidation failed
401UnauthorizedMissing/invalid auth
403ForbiddenAuthenticated but not allowed
404Not FoundUnknown route or id
500Server ErrorUnhandled 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, Bearer middleware
  • EJSapp.set('view engine','ejs'), res.render
  • Security — Helmet, CORS allowlist, express-rate-limit, payload size limits
  • Productiontrust 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

Resources



자주 묻는 질문 (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, Express, REST API, Middleware, Backend, Tutorial 등으로 검색하시면 이 글이 도움이 됩니다.