Structuring backend applications
Seoul National University of Science and Technology
Information Technology Management
Lecture slides index
May 8, 2026
app.jsArchitectural pattern that organizes an application around three roles:
Model:
View:
Controller:
Responsibility boundaries:

Typical execution flow of an incoming request:
GET /flights)
/flights/:id?/flights?origin=Seoul:param and accessed through req.paramsGET /flights/42req.params: { "id": "42" }? in the URLreq.queryGET /flights?origin=Seoul&destination=Tokyoreq.query: { "origin": "Seoul", "destination": "Tokyo" }req.bodyapp.use(express.json())| Method | Purpose |
|---|---|
res.send() |
Sends a response body (text or data) |
res.json() |
Sends a JSON response and sets the content type |
res.status(code) |
Sets the HTTP status code |
Status codes communicate the outcome of request processing
400 — invalid input or missing parameters404 — resource not found401 / 403 — authentication or authorization failures500 — unexpected failure in application logic
res.status() with a JSON error bodyreq, res, and next as parametersnext()app.use(...)express.json()req.bodyexpress.urlencoded({ extended: true })(err, req, res, next)app.js — application configuration and initializationroutes/ — endpoint definitionscontrollers/ — request-handling logicmodels/ — data representation and accessEach documented endpoint specifies:
Path and method:
GET /flights/:idParameters:
Request body:
Responses:

app.jsPOST /flights and DELETE /flights/:idapp.jsGET /flights and GET /flights/:idapp.jsreq or res// models/flightsModel.js
let flights = [
{ id: 1, origin: "Seoul", destination: "Tokyo", date: "2026-06-01" },
{ id: 2, origin: "Seoul", destination: "Osaka", date: "2026-06-03" }
];
function findAll() { return flights; }
function findById(id) { return flights.find(f => f.id === id); }
function create(flight) { /* ... */ }
function remove(id) { /* ... */ }
module.exports = { findAll, findById, create, remove };module.exports
{ findAll, findById, create, remove } exposes those four functions; any file that requires this module receives exactly that object.// controllers/flightsController.js
const model = require("../models/flightsModel");
function getAll(req, res) {
res.status(200).json(model.findAll());
}
function getById(req, res) {
const id = Number(req.params.id);
const flight = model.findById(id);
if (!flight) return res.status(404).json({ error: "Flight not found" });
res.status(200).json(flight);
}
module.exports = { getAll, getById };require
"../models/flightsModel" goes up one folder (from controllers/ to the project root), then enters models/ and loads flightsModel.js.model and used as model.findAll(), model.findById(id), etc.Router to encapsulate route definitionsapp.jsapp.js becomes a configuration entry pointPOST /flights// controllers/flightsController.js
function create(req, res) {
const { origin, destination, date } = req.body;
if (!origin || !destination || !date) {
return res.status(400).json({ error: "Missing required fields" });
}
const newFlight = model.create({ origin, destination, date });
res.status(201).json(newFlight);
}
Why 201 Created?
201 indicates that the request was successful and a new resource was created as a result.POST that creates a resource, and the response body typically contains the newly created resource (including its assigned id).DELETE /flights/:id404 if the flight does not exist
Why 204 No Content?
204 indicates the request was processed successfully and there is no content to return in the response body.DELETE, since the resource no longer exists and there is nothing meaningful to send back.swagger-ui-express — serves the interactive UIyamljs — loads the OpenAPI specification from a YAML fileapp.js:http://localhost:8080/api-docsGET /flights — list of flights, status 200GET /flights/:id — single flight or 404POST /flights — create a flight, status 201DELETE /flights/:id — remove a flight, status 204 or 404
Web Programming