서버 개발을 하다보면 코드의 특성별로 소스 파일을 나누게 되어있어요.
Node도 마찬가지에요.
처음에 잘 구조를 잡아두면 유지보수할 때 큰 이득을 볼 수 있어요.
구조만 잘 잡아줘도 Node에서도 충분히 복잡한 비즈니스를 말끔하게 볼 수 있습니다.
반대로 매우 간단한 로직을 나눠버리면 비효율적인 작업이 될 수도 있으니 잘 판단해서 디자인해야되요.
우선, 기본으로 사용할 수 있는 Routes-Controllers-Services 구조로 게시판 CRUD 예제를 구현해볼게요.
board-route
var express = require('express')
var router = express.Router()
const BoardController = require('../controllers/board-controller')
router.get('/:boardId', BoardController.getBoard)
router.get('/', BoardController.getBoards)
router.post('/', BoardController.insertBoard)
router.patch('/:boardId', BoardController.updateBoard)
router.delete('/:boardId', BoardController.deleteBoard)
router.get('/:boardId/comment', BoardController.getComments)
router.post('/:boardId/comment', BoardController.insertComment)
router.patch('/:boardId/comment/:commentId', BoardController.updateComment)
router.delete('/:boardId/comment/:commentId', BoardController.deleteComment)
module.exports = router
board-controller
const BoardService = require('../services/board-service')
exports.getBoard = async (req, res, next) => {
let { boardId } = req.params
try {
let rows = await BoardService.getBoard(boardId)
return res.json(rows[0])
} catch (err) {
return res.status(500).json(err)
}
}
// 생략...
exports.deleteComment = async (req, res, next) => {
let { boardId, commentId } = req.params
try {
let del = await BoardService.deleteComment(boardId, commentId)
return res.json(del)
} catch (err) {
return res.status(500).json(err)
}
}
board-service
const pool = require('../database/pool')
const BoardQuery = require('../queries/board-query')
exports.getBoard = async (boardId) => {
try {
let data = await pool.query(BoardQuery.getBoard, [boardId])
return data[0]
} catch (err) {
console.log(err)
throw Error(err)
}
}
// 생략...
exports.deleteComment = async (boardId, commentId) => {
let conn = await pool.getConnection()
try {
await conn.beginTransaction()
let del = await conn.query(BoardQuery.deleteComment, [commentId])
if (del[0].affectedRows == 1) {
let upd = await conn.query(BoardQuery.minusCommentCnt, [boardId])
}
await conn.commit()
return del[0]
} catch (err) {
conn.rollback()
console.log(err)
throw Error(err)
} finally {
conn.release()
}
}
board-query
exports.getBoard = 'select board_id, title, content from board where board_id = ?'
exports.getBoards = 'select board_id, title from board limit ?, ?'
exports.insertBoard = 'insert into board set ?'
exports.updateBoard = 'update board set title = ?, content = ?, upd_dt = now() where board_id = ?'
exports.deleteBoard = 'delete from board where board_id = ?'
exports.getComments = 'select board_id, title, content from board where board_id = ?'
exports.insertComment = 'insert into board set ?'
exports.plusCommentCnt = 'update board set comment_cnt = comment_cnt + 1 where board_id = ?'
exports.updateComment = 'update board_comment set content = ?, upd_dt = now() where comment_id = ?'
exports.deleteComment = 'select board_id, title, content from board where board_id = ?'
exports.minusCommentCnt = 'update board set comment_cnt = comment_cnt - 1 where board_id = ?'
mysql2 모듈을 이용하여 쿼리를 직접 작성/호출하는 방식이여서 쿼리를 별도로 관리해야 해요. (안그럼 후회해요.)
중복 쿼리를 작성할 확률도 줄어들고 굉장히 긴 쿼리를 작성하는 경우에 이점이 있어요.
sql 작성이 아닌 ORM을 사용하면 Queries를 작성할 필요 없이 Models를 관리하게 되요.
자연스럽게 Models-Routes-Controllers-Services 구조로 잡으면 됩니다.
위와 같이 소개 드렸지만 개인적으로 JavaScript와는 맞지 않은 것 같아 전 따라가지 않는 편입니다.
JavaScript 언어 자체가 자유도나 유연성이 높아서 직접 연구해보시는 것이 더 좋은 것 같아요!
'Backend > Node.js' 카테고리의 다른 글
Node.js 파라미터 전달 (Param, Path, Body, Header) (0) | 2020.04.09 |
---|---|
Node.js 재시작 없이 반영, 자동 재시작 (Supervisor) (0) | 2020.04.01 |
Node.js MySQL Transaction(트랜잭션) (6) | 2019.11.13 |
Node.js MySQL 연동 (Express) (0) | 2019.11.11 |
Node.js Express 설치 (express-generator) (0) | 2019.10.10 |