리셋 되지 말자

[express] 라우터-주소체계변경 본문

NodeJS/생활코딩

[express] 라우터-주소체계변경

kyeongjun-dev 2020. 9. 24. 01:40

안되던 주소

express의 클린 url 체계 방식으로 form이나 링크 이동을 클린 url로, 즉 상세 페이지 보기에서 'localhost/page/:pageId' 로 이동하도록 했는데, 글 생성 및 update도 'localhost/page/create'와 'localhost/page/update'로 하고 싶었는데 변경하면 안되었다.

안된 이유는 미들웨어 'localhost/page/:pageId'를 처리하는데, /page/create를 입력해버리면 pageId인 상세페이지 보기로 인식하기 때문이다.

해결방법은 간단한데, '/page/create'를 처리하는 미들웨어를 '/page/:pageId'를 처리하는 미들웨어보다 위쪽에 두는 것이다. 링크의 이동하는 경로와 미들웨어의 순서를 변경하여 해결했다.

(그런데 이게, 좋은 방법일까???)

/page/update/ 동작

 

express의 라우터를 이용하기

(expressjs.com/en/guide/routing.html)페이지의 express.Router부분을 보면 사용방법이 나와있다.

모듈처럼 사용한다는거 같다. 

routes라는 디렉토리를 새로 생성한 뒤, page.js라는 파일을 만들었다. 이제 /page로 시작하는 경로를 가진 미들웨어들을 이 파일로 이주시킨다.

  • main.js 수정
var pageRouter = require('./routes/page');

우선 위에서 모듈을 선언한다. 그리고 

app.use('/page', pageRouter);

위와같이 미들웨어를 장착(?)시킨다. '/page'로 시작하는 주소들에게 pageRouter라는 미들웨어를 적요하겠다라는 뜻이다.

 

  • page.js
var express = require('express');
var router = express.Router();
var db = require('../lib/db');
var template = require('../lib/template');

router.get('/create', (req, res) => {
    db.query('SELECT * FROM topic', function (error, topics) {
        if (error) throw error;
        db.query('SELECT * FROM author', function (error2, authors) {
            if (error2) throw error2;
            var title = 'Create';
            var description = '';
            var list = template.list(topics);
            var authorOptions = '';

            authors.forEach((author) => {
                authorOptions += `<option value = ${author.id}>${author.name}</option>`;
            });
            var html = template.html(title, list, `<h2>${title}</h2><form action="/page/create_process" method='POST'>
        <p>
           <input type="text" name="title" placeholder="title">
        </p>
        <p>
            <textarea name="description" placeholder="description"></textarea>
        </p>
        <p>
            <select name="author">
                ${authorOptions};
            </select>
        </p>
        <input type="submit" value="전송">
    </form>${description}`, ``);
            res.send(html);
        });

    });
});


router.post('/create_process', (req, res) => {
    var title = req.body.title;
    var description = req.body.description;
    var authorId = req.body.author;
    db.query(`INSERT INTO topic (title, description, created, author_id) values (?, ?, now(), ?);`, [title, description, authorId], function (error, result) {
        if (error) throw error;
        res.redirect(`/page/${result.insertId}`);
    });
});

router.post('/delete_process', (req, res) => {
    db.query(`DELETE FROM topic WHERE topic.id = ?`, [req.body.id], (error, result) => {
        res.redirect('/');
    });
});

router.get('/update/:topicId', (req, res) => {
    db.query('SELECT * FROM topic', function (error1, topics) {
        if (error1) throw error1;
        db.query('SELECT * FROM topic WHERE id = ?', [req.params.topicId], function (error2, topic) {
            if (error2) throw error2;
            db.query('SELECT * FROM author', (error3, authors) => {
                var list = template.list(topics);
                var title = topic[0].title;
                var description = topic[0].description;
                var tag = template.author(authors, topic[0].author_id);
                var html = template.html(title, list, `<h2>${title}</h2>
            <form action="/page/update_process" method='POST'>
            <p>
               <input type="text" name="title" value="${title}">
            </p>
            <p>
                <textarea name="description">${description}</textarea>
            </p>
            <p>
                <input type="hidden" name="id" value="${topic[0].id}">
            </p>
            <p>
                ${tag}
            <p>
            <input type="submit" value="수정">
        </form>`, ``);
                res.send(html);
            });
        });
    });
});

router.post('/update_process', (req, res) => {
    db.query('UPDATE topic SET title=?, description=?, author_id=? where topic.id = ?', [req.body.title, req.body.description, req.body.author, req.body.id], function (error1, result) {
        if (error1) throw error1;
        res.redirect(`/page/${req.body.id}`);
    });
});

//상세 보기 페이지
router.get('/:pageId', (req, res, next) => {
    //console.log(req.params.pageId);
    db.query('SELECT * FROM topic', function (error, topics) {
        if (error) next(error);
        db.query('SELECT * FROM topic WHERE topic.id = ?', [req.params.pageId], function (error2, topic) {
            if (error2) next(error2);
            try {
                db.query('SELECT * FROM author WHERE id = ?', [topic[0].author_id], function (error3, author) {
                    if (error3) {
                        console.log('error3 occured!!');
                        next(error3);
                    }
                    else {
                        var description = topic[0].description;
                        var title = topic[0].title;
                        var list = template.list(topics);

                        var html = template.html(title, list, `<h2>${title}</h2>${description}<p>by ${author[0].name}</p>`, `<a href="/page/create">create</a>
                <a href="/page/update/${topic[0].id}">update</a>
                <form action="/page/delete_process" method="POST">
                    <input type="hidden" name="id" value="${topic[0].id}">
                    <input type="submit" value="삭제">
                </form>`);
                        res.send(html);
                    }
                });
            } catch (err) {
                if (err) {
                    console.log('err occured!!');
                    next(err);
                }
            }
        });
    });
});

module.exports = router;

위처럼 필요한 모듈들을 선언해주고, 마지막에 module.exports = router; 를 사용해서 router가 모듈로 동작호도록 한다.

여기서 중요한 것은, 'app.use('/page', pageRouter);'라고 사용할 때, 요청되는 url이 '/page'로 시작하면 pageRouter라는 미들웨어로 동작하게 하는 것이므로 page.js의 미들웨어들을 보면 '/update', '/create'등과 같이 '/page/update'가 아니다. 즉, 'localhost/page/update'로 요청이 들어오면 app.use에 지정한 '/page'가 처리되고, 그 뒤의 url인 '/update'에 해당하는 미들웨어가 page.js안에서 동작하는 것이다.

 

Home 분리하기

이제 main.js에 남은 '/'를 처리하는 page를 분리한다. (author을 안만든줄 알았는데, 있어서 author도 분리 하였음)

  • index.js
var express = require('express');
var router = express.Router();
var db = require('../lib/db');
var template = require('../lib/template');

//get은 route, routing
router.get('/', (req, res) => {
    db.query('SELECT * FROM topic', function (error, topics) {
        if (error) throw error;
        var description = 'Hello, Node.js';
        var title = 'Welcome';
        var list = template.list(topics);

        var html = template.html(title, list, `<h2>${title}</h2>${description}
        <img src="/image/profile.jpg" style="width:200px; display:block; margin-top:10px;">`, `<a href="/page/create">create</a>`);
        res.send(html);

    });
});

module.exports = router;

 

  • main.js
const express = require('express')
const app = express()
const port = 80
var compression = require('compression')
var bodyParser = require('body-parser');
var pageRouter = require('./routes/page');
var indexRouter = require('./routes/index');
var authorRouter = require('./routes/author');

app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(compression());
app.use('/page', pageRouter);
app.use('/author', authorRouter);
app.use('/',indexRouter);

app.use(function (req, res, next) {
    res.status(404).send('Sorry cant find that!');
});

app.use(function (err, req, res, next) {
    console.error(err.stack)
    res.status(500).send('Something broke!');
})

app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`)
});

라우터별로 분리하니, main.js의 코드가 매우 간결해졌다!

'NodeJS > 생활코딩' 카테고리의 다른 글

[NodeJS] 쿠키의 생성  (0) 2020.09.25
[express] 보안 - 포괄적으로 둘러보기  (0) 2020.09.24
[express] 에러 처리하기  (0) 2020.09.23
[express] 미들웨어 만들기  (0) 2020.09.23
[express] 미들웨어 - compression  (2) 2020.09.23
Comments