Others/42Seoul

BLIND CLONE CODING 2일차

tonyhan18 2022. 1. 23. 17:35
728x90

이제 user.js에서 사용자 정보 변경, 사용자 삭제, 프로필 이미지 추가 같은걸 해야하는데... 할 수 있을려나...

 

board 스키마를 붙일건데 이걸 slug라고 부른다. 이제 막 url이었던 것을 slug로 바꾼것이다.

 

slug에 따라서 게시판 id를 얻어야 하고 article에 적힌 board id 값을 보고 가져오는 형태로 만들어진다.

 

findOne은 하나만 찾아내느데 find는 배열 형태로 찾게 되는 차이점이 존재한다.

 

일단 위와같이해서 board의 api를 정의해놓자

 

board api에 보드를 만드는 기능을 추가하자

 

POSTMAN으로 board에 위와같은 요청을 보낼것이다. 왜냐하면 이 서비스의 slu이름은 주소창에 쓰이니 언제 바뀔지 모르기 때문이다.

 

다행히 잘 들어가 있다.

 

어떤값을 생성할때는 post를 사용하자

 

작성전에 Article에 author을 추가해놓자. 그래야 누가 작성했는지 알아볼 수 있다.

 

만약 정상적으로 되었다면 newArticle에 _id 값이 자동으로 추가가 될것이다.그런데 우리가 앞에서 무한 스크롤을 위해서 AutoIncrement를 추가했던 부분에 id가 있다. 그렇다보니 우리가 코드 짜다가 헷갈릴 수 있을거 같아서 id도 key로 바꾸었다.

 

 

에러가 이번에는 title의 dup key가 있다고 한다...

 

일단 article/title에 unique가 있어서 생긴 문제였다. 이걸 지워주고 db에서도 해당 보드를 일시적으로 지워주어야 적용된다.

 

이번에는 잘 추가되었다

 

실재로 해당 보드에서 게시글을 매우 잘 가져온것을 확인할 수 있다.

 

comment 부분과 대댓글 부분을 구현해보자

 

수정을 위해서는 patch 또는 put을 사용하는데 여기에서는 patch로만 사용하자

findOneAndUpdate({},{})으로 해서 해당 댓글을 찾아내고 수정도 가능해진다.

 

위와같이 Mongoose의 공식 문서에 있는 함수를 사용해서 처리하면된다.

 

 

Mongoose v6.1.7: API docs (mongoosejs.com)

 

Mongoose v6.1.7: API docs

 

mongoosejs.com

 

암튼 앞으로 몽구스로 데이터를 바꿀때는 공식문저 뒤져가면서 찾아내자

 

 

 

다시금 postman으로 이걸 처리해보자

 

const { Reply, Comment } = require("../mongoose/model.js");
var express = require("express");
var router = express.Router();

// 댓글 생성하기
router.post("/Reply/create", async (req, res) => {
  const { author, comment, content } = req.body;
  const newReply = await Reply({
    author,
    comment,
    content,
  }).save();
  res.send(newReply._id ? true : false);
});

// 댓글 수정
router.patch("/Reply/update", async (req, res) => {
  const { id, author, content } = req.body;
  const updateReply = await Reply.findOneAndUpdate(
    {
      _id: id,
      author,
    },
    {
      content,
    },
    {
      new: true,
    }
  );

  res.send(updateReply);
});

// 댓글 삭제
router.delete("/reply/delete", async (req, res) => {
  const { id, author } = req.body;
  const deletedReply = await Reply.deleteOne({
    _id: id,
    author,
  });

  res.send(deletedReply);
});

module.exports = router;

 

이렇게 CRUD작업을 왠만한건 다 했는데 좀 뭐랄까... 노가다 작업인 느낌이 들 수 밖에 없다.

 

위와같이 reply가 들어갔다.

 

그런데 이제 문제점은 댓글을 그냥 삭제해버리면 문제가 생긴다. 만약 댓글을 그냥 지워버리면 아랫쪽에 있는 reply들도 다 지워줘야하는 문제점이 생긴다. 이걸 해결하기 위해서는 soft delete와 hard delete를 적용해야한다.

 

현재 짜진것은 hard delete로 진짜 삭제해버린거다.

soft delete는 내용만 없애는 거이다.

 

// hard delete : DB에도 존재하지 않게 만드는것
// soft delete : 일반 사용자는 보지 못하는 상태, 일정 기간이 지나면 삭제될 상태

 

soft delete는 나중에 한번에 삭제해버린다. 서버 점검시나 60일의 기간을 지나고 지운다. 그리고 이렇게 해야 서버의 잠재적인 위협요소도 해결할 수 있다.

 

 

위와같이 soft delete는 시간을 추가해준다. 그리고 deleteOne이 아닌 findOneAndUpdate를 사용했다.

 

comment 관련 수정 완료

const { Article, Comment } = require("../mongoose/model.js");
var express = require("express");
var router = express.Router();

// 개별 게시글 가져오는 라우터
router.get("/article/:id", async (req, res) => {
  const { id } = req.params;
  const article = await Article.findById(id);
  const comment = await Comment.find({ article: id });
  res.send({ article, comment });
});

router.post("/article/create", async (req, res) => {
  const { author, title, content, board } = req.body;
  const newArticle = await Article({
    author,
    title,
    content,
    board,
  }).save();
  res.send(newArticle);
});

// 게시글 수정
router.patch("/article/update", async (req, res) => {
  const { id, author, content } = req.body;
  const updateArticle = await Comment.findOneAndUpdate(
    {
      _id: id,
      author,
    },
    {
      content,
    },
    {
      new: true,
    }
  );
  res.send(updateArticle);
});

// article 완전 삭제
router.delete("/article/delete/hard", async (req, res) => {
  const { id, author } = req.body;
  const deletedContent = await Comment.deleteOne({
    _id: id,
    author,
  });

  res.send(deletedContent);
});

// article 완전 삭제
router.delete("/article/delete/soft", async (req, res) => {
  const { id, author } = req.body;
  const deletedContent = await Comment.findOneAndUpdate(
    {
      _id: id,
      author,
    },
    {
      deleteTime: new Date().getTime() + 30 * 24 * 60 * 60 * 1000,
    }
  );

  res.send(deletedContent);
});

module.exports = router;

위와같이 reply, article, comment 부분에 deleteTime을 추가해주었다.

 

그럼 앞으로 삭제된 날짜가 있는 것들은 쿼리로 가져올때 삭제될 날짜가 정해져있다면 안가져오면된다.

 

 

 

이제 프론트 작업하자

 

---

 

NUXT 를 써서 만들꺼다

그런데 React, Vue는 가급적 여기에서 안쓰는게 좋다. 왜냐하면 많은 경우의 서비스가 서버를 통하고 SEO 문제도 있고 각각의 페이지를 랜더링을 하고 공유도 많이하고 그럴텐데 근본적으로 SSR이 잘되는 NEXT, NUXT를 써줘야한다.

 

```

npx create-nuxt-app alumni

```

하면 뭔가가 된다. 일단 위와같이 패키지들을 설치해주자

 

실수로 GIt을 까았는데 삭제해주자

 

그리고 폴더명을 client로 바꾸어놓자

 

 

잠시만 vue.js의 nuxt.js (react는 next.js)를 배워보자

 

이건 서버사이드 렌더링이다. 리액트와 뷰는 모두 SPA(CSR)이다.

SPA의 단점은

1. First Page Rendering이라는 사용자 첫방문시 사이트가 열리는 속도가 느리다.

2. SEO : 검색엔진 최적화가 잘 안된다.

3. 어떠한 페이지를 사용자가 공유할때 SPA로 만들어진 친구들은 공유할때 우리가 원하는 형태의 데이터가 전달되지 않는 경우가 많다.

 

정적사이트 생성에 도움이된다.

많은 것들의 코드가 프레임워크로 정해져 있어서 패턴만 익숙해지면 생산성이 향상된다.

 

```

npx create-nuxt-app <project-name>

```

 

yarn -> yarn-lock

npm -> npm-lock

npm 서버에서는 npm이 나음

 

UI Framework로는 Vuetify.js를 많이 쓴느 변 그 다음은 Ant Design -> BootStrap

728x90