NodeJS+MongoDB

NodeJS+MongoDB Part3 - 게시판, API 관리

hminor 2023. 6. 27. 21:03

게시판

우선 정정할 것이 있다.

지난번 로그인 시 세션을 저장할 때 로그인 유저의 정보를 같이 담아주는 코드가 잘못되어 있었다.

// 지난번 코드
// 이때 id로 가져오는 값에 object로 로그인 유저의 정보가 들어가 있기에
// 찾을 수 없었고 그렇기에 data에는 undefined가 들어가게 되었었다 ㅠㅠ 
//  (한참을 찾았네...)
passport.deserializeUser((id, done) => {
  db.collection("login").findOne({ id: id }, (err, data) => {
    done(null, data);
  });
});

// 변경 후
passport.deserializeUser((userData, done) => {
  db.collection("login").findOne({ id: userData.id }, (err, data) => {
    done(null, userData);
  });
});

위의 코드를 작성하게 되면 어디에서든 done(null, userData) 안에 있는 userData를 req.user로 가져올 수 있게 된다.

이후 해당 게시글을 작성한 유저만 삭제할 수 있도록 하기 위해 아래와 같이 코드를 수정하기

 app.delete("/delete", (req, res) => {
  // req.body를 하게되면 ajax로 요청시 보낸 data를 받아서 확인할 수 있다.
  // 그리고 아래처럼 req.body로 보낸 숫자 1의 데이터가 받아올때는 문자 '1'로 받아와지기에 Int로 변경 시켜주기.
  const id = parseInt(req.body._id);
  // req.body에 담겨온 게시물번호를 가진 글을 db에서 찾아서 삭제해주세요.
  console.log("req.user._id", req.user._id);
  const deleteData = { _id: id, user: req.user._id };

  // deleteOne({어떤 항목을 삭제할지}, ()=>{}) --> 삭제 메서드
  db.collection("post").deleteOne(deleteData, (error, data) => {
    // 응답코드 200을 보내주기.
    // .send({}) 로 메시지를 함께 보내주기.
    console.log("data.deletedCount", data.deletedCount);

    if (error) {
      res.status(400).send({ message: "실패" });
    } else if (data.deletedCount !== 1) {
      res.status(400).send({ message: "실패" });
    } else {
      res.status(200).send({ message: "성공" });
    }
  });
});

여기서 주의할 점은 기존에 deleteOne으로 해당 데이터를 지웠는지 못지웠는지에 대한 데이터를 확보하지 못했어서 작성한 유저가 아닐 경우에도 당장은 지워지도록 되지만 새로고침을 하게되면 여전히 남아있게 되어서 아래의 코드처럼 else if(data.deletedCount !== 1)라는 경우가 아니면 400에러를 보내도록 해서 해결했음.

if (error) {
      res.status(400).send({ message: "실패" });
    } else if (data.deletedCount !== 1) {
      res.status(400).send({ message: "실패" });
    } else {
      res.status(200).send({ message: "성공" });
    }

Router 폴더와 파일을 만들어 API들 관리하기

별개로 routes 라는 폴더를 생성 후 shop.js 라는 라우터를 만들고 해당 파일안에 아래 코드 작성

const router = require("express").Router(); // 라우터 파일 필수
// require는 다른 파일이나 라이브러리를 여기에 첨부하겠다라는 의미가 된다.

// app.get('/shop/shirts', (req, res)=> {  // <--------- app 대신에 위에서 불러온 router로 변경하기
//   res.send('셔츠 판매 페이지')
// })

router.get("/shop/shirts", (req, res) => {
  res.send("셔츠 판매 페이지");
});

router.get("/shop/pants", (req, res) => {
  res.send("바지 판매 페이지");
});

module.exports = router; // module.exports = 내보낼 변수명
// 그래서 다른 곳에서 shop.js를 가져다 쓸 때 내보낼 변수가 된다.

이후 server.js에서 해당 라우터를 사용하기 위해 shop.js를 첨부하는 코드

// shop.js 라우터 첨부하기
// app.use 는 미들웨어를 사용하겠다 라는 의미 (다시 한번 기억하기!)
// 그래서 '/' 경로로 이동하게되면 require한 것을 요청해주세요 라는 의미가 된다.
app.use("/", require("./routes/shop"));

여기서 shop.js 에서 코드를 보면 /shop이 반복적으로 작성되고 있는데 이러한 것도 해결을 할 수 있다.

const router = require("express").Router(); // 라우터 파일 필수
// require는 다른 파일이나 라이브러리를 여기에 첨부하겠다라는 의미가 된다.

// app.get('/shop/shirts', (req, res)=> {  // <--------- app 대신에 위에서 불러온 router로 변경하기
//   res.send('셔츠 판매 페이지')
// })

router.get("/shirts", (req, res) => {
  res.send("셔츠 판매 페이지");
});

router.get("/pants", (req, res) => {
  res.send("바지 판매 페이지");
});

module.exports = router; // module.exports = 내보낼 변수명
// 그래서 다른 곳에서 shop.js를 가져다 쓸 때 내보낼 변수가 된다.
// shop.js 라우터 첨부하기
// app.use 는 미들웨어를 사용하겠다 라는 의미 (다시 한번 기억하기!)
// 그래서 '/' 경로로 이동하게되면 require한 것을 요청해주세요 라는 의미가 된다.
app.use("/shop", require("./routes/shop"));

그런데 해당 라우터를 이동할 때 로그인을 한 유저만 방문할 수 있도록 하기 위해선

미들웨어를 추가해서 isLogin을 실행 후 동작하도록 하기!

const router = require("express").Router();

// 만약 해당 라우터를 로그인을 한 유저만 사용하도록 하려면 어떻게 미들웨어를 추가 해야할까?
function isLogin(req, res, next) {
  if (req.user) {
    // <--- req.user는 로그인 후 세션이 있으면 항상 있는 데이터
    next();
  } else {
    res.redirect("/login");
  }
}

router.get("/sports", isLogin, (req, res) => {
  res.send("스포츠 게시판");
});

router.get("/game", isLogin, (req, res) => {
  res.send("게임 게시판");
});

module.exports = router;

다만 100개가 넘는 라우터가 있는데 하나하나 미들웨어를 작성하는건 불필요하기에

아래와 같이 router.use(isLogin)을 추가하게 되면 무조건 router를 실행하는 곳은 무조건 isLogin을 실행하도록 한다.

const router = require("express").Router();

function isLogin(req, res, next) {
  if (req.user) {
    // <--- req.user는 로그인 후 세션이 있으면 항상 있는 데이터
    next();
  } else {
    res.redirect("/login");
  }
}

//  만약 무조건 로그인을 해야만 이동하도록 해서 isLogin을 계속 넣지 않도록 하는 방법
// router에서 무조건 해당 미들웨어를 실행시키고 다음으로 넘어가게 하는 방법
router.use(isLogin);

router.get("/sports", (req, res) => {
  res.send("스포츠 게시판");
});

router.get("/game", (req, res) => {
  res.send("게임 게시판");
});

module.exports = router;

또 특정 URL에서만 해당 미들웨어를 추가하려면 아래와 같이 작성하기

// 만약 특정 URL에만 적용하는 미들웨어를 추가하려면
//  아래처럼 코드 작성하기
router.use('/shirts', isLogin);