게시판 - 파일첨부 기능 만들기 3 (리스트에 아이콘 추가)

소스코드

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

이 게시물의 소스코드는 게시판 만들기(고급) / 게시판 - 파일첨부 기능 만들기 2 (다운로드)에서 이어집니다.

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

git reset --hard
git pull
git reset --hard d576566
git reset --soft ccd0c59
npm install
atom .

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

git clone https://github.com/a-mean-blogger/board.git
cd board
git reset --hard d576566
git reset --soft ccd0c59
npm install
atom .

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


게시물에 첨부파일이 있는 경우 post index view에 아이콘을 추가해 봅시다. 이번 강의는 좀 짧지만 다음 강의와 합치자니 너무 복잡해지는것 같아서 분리했습니다.

일단 어떤식으로 이번 강의의 코드를 만들 수 있을지 생각해 봅시다. 게시판 - 댓글 기능 만들기 4 (댓글 수 표시) 강의와 비슷할 것이라고 추측할 수 있는데 맞습니다.

다만, 댓글에서는 isDeleted가 true이면 댓글의 내용을 숨기기만 했는데, 첨부파일은 isDeleted가 true이면 아예 해당 데이터가 없는것처럼 만들었습니다.

폴더 구조

코드 - js

// routes/posts.js

...

// Index

    ...
    posts = await Post.aggregate([
      ...
      { $lookup: {
          from: 'comments',
          ...
      } },
      { $lookup: { // 1
          from: 'files',
          localField: 'attachment',
          foreignField: '_id',
          as: 'attachment'
      } },
      { $unwind: { // 2
        path: '$attachment',
        preserveNullAndEmptyArrays: true
      } },
      { $project: {
          title: 1,
          author: {
            username: 1,
          },
          views: 1,
          numId: 1,
          attachment: { $cond: [{$and: ['$attachment', {$not: '$attachment.isDeleted'}]}, true, false] }, // 3
          createdAt: 1,
          commentCount: { $size: '$comments'}
      } },
    ]).exec();
  ...

1. post에 file을 $lookup을 통해 post.attachment로 연결합니다. 게시판 - 댓글 기능 만들기 4 (댓글 수 표시)강의에서 $lookup에 대해 설명했으므로 이 설명은 생략합니다.

2. $lookup은 항상 배열로 해당 조건을 만족하는 모든 데이터를 배열로 연결하는 특징이 있고, 이 배열을 풀어주려면 $unwind를 사용하는 것도 게시판 - 댓글 기능 만들기 4 (댓글 수 표시)강의에서 설명했었습니다. author와 마찬가지로 $unwind를 사용했는데, 그 모양이 조금 다릅니다.

author는 { $unwind: '$author' } 와 $unwind에 같이 문자열('$author')을 바로 넣어주었고, 여기서는 $unwind에 pathpreserveNullAndEmptyArrays항목이 들어갔습니다. { $unwind: '$author' }{ $unwind: { path:'$author' } }의 축약형으로 다들 예상하셨을 것이고, preserveNullAndEmptyArrays에 대해 알아봅시다.

unwind는 배열을 flat하게 풀어주는 대신에 배열의 수만큼 오브젝트를 생성합니다. author는 모든 post에 반드시 하나 존재하므로 단순히 unwind하면 되지만, 첨부파일은 없을수도 있습니다. 첨부파일이 없는 post는 unwind하게 되면 $lookup으로 생성된 첨부파일 배열의 길이가 0이므로 해당 post가 사라집니다. 배열의 길이가 0이거나, 배열이 없는 항목을 unwind하는 경우 기존 오브젝트를 삭제하지 않도록 하는 설정이 preserveNullAndEmptyArrays: true 입니다.

3. $cond(https://docs.mongodb.com/manual/reference/operator/aggregation/cond)에 대해 알아봅시다!

{ $cond: [조건, 조건이_참인_경우_값, 조건이_거짓인_경우_값] }

3. aggregation에서 $cond은 길이가 3인 배열을 받으며, 첫번째로는 조건, 두번째로는 조건이 참인 경우에 사용될 값, 세번째로 조건이 거짓인 경우에 사용될 값을 받습니다. 현재 코드는 조건이_참인_경우_값true, 조건이_거짓인_경우_값false로 조건에 따라 attachment의 값을 truefalse로 만드는 코드입니다.

다음으로 이 강의에서 조건에 사용된 코드를 살펴봅시다.

{$and: ['$attachment', {$not: '$attachment.isDeleted'}]

$and(https://docs.mongodb.com/manual/reference/operator/aggregation/and)와 $not(https://docs.mongodb.com/manual/reference/operator/aggregation/not)을 사용하고 있는데, $and는 배열을 받아 해당배열의 모든 값이 true이면 true를 return합니다. $not은 true인 값은 false로, false인 값은 true로 바꿔버립니다.

{ $cond: [{$and: ['$attachment', {$not: '$attachment.isDeleted'}]}, true, false] }

즉 위의 조건을 자바스크립트로 나타내면

$attachment && !$attachment.isDeleted ? true : false

으로, post.attachment의 값이 있고, post.attachment.isDeleted가 true가 아닌 경우 post.attachment에 true를, 아니면 false를 대입합니다.

코드 - ejs

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

              ...
                <a href="/posts/<%= post._id %><%= getPostQueryString() %>" class="title-container">
                  ...
                  <% if(post.commentCount){ %>
                    <small class="title-comments d-inline-block pl-2">(<%= post.commentCount %>)</small>
                  <% } %>
       <!-- 1 --> <% if(post.attachment){ %>
       <!-- 1 -->   <small class="title-attachment d-inline-block pl-2">📁</small>
       <!-- 1 --> <% } %>
                </a>

1. post index route에 의해 게시물에 첨부파일이 있는 경우 post.attachment의 값이 true 설정되므로 이 값을 이용해 첨부파일이 있는지 없는지를 표시해 줄 수 있습니다.

코드 - css

/* public/css/master.css */

...
.board-table .title-container:hover .title-comments,
.board-table .title-container:hover .title-text,
.board-table .title-container:hover .title-attachment
{
  text-decoration: underline;
}

...

기존의 .title-comments, .title-text만 있었는데, .title-attachment를 추가해주었습니다.

실행 결과

4번 게시물에 첨부파일이 있으므로 폴더 모양 아이콘이 표시되었습니다.

마치며...

다음으로 게시물에 첨부파일을 삭제/수정하는 기능을 추가합니다.

댓글

댓글쓰기

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

UP