이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실행할 수 있습니다.
이 게시물의 소스코드는 게시판 만들기(2016) / 게시판 - Post Error 처리에서 이어집니다.
board.git 을 clone 한 적이 있는 경우: 터미널에서 해당 폴더로 이동 후 아래 명령어들을 붙여넣기합니다. 폴더 내 모든 코드가 이 게시물의 코드로 교체됩니다. 이를 원치 않으시면 이 방법을 선택하지 마세요.
board.git 을 clone 한 적이 없는 경우: 터미널에서 코드를 다운 받을 폴더로 이동한 후 아래 명령어들을 붙여넣기하여 board.git 을 clone 합니다.
- Github에서 소스코드 보기: https://github.com/a-mean-blogger/board/tree/19d8720efd1c2a9da2b832b73bd3ef54849a77d8
/* * 이 강의는 2020년 버전으로 update되었습니다. -> 2020년 버전 보기 */
게시물과 사용자 사이에 관계(relationship)을 만들어 봅시다. 게시물 document에 작성자 document id를 기록하여 글 작성자 정보를 알 수 있게 됩니다.
이게 왜 중요한가 하면, 로그인 기능으로 현재 사이트에 로그인 한 유저가 누군지 알 수 있게 됐고, 여기에 작성자가 기록되면 자신이 작성한 글, 다른 사람이 작성한 글의 구분이 가능해 집니다. 즉 자신의 글은 삭제가 가능/남의 글은 삭제가 불가능하게 할 수 있습니다. 이번 게시물에서는 일단 게시물에 작성자를 만드는 법만 알아보겠습니다.
// 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}, },{ toObject:{virtuals:true} });
1. post schema에 author를 추가해 줍니다. 즉 post에 작성자 정보(user.id)를 기록하고, 이 정보는 user collection에서 가져오는 것임을 ref를 통해서 지정합니다.
// 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()
함수를 추가하였습니다.
<!-- views/posts/index.ejs --> <!-- ... --> <table class="table table-striped posts"> <thead> <tr> <th class="title">Title</th> <th class="author">Author</th> <!-- 1 --> <th class="date">Date</th> </tr> </thead> <tbody> <% if(posts == null || posts.length == 0){ %> <tr> <td class="noData" colspan=100> There is no data to show :( </td> </tr> <% } %> <% posts.forEach(function(post) { %> <tr> <td class="title"> <a href="/posts/<%= post._id %>"><div class="ellipsis"><%= post.title %></div></a> <!-- 3 --> </td> <td class="author"> <!-- 2 --> <div class="ellipsis"><%= post.author ? post.author.username : "" %></div> <!-- 3 --> </td> <td class="date"> <%= post.createdDate %> </td> </tr> <% }) %> </tbody> </table> <!-- ... -->
1. tabletheader
에 author 항목을 추가합니다.
2. tabletbody
에 author 항목을 추가하고 author가 있는 경우 author의 username을 표시합니다.
3. tabletbody
의 title과 author에 ellipsis
class를 주었습니다. ellipsis
custom CSS로 text의 내용이 width보다 긴 경우 긴 부분을 잘라내고 "..."을 추가해줍니다. 아래 CSS 항목에서 상세값을 볼 수 있습니다.
<!-- views/posts/show.ejs --> <!-- ... --> <div class="contentBox"> <h3 class="contentBoxTop"><%= post.title %></h3> <div class="row"> <div class="col-sm-4 col-sm-push-8"> <div class="post-info"> <div><span>Author</span> : <%= post.author ? post.author.username : "" %></div> <!-- 1 --> <div><span>Created</span> : <%= post.createdDate %> <%= post.createdTime %></div> <% if(post.updatedAt) { % <div><span>Updated</span> : <%= post.updatedDate %> <%= post.updatedTime %></div> <% } %> </div> <!-- post-info end --> </div> <!-- col end--> <div class="col-sm-8 col-sm-pull-4"> <div class="post-body"><%= post.body %></div> </div> <!-- col end--> </div> <!-- row end --> </div> <!-- post-container end --> <!-- ... -->
1. index와 마찬가지로 show에도 author 항목을 추가하고 author가 있는 경우 author의 username을 표시합니다.
/* pulbic/css/master.css */ /* ... */ .ellipsis{ /* 1 */ display: block; width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* ... */ .post-index .posts{ border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; table-layout: fixed; /* 2 */ } /* ... */ .post .posts .author{ /* 3 */ text-align: center; width: 80px; } /* ... */
1. text의 내용이 width보다 긴 경우 긴 부분을 잘라내고 "..."을 추가해줍니다. 핵심은 text-overflow: ellipsis;
랑 overflow: hidden;
이며 둘 중 하나라도 없으면 작동하지 않습니다. white-space: nowrap;
은 text에 space가 있고 text 길이가 width보다 긴 경우 자동으로 줄바꿈을 하는데, 이것을 방지하기 위함합니다.
2. .ellipsis를 table안의 title항목에 적용하기 위해 기존의 .post-index .posts에 추가된 항목입니다.
table의 경우 cell의 길이에 맞춰 유동적으로 width가 변하게 되어 있는데, table-layout: fixed;
를 넣어주면 cell이 table보다 더 길어지지 않게 됩니다.
3. author 를 가운데 정렬하고 길이를 지정해 줬습니다.
로그인을 한 후에 글을 작성해 봅시다.
게시물에 들어가면 author가 표시됩니다.
ellipsis도 테스트 해 봅시다.
제목이 긴 경우 뒷부분이 ... 으로 표시됩니다.
만약 로그인 하지 않고 글을 작성하려고 한다면?
req.user
의 값을 읽어 오지 못하므로 에러가 납니다. 이 에러의 처리는 다음 게시물에서...
이제 작성자 정보를 기록했으니 작성자를 기준으로 게시물의 삭제, 수정을 가능하게 할 수 있습니다.
다음 강의에서는 로그인 유무, 글 작성자 본인 확인을 통해 사이트의 기능을 제한하는 방법을 알아보겠습니다.
댓글
이 글에 댓글을 다시려면 SNS 계정으로 로그인하세요. 자세히 알아보기