์ด์ ์์ ์์ ๋ผ์ฐํฐ๋ฅผ ๋ง๋ค ๋ ์์ฒญ ๋ฉ์๋์ ์ฃผ์๋ณ๋ก ๋ถ๊ธฐ ์ฒ๋ฆฌ๋ฅด ํ๋๋ผ ์ฝ๋๊ฐ ๋งค์ฐ ๋ณต์กํ๋ค. if ๋ฌธ์ผ๋ก ๋ถ๊ธฐํ์ฌ ์ฝ๋ฉํ์ฌ ๋ณด๊ธฐ์๋ ์ข์ง ์๊ณ ํ์ฅํ๊ธฐ๋ ์ด๋ ค์ ๋ค. ์ต์คํ๋ ์ค๋ฅผ ์ฌ์ฉํ๋ ์ด์ ์ค ํ๋๊ฐ ๋ฐ๋ก ๋ผ์ฐํ ์ ๊น๋ํ๊ฒ ๊ด๋ฆฌํ ์ ์๋ค๋ ์ ๋๋ฌธ์ด๋ค.
app.js์ ๋ผ์ฐํฐ ๋ถ๋ถ์ ์ดํด๋ณด์.
์ต์คํ๋ ์ค ์ฑ๊ณผ๋ app.use('/', indexRouter)์ app.use('/users', userRouter)๋ก ์ฐ๊ฒฐ๋์ด ์๋ค. app.use๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ๋ผ์ฐํฐ๋ ์ผ์ข ์ ๋ฏธ๋ค์จ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค. ๋ค๋ฅธ ๋ฏธ๋ค์จ์ด์๋ ๋ค๋ฅด๊ฒ ์์ ์ฃผ์๊ฐ ๋ถ์ด์๋ค. ์ด์ ๊ฐ์ด ๋ผ์ฐํ ๋ฏธ๋ค์จ์ด๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ฃผ์๋ฅผ ๋ฐ์์ ํน์ ์ฃผ์์ ํด๋นํ๋ ์์ฒญ์ด ์์ ๋๋ง ๋ฏธ๋ค์จ์ด๊ฐ ๋์ํ๊ฒ ํ ์๋ ์๋ค. ์ฃผ์๊ฐ /๋ก ์์ํ๋ฉด routes/index.js๋ฅผ, /users๋ก ์์ํ๋ฉด routes/users.js๋ฅผ ํธ์ถํ๋ผ๋ ์๋ฏธ์ด๋ค.
use ๋์ get, post, put, patch, delete ๊ฐ์ HTTP ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์๋ ์๋ค.
app.use('/', function(req, res, next) {
console.log('/ ์ฃผ์์ ์์ฒญ์ผ ๋ ์คํ๋ฉ๋๋ค. HTTP ๋ฉ์๋๋ ์๊ด ์์ต๋๋ค.');
next();
});
app.get('/', function(req, res, next) {
console.log('GET ๋ฉ์๋ / ์ฃผ์์ ์์ฒญ์ผ ๋๋ง ์คํ๋ฉ๋๋ค.');
next();
});
app.post('/data', function(req, res, next) {
console.log('POST ๋ฉ์๋ /data ์ฃผ์์ ์์ฒญ์ผ ๋๋ง ์คํ๋ฉ๋๋ค.');
next();
});
use ๋ฉ์๋๋ ๋ชจ๋ HTTP ๋ฉ์๋์ ๋ํด ์์ฒญ ์ฃผ์๋ง ์ผ์นํ๋ฉด ์คํ๋์ง๋ฐ, get, post, put, patch, delete ๊ฐ์ ๋ฉ์๋๋ ์ฃผ์ ๋ฟ๋ง ์๋๋ผ HTTP ๋ฉ์๋๊น์ง ์ผ์นํ๋ ์์ฒญ์ผ ๋๋ง ์คํ๋๋ค.
์ด์ ๋ผ์ฐํฐ๋ฅผ ์ดํด๋ณด์. ๋ผ์ฐํฐ ํ์ผ๋ค์ routes ํด๋์ ๋ค์ด ์๋ค. index์ users ๋ผ์ฐํฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
router ๊ฐ์ฒด๋ express.Router()๋ก ๋ง๋ค์๋ค. ๋ง์ง๋ง์๋ module.exports = router;๋ก ๋ผ์ฐํฐ๋ฅผ ๋ชจ๋๋ก ๋ง๋ ๋ค. router์๋ app์ฒ๋ผ use, get, post, put, patch, delete ๊ฐ์ ๋ฉ์๋๋ฅผ ๋ถ์ผ ์ ์๋ค. use๋ฅผ ์ ์ธํ๊ณ ๋ ๊ฐ๊ฐ HTTP ์์ฒญ ๋ฉ์๋์ ์์ํ๋ค.
๋ํ, app.use์ฒ๋ผ router ํ๋์ ๋ฏธ๋ค์จ์ด๋ฅผ ์ฌ๋ฌ ๊ฐ ์ฅ์ฐฉํ ์๋ ์๋ค. ์ค์ ๋ผ์ฐํฐ ๋ก์ง์ด ์คํ๋๋ ๋ฏธ๋ค์จ์ด ์ ์ ๋ก๊ทธ์ธ ์ฌ๋ถ ๋๋ ๊ด๋ฆฌ์ ์ฌ๋ถ๋ฅผ ์ฒดํฌํ๋ ๋ฏธ๋ค์จ์ด๋ฅผ ์ค๊ฐ์ ๋ฃ์ด๋๊ณค ํ๋ค. ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ด ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ด๋ค.
router.get('/', middleware1, middleware2, middleware3);
๋ค์ ์ฝ๋ ์ค๋ช ์ผ๋ก ๋์๊ฐ์, router.get('/')์ด๋ฉด / ์ฃผ์๋ก GET ์์ฒญ์ ํ๋ ๊ฒ๊ณผ ๊ฐ๋ค. res.render ๋ฉ์๋๋ก ํด๋ผ์ด์ธํธ์ ์๋ต์ ๋ณด๋ธ๋ค. ์ต์คํ๋ ์ค๊ฐ ์๋ต ๊ฐ์ฒด์ ์๋ก ์ถ๊ฐํ ๋ฉ์๋์ด๋ค. ์ด ๋ฉ์๋๋ ํ ํ๋ฆฟ ์์ง์ ์ฌ์ฉํ๋ ๋ถ๋ถ์ด๋ค.
users.js์์๋ router.get('/') ๋ถ๋ถ์ด ์๋ค. app.js์์ app.use('/users', usersRouter)๋ก ์ฐ๊ฒฐํ๊ธฐ ๋๋ฌธ์ /users์ /์ด ํฉ์ณ์ ธ /users/๋ก GET ์์ฒญ์ ํ์ ๋ ์ด ๋ผ์ฐํฐ์ ์ฝ๋ฐฑ ํจ์๊ฐ ์คํ๋๋ค.
์ฌ์ค ๋ผ์ฐํฐ(express.Router())๋ฅผ ์ฌ์ฉํ ํ์ ์์ด app.js์์ app.get('/', ๋ฏธ๋ค์จ์ด), app.get('/users', ๋ฏธ๋ค์จ์ด)๋ฅผ ํด๋ ๊ธฐ๋ฅ์ ๋์ผํ๋ค. ํ์ง๋ง ์ฝ๋ ๊ด๋ฆฌ๋ฅผ ์ํด ๋ผ์ฐํฐ๋ฅผ ๋ณ๋๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ด๋ค.
๋ผ์ฐํฐ์์๋ ๋ฐ๋์ ์์ฒญ์ ๋ํ ์๋ต์ ๋ณด๋ด๊ฑฐ๋ ์๋ฌ ํธ๋ค๋ฌ๋ก ์์ฒญ์ ๋๊ฒจ์ผ ํ๋ค. ์๋ต์ ๋ณด๋ด์ง ์์ผ๋ฉด ๋ธ๋ผ์ฐ์ ๋ ๊ณ์ ์๋ต์ ๊ธฐ๋ค๋ฆฐ๋ค. ์๋ต์ ์ ํ ์๊ฐ์ด ์์ผ๋ฏ๋ก ์์ํ ๊ธฐ๋ค๋ฆฌ์ง๋ ์์ง๋ง, ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋ค๋ฅธ ๋์์ ์ํํ ์ ์์ ์๋ ์๋ค. res ๊ฐ์ฒด์ ๋ค์ด ์๋ ๋ฉ์๋๋ค๋ก ์๋ต์ ๋ณด๋ธ๋ค.
next ํจ์์๋ ๋ผ์ฐํฐ์์๋ง ๋์ํ๋ ํน์ ๊ธฐ๋ฅ์ด ์๋ค. next('route')์ด๋ค. ๋ผ์ฐํฐ์ ์ฐ๊ฒฐ๋ ๋๋จธ์ง ๋ฏธ๋ค์จ์ด๋ค์ ๊ฑด๋๋ฐ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ค.
router.get('/', function(req, res, next) {
next('route');
}, function(req, res, next) {
console.log('์คํ๋์ง ์์ต๋๋ค.');
next();
}, function(req, res, next) {
console.log('์คํ๋์ง ์์ต๋๋ค.');
next();
});
router.get('/', function(req, res) {
console.log('์คํ๋ฉ๋๋ค.');
res.render('index', { title: 'Express' });
});
๊ฐ์ ์ฃผ์์ ๋ผ์ฐํฐ๋ฅผ ๋ ๊ฐ ๋ง๋ค์๋ค. ์ฒซ ๋ฒ์งธ ๋ผ์ฐํฐ์ ์ฒซ ๋ฒ์งธ ๋ฏธ๋ค์จ์ด์์ next('route')๋ฅผ ํธ์ถํ์ ๋ ๋ฒ์งธ, ์ธ ๋ฒ์งธ ๋ฏธ๋ค์จ์ด๋ ์คํ๋์ง ์๋๋ค. ๋์ ์ฃผ์์ ์ผ์นํ๋ ๋ค์ ๋ผ์ฐํฐ๋ก ๋์ด๊ฐ๋ค.
์ ์ฉํ ํ์ด ํ๋ ๋ ์๋ค. ๋ผ์ฐํฐ ์ฃผ์์๋ ํน์ํ ํจํด์ ์ฌ์ฉํ ์ ์๋ค. ์ฌ๋ฌ ๊ฐ์ง ํจํด์ด ์์ง๋ง, ์์ฃผ ์ฐ์ด๋ ํจํด ํ๋๋ง ์์๋ณด์.
router.get('/users/:id', function(req, res) {
console.log(req.params, req.query);
});
์ฃผ์์ :id๊ฐ ์๋๋ฐ, ๋ฌธ์ ๊ทธ๋๋ก :id๋ฅผ ์๋ฏธํ๋ ๊ฒ์ด ์๋๋ค. ์ด ๋ถ๋ถ์๋ ๋ค๋ฅธ ๊ฐ์ ๋ฃ์ ์ ์๋ค. /users/1์ด๋ /users/123 ๋ฑ์ ์์ฒญ๋ ์ด ๋ผ์ฐํฐ์ ๊ฑธ๋ฆฐ๋ค. ์ด ๋ฐฉ์์ ์ฅ์ ์ :id์ ํด๋นํ๋ 1์ด๋ 123์ ์กฐํํ ์ ์๋ค๋ ์ ์ด๋ค. req.params ๊ฐ์ฒด ์์ ๋ค์ด ์๋ค. :id๋ฉด req.params.id๋ก, :type์ด๋ฉด rea.params.type์ผ๋ก ์กฐํํ ์ ์๋ค.
์ฃผ์์ ์ฟผ๋ฆฌ์คํธ๋ง์ ์ธ ๋๋ ์๋ค. ์ฟผ๋ฆฌ์คํธ๋ง์ ํค-๊ฐ ์ ๋ณด๋ req.query ๊ฐ์ฒด ์์ ๋ค์ด ์๋ค.
์๋ฅผ ๋ค์ด, /users/123?limit=5&skip=10์ด๋ผ๋ ์ฃผ์์ ์์ฒญ์ด ๋ค์ด์์ ๋ req.params์ req.query ๊ฐ์ฒด๋ ๋ค์๊ณผ ๊ฐ๋ค.
{ id: '123' } { limit: '5', skip: '10' }
์์ฒญ ์ฃผ์์ ๋ํ ์ ๋ณด๊ฐ ๋ด๊ฒจ ์์ด ์๊ธดํ๊ฒ ํ์ฉํ ์ ์๋ค. ๋จ, ์ด ํจํด์ ์ฌ์ฉํ ๋ ์ฃผ์ํ ์ ์ด ์๋ค. ์ผ๋ฐ ๋ผ์ฐํฐ๋ณด๋ค ๋ค์ ์์นํด์ผ ํ๋ค๋ ๊ฒ์ด๋ค. ๋ค์ํ ๋ผ์ฐํฐ๋ฅผ ์์ฐ๋ฅด๋ ์์ผ๋์นด๋ ์ญํ ์ ํ๋ฏ๋ก ์ผ๋ฐ ๋ผ์ฐํฐ๋ณด๋ค๋ ๋ค์ ์์นํด์ผ ๋ค๋ฅธ ๋ผ์ฐํฐ๋ฅผ ๋ฐฉํดํ์ง ์๋๋ค.
์๋ฌ๊ฐ ๋ฐ์ํ์ง ์์๋ค๋ฉด ๋ผ์ฐํฐ๋ ์์ฒญ์ ๋ณด๋ธ ํด๋ผ์ด์ธํธ์๊ฒ ์๋ต์ ๋ณด๋ด์ฃผ์ด์ผ ํ๋ค.
send๋ ๋ง๋ฅ ๋ฉ์๋์ด๋ค. ๋ฒํผ ๋ฐ์ดํฐ๋ ๋ฌธ์์ด์ ์ ์กํ๊ฑฐ๋, HTML ์ฝ๋๋ฅผ ์ ์กํ๊ธฐ๋ ํ๊ณ , JSON ๋ฐ์ดํฐ๋ ์ ์กํ ์ ์๋ค. sendFile์ ํ์ผ์ ์๋ต์ผ๋ก ๋ณด๋ด์ฃผ๋ ๋ฉ์๋๊ณ , json์ JSON ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด์ค๋ค. redirect๋ ์๋ต์ ๋ค๋ฅธ ๋ผ์ฐํฐ๋ก ๋ณด๋ด๋ฒ๋ฆฐ๋ค. ์๋ฅผ ๋ค์ด, ๋ก๊ทธ์ธ ์๋ฃ ํ ๋ค์ ๋ฉ์ธ ํ๋ฉด์ผ๋ก ๋์๊ฐ ๋ res.redirect(๋ฉ์ธ ํ๋ฉด ์ฃผ์)๋ฅผ ํ๋ฉด ๋๋ค.
res.send(๋ฒํผ ๋๋ ๋ฌธ์์ด ๋๋ HTML ๋๋ JSON);
res.sendFile(ํ์ผ ๊ฒฝ๋ก);
res.json(JSON ๋ฐ์ดํฐ);
res.redirect(์ฃผ์);
res.render('ํ
ํ๋ฆฟ ํ์ผ ๊ฒฝ๋ก', { ๋ณ์ });
๊ธฐ๋ณธ์ ์ผ๋ก๋ 200 HTTP ์ํ ๋ณด๋๋ฅผ ์๋ตํ์ง๋ง (res.redirect๋ 302), ์ง์ ๋ฐ๊ฟ์ค ์๋ ์๋ค. ๋ค์๊ณผ ๊ฐ์ด status ๋ฉ์๋๋ฅผ ๋จผ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
res.status(404).send('Not Found');
render ๋ฉ์๋๋ ํ ํ๋ฆฟ ์์ง์ ๋ ๋๋งํ ๋ ์ฌ์ฉ๋๋ค. views ํด๋ ์ pug ํ์ฅ์๋ฅผ ๊ฐ์ง๊ณ ์๋ ํ์ผ๋ค์ด ํ ํ๋ฆฟ ์์ง์ด๋ค.
๋ง์ง๋ง์ผ๋ก ๋ผ์ฐํฐ๊ฐ ์์ฒญ์ ์ฒ๋ฆฌํ์ง ๋ชปํ ๋ ์ด๋ค ์ผ๋ค์ด ๋ฐ์ํ๋์ง ์์๋ณด์. ์์ฒญ์ ์ฒ๋ฆฌํ ์ ์๋ ๋ผ์ฐํฐ๊ฐ ์๋ค๋ฉด ๋ค์ ๋ฏธ๋ค์จ์ด๋ก ๋์ด๊ฐ๋ค. 404 HTTP ์ํ ์ฝ๋๋ฅผ ๋ณด๋ด์ฃผ์ด์ผ ํ๋ฏ๋ก ๋ค์ ๋ฏธ๋ค์จ์ด์์ ์๋ก์ด ์๋ฌ๋ฅผ ๋ง๋ค๊ณ ์๋ฌ์ ์ํ์ฝ๋๋ฅผ 404๋ก ์ค์ ํ ๋ค ์๋ฌ ์ฒ๋ฆฌ ๋ฏธ๋ค์จ์ด๋ก ๋๊ฒจ ๋ฒ๋ฆฐ๋ค.
...
//404 ์ฒ๋ฆฌ ๋ฏธ๋ค์จ์ด
app.use(function(req, res, next) {
next(createError(404));
});
// ์๋ฌ ํธ๋ค๋ฌ
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
...l