[35] Sequelize, cookie, session을 이용한 회원가입 + 로그인 + 게시판 예제(2)

minjeong·2024년 2월 16일
0
post-thumbnail

1. controller/post.js

  • controller 폴더는 model 즉, DB의 내용을 가지고 와서 보여주기 위함이다. 게시글을 올리고 확인하는 코드를 짜보았다.
  • 중간중간 주석처리 되어있는건 밑에 있는 코드보다 효율적이지 못해서 비교차 냅뒀다.
const { Post, Comment } = require('../models');

//전체글 조회
exports.all = async (req, res) => {
    // Post.findAll().then((result) => {
    //     console.log('all', result);
    // });
    const result = await Post.findAll({ order: [['id', 'desc']] });
    console.log('all', result);
    res.json({ success: true, result });
};
//하나 조회
exports.post = async (req, res) => {
    console.log(req.params.id);
    //const result = await Post.findOne({ where: { id: req.params.id } });
    // include: [{ model: Comment }] == include: Comment 는 동일 결과
    // include: 쿼리를 실행할때 관련된 모델의 데이터도 함께 조회할 수 있도록 하는 옵션
    const result = await Post.findByPk(req.params.id, { include: [{ model: Comment }] }); //해당 아이디를 가지고 있는 Post 모델과 관련된 comment까지 가져오게 한다.
    res.json({ success: true, result });
};
//하나 생성
exports.write = async (req, res) => {
    const { title, content } = req.body;
    const result = await Post.create({
        title,
        content,
    });
    console.log('write', result);
    res.json({ success: true, result: result.id });
};
//하나 수정
exports.update = async (req, res) => {
    const { id, title, content } = req.body;
    const result = await Post.update(
        {
            title,
            content,
        },
        { where: { id } }
    );
    console.log('update', result);
    res.json({ success: true });
};
//하나 삭제
exports.delete = async (req, res) => {
    const result = await Post.destroy({ where: { id: req.body.id } });
    console.log('delete', result);
    res.json({ success: true });
};

//댓글 작성
exports.comment = async (req, res) => {
    const { id, content } = req.body;
    const result = await Comment.create({ content, postId: id });
    console.log('comment', result);
    res.json({ success: true });
};

2. models/comment.js

// const { DataTypes } = require('sequelize');

const CommentModel = (sequelize, DataTypes) => { // 두개의 매개변수를 받음
    return sequelize.define('comment', { //comment라는 이름의 새로운 모델(데이터베이스의 테이블)을 정의함
        content: DataTypes.TEXT('medium'),
    });
};

module.exports = CommentModel;
  • content: DataTypes.TEXT('medium') : content라는 이름의 필드를 정의하고, 그 타입으로 medium 크기의 TEXT 타입을 지정한다.
    이 필드는 Comment 모델의 인스턴스가 가질 수 있는 속성 중 하나이다.

3. models/index.js

테이블끼리도 서로 relationship을 맺을 수 있다.

'use strict';

const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.js')[env];
const db = {};

let sequelize = new Sequelize(config.database, config.username, config.password, config); //인스턴스를 생성해서 데이터베이스와 연결함

// 각 모델을 가져와서 Sequelize 인스턴스를 통해 초기화하고, 이를 db 객체에 할당
db.Post = require('./post')(sequelize);
db.Member = require('./member')(sequelize);
db.Profile = require('./profile')(sequelize);
db.Comment = require('./comment')(sequelize, Sequelize);

//1:1
db.Member.hasOne(db.Profile, { foreignKey: 'memberId', onDelete: 'CASCADE' }); //foreignKey: 'memberId': Profile 모델에서 참조하는 외래 키
db.Profile.belongsTo(db.Member, { foreignKey: 'memberId', onDelete: 'CASCADE' });

//1:다
db.Post.hasMany(db.Comment);
db.Comment.belongsTo(db.Post);

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;
  • 이번엔 테이블끼리 서로 relationship 해보았다.
  • db.Member.hasOne(db.Profile, { foreignKey: 'memberId', onDelete: 'CASCADE' }); : Member와 Profile 모델 사이에 1:1 관계를 정의한다. 이 관계는 Member가 Profile을 가지고 있음을 의미하며, memberId라는 외래 키를 통해 연결된다. CASCADE 옵션은 Member가 삭제되면 관련된 Profile도 함께 삭제됨을 의미한다.
  • db.Post.hasMany(db.Comment); : Post와 Comment 모델 사이에 1:다 관계를 정의한다. 이 관계는 하나의 Post가 여러 Comment를 가질 수 있음을 의미한다.

4. routes/post.js

const express = require('express');
const controller = require('../controller/post');

const router = express.Router();

//미들웨어
const isAuth = (req, res, next) => {
    //각 요청이 인증된 사용자에 의해 만들어졌는지 확인
    //next(): express미들웨어에서 다음 미들웨어로 제어를 전달하는 역할
    if (req.session && req.session.member) {
        next(); //이거로 인해 해당 조건을 만족하면 다음 미들웨어로 전달
    } else {
        res.status(401).json({ success: false, message: '인증되지 않는 사용자입니다' }); // 해당하지 않으면 오류메시지
    }
};

//GET /all 전체글 조회
router.get('/all', isAuth, controller.all);
//GET /post/:id 게시판글 하나 조회
router.get('/:id', isAuth, controller.post);
//POST /write 게시판 글 하나 생성
router.post('/write', isAuth, controller.write);
//PATCH /update 게시판 글 하나 수정
router.patch('/update', isAuth, controller.update);
//DELETE /delete 게시판 글 하나 삭제
router.delete('/delete', isAuth, controller.delete);
//POST /comment 댓글 생성
router.post('/comment', isAuth, controller.comment);

module.exports = router;

➡️ 미들웨어를 통해 인증되지 않은 사용자가 접근하지 못하도록 제한을 걸 수 있다.

📌📌 deleteFunc 사용시 주의할점

  • delete는 실수할 수 있는 사용자들을 위해 한번 더 물어보는 장치가 필요하다.
  • confirm 이다.
  • 말그대로 확인하는 역할이다.
async function deleteFunc() {
                if (!confirm('삭제하시겠습니까?')) {
                    return;
                }
                const res = await axios({
                    method: 'DELETE',
                    url: '/api/post/delete',
                    data: {
                        id: document.querySelector('#index').value,
                    },
                });
                if (res.data.success) {
                    document.location.href = '/post';
                }
            }

➡️ DELETE 페이지에서 주로 쓰이고, 예시처럼 한번 더 물어봐주는 장치를 만드는 것이 좋다.


마무리

쉽지는 않지만, 이 틀을 이해하고 여러번 반복하다보면 여러 곳에서 활용할 수 있을 것 같다. node.js..재밌다!
더 많은 내용을 배울수록 자료구조의 내용을 놓칠 수 없을 것 같아서 관련 책을 샀다. 책을 읽으면서 두고두고 봐야할 것 같은 내용은 기록할 예정이다.

profile
중요한 건 꺾여도 다시 일어서는 마음

0개의 댓글