게시판 - Post-User 관계(relationship) 만들기

소스코드

이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실행할 수 있습니다.

이 게시물의 소스코드는 게시판 만들기 / 게시판 - Post Error 처리에서 이어집니다.

board.git 을 clone 한 적이 있는 경우: 터미널에서 해당 폴더로 이동 후 아래 명령어들을 붙여넣기합니다. 폴더 내 모든 코드가 이 게시물의 코드로 교체됩니다. 이를 원치 않으시면 이 방법을 선택하지 마세요.

git reset --hard
git pull
git reset --hard 9d00684
git reset --soft 0a4b23b
npm install
atom .

board.git 을 clone 한 적이 없는 경우: 터미널에서 코드를 다운 받을 폴더로 이동한 후 아래 명령어들을 붙여넣기하여 board.git 을 clone 합니다.

git clone https://github.com/a-mean-blogger/board.git
cd board
git reset --hard 9d00684
git reset --soft 0a4b23b
npm install
atom .

- Github에서 소스코드 보기: https://github.com/a-mean-blogger/board/tree/9d00684c3f5355a777c575e163339694978cb61e


게시물과 사용자 사이에 관계(relationship)을 만들어 봅시다. 게시물 document에 작성자 document id를 기록하여 글 작성자 정보를 알 수 있게 됩니다.

이게 왜 중요한가 하면, 로그인 기능으로 현재 사이트에 로그인 한 유저가 누군지 알 수 있게 됐고, 여기에 작성자가 기록되면 자신이 작성한 글, 다른 사람이 작성한 글의 구분이 가능해 집니다. 즉 자신의 글은 삭제가 가능/남의 글은 삭제가 불가능하게 할 수 있습니다. 이번 게시물에서는 일단 게시물에 작성자를 만드는 법만 알아보겠습니다.

폴더구조

코드 - js

// models/Post.js

...

// schema
var postSchema = mongoose.Schema({
  title:{type:String, required:[true,'Title is required!']},
  body:{type:String, required:[true,'Body is required!']},
  author:{type:mongoose.Schema.Types.ObjectId, ref:'user', required:true}, // 1
  createdAt:{type:Date, default:Date.now},
  updatedAt:{type:Date},
});

...

1. post schema에 author를 추가해 줍니다. 또한 ref:'user'를 통해 이 항목의 데이터가 user collection의 id와 연결됨을 mongoose에 알립니다. 이렇게 하여 user의 user.id와 post의 post.author가 연결되어 user와 post의 relationship이 형성되었습니다.

// routes/posts.js

...

// Index
router.get('/', function(req, res){
  Post.find({})
    .populate('author') // 1
    .sort('-createdAt')
    .exec(function(err, posts){
      if(err) return res.json(err);
      res.render('posts/index', {posts:posts});
    });
});

...

// create
router.post('/', function(req, res){
  req.body.author = req.user._id; // 2
  Post.create(req.body, function(err, post){
    if(err){
      req.flash('post', req.body);
      req.flash('errors', util.parseError(err));
      return res.redirect('/posts/new');
    }
    res.redirect('/posts');
  });
});

// show
router.get('/:id', function(req, res){
  Post.findOne({_id:req.params.id}) // 3
    .populate('author')             // 3
    .exec(function(err, post){      // 3
      if(err) return res.json(err);
      res.render('posts/show', {post:post});
    });
});

...

1. Model.populate()함수는 relationship이 형성되어 있는 항목의 값을 생성해 줍니다. 현재 post의 author에는 user의 id가 기록되어 있는데, 이 값을 바탕으로 실제 user의 값을 author에 생성하게 됩니다.

2. 글을 작성할때는 req.user._id를 가져와서 post의 author에 기록합니다.
(req.user는 로그인을 하면 passport에서 자동으로 생성해 줍니다.. 기억하죠?)

3. index와 마찬가지로 show에도 .populate()함수를 추가하였습니다.

코드 - ejs

<!-- views/posts/index.ejs -->

...
      <table class="board-table table table-sm border-bottom">

        <thead class="thead-light">
          <tr>
            <th scope="col">Title</th>
            <th scope="col" class="author">Author</th> <!-- 1 -->
            <th scope="col" class="date">Date</th>
          </tr>
        </thead>

        <tbody>
          <% if(posts == null || posts.length == 0){ %>
            <tr>
              <td colspan=100> There is no data to show :( </td>
            </tr>
          <% } %>
          <% posts.forEach(function(post) { %>
            <tr>
              <td>
                <a href="/posts/<%= post._id %>"><div class="ellipsis"><%= post.title %></div></a>
              </td>
              <td class="author"> <!-- 2 -->
                <div class="ellipsis"><%= post.author ? post.author.username : "" %></div>
              </td>
              <td class="date">
                <span data-date="<%= post.createdAt %>"><%= post.createdAt %></span>
              </td>
            </tr>
          <% }) %>
        </tbody>

      </table>

...

1. tabletheader에 author 항목을 추가합니다.

2. tabletbody에 author 항목을 추가하고 author가 있는 경우 author의 username을 표시합니다.

<!-- views/posts/show.ejs -->

...
            <div class="post-info card m-2 p-2">
              <div class="border-bottom pb-1 mb-1"> <!-- 1 -->
                <span>Author</span> : <%= post.author ? post.author.username : "" %>
              </div>
              <div><span>Created</span> : <span data-date-time="<%= post.createdAt %>"><%= post.createdAt %></span></div>
              <% if(post.updatedAt) { %>
                <div><span>Updated</span> : <span data-date-time="<%= post.updatedAt %>"><%= post.updatedAt %></span></div>
              <% } %>
            </div>
...

1. index와 마찬가지로 show에도 author 항목을 추가하고 author가 있는 경우 author의 username을 표시합니다.

코드 - css

/* pulbic/css/master.css */

...

.board-table {
  table-layout: fixed;
}
.board-table .author,
.board-table .date {
  width: 100px;
}

...

실행결과

로그인을 한 후에 글을 작성해 봅시다.

post index 페이지에 author가 표시됩니다.

post show에서도 표시가 됩니다.

마치며...

이제 게시판에 누가 글을 썼는지 알 수 있습니다!

다음 강의에서는 로그인 유무, 글 작성자 본인 확인을 통해 사이트의 기능을 제한하는 방법을 알아보겠습니다.

댓글

댓글쓰기

이 글에 댓글을 다시려면 SNS 계정으로 로그인하세요. 자세히 알아보기

UP