본문 바로가기
STUDY/Project

게시판 로직 - Post, postController, postRoutes

by Y.Choi 2025. 4. 30.
728x90
반응형

 

| Post 모델 스키마 정의

 

backend/models/Post.js

// backend/models/Post.js

const mongoose = require('mongoose');

const postSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true,
  },
  content: {
    type: String,
    required: true,
  },
  author: {
    type: mongoose.Schema.Types.ObjectId, // 유저 참조
    ref: 'User',
    required: true,
  }
}, { timestamps: true }); // createdAt, updatedAt 자동 생성

module.exports = mongoose.model('Post', postSchema);

 

- author: { ref: 'User' } : User 모델과 연결한다.

 

 

 

| 글작성, 목록, 특정글조회 컨트롤러

 

backend/controllers/postController.js

// backend/controllers/postController.js

const Post = require('../models/Post');

// 글 작성
exports.createPost = async (req, res) => {
  try {
    const { title, content } = req.body;

    const post = await Post.create({
      title,
      content,
      author: req.user.id  // authMiddleware 통해 주입된 사용자
    });

    res.status(201).json(post);
  } catch (error) {
    res.status(400).json({ message: '게시글 작성 오류', error: error.message });
  }
};

// 글 전체 목록
exports.getPosts = async (req, res) => {
  try {
    const posts = await Post.find().populate('author', 'username');
    res.json(posts);
  } catch (error) {
    res.status(500).json({ message: '게시글 불러오기 오류', error: error.message });
  }
};

// 특정 글 조회
exports.getPostById = async (req, res) => {
  try {
    const post = await Post.findById(req.params.id).populate('author', 'username');
    if (!post) {
      return res.status(404).json({ message: '게시글 없음' });
    }
    res.json(post);
  } catch (error) {
    res.status(500).json({ message: '게시글 조회 오류', error: error.message });
  }
};

 

/ createPost -- req.user.id

- req.user 는 authMiddleware에서 설정된 사용자 정보이다. 

- id는 로그인한 유저의 ID로 글 작성을 하게 한다.

 

/ populate -- .populate('author', 'username')

- author 필드에 연결된 유저 정보 중에 username만 가져온다.

 

 

 

| 라우터 연결

 

backend/routes/postRoutes.js

// backend/routes/postRoutes.js

const express = require('express');
const router = express.Router();
const postController = require('../controllers/postController');
const protect = require('../middleware/authMiddleware');

// 라우터 설정
router.post('/', protect, postController.createPost);      // 글 작성
router.get('/', postController.getPosts);                  // 전체 글 조회
router.get('/:id', postController.getPostById);            // 특정 글 조회

module.exports = router;

 

/ protect : 미들웨어로 로그인 여부를 확인하고 로그인된 사용자만 글을 작성할 수 있게 한다.

 

 

 

| 사용자 확인을 위한 미들웨어

 

backend/middleware/authMiddleware.js

// backend/middleware/authMiddleware.js

const jwt = require('jsonwebtoken');
const User = require('../models/User');

const protect = async (req, res, next) => {
  let token;

  if (req.headers.authorization?.startsWith('Bearer')) {
    try {
      token = req.headers.authorization.split(' ')[1];
      const decoded = jwt.verify(token, process.env.JWT_SECRET);

      req.user = await User.findById(decoded.id).select('-password');
      next();
    } catch (error) {
      res.status(401).json({ message: '토큰 인증 실패', error: error.message });
    }
  } else {
    res.status(401).json({ message: '토큰이 없습니다' });
  }
};

module.exports = protect;

 

이 미들웨어에 대한 자세한 설명은 여기에서 확인.

 

 

| 테스트

 

Thunder Client에서 위에서 작업한 기능들을 테스트한다.

 

 

POST http://localhost:5000/api/auth/register → 회원가입

POST http://localhost:5000/api/auth/login → 토큰 확인

POST http://localhost:5000/api/posts

          Headers: Authorization: Bearer {토큰}

          Body: { "title": "제목", "content": "내용" }

GET http://localhost:5000/api/posts

GET http://localhost:5000/api/posts/:id

 

 

728x90
반응형