All Articles

허선생님과 Node.js 공부 - error 발생시키기, 중첩라우팅, fs

image.png

error 발생시키기

status에 따라 에러가 발생하도록 내가 error number와 메시지를 지정할 수 있다. 예를 들어 지정하지 않은 앤드포인트에 접속했을 때 404가 발생하도록 해보자.

app.use((req, res, next) => {
  res.status(404).json({
    message: '존재하지 않는 url입니다',
  });
});

response의 status가 404 일때 다음과 같은 메시지가 뜨도록 설정했다.
다음과 같은 방식으로도 해볼 수도 있다!

app.use((req, res, next) => {
  const err = new Error('존재하지 않는 url 입니다');
  err.status = 404;
  next(err);
});

우리 허선생님께서 최대한 효율적인 방법을 가르쳐주려고 노력을 많이 해주신다 감동쓰 ㅠㅠ

guard

로그인과 같이 인증을 통해 접근이 가능한 페이지를 만들어줄거다. cookie-parser를 이용해서 일단 쿠키 데이터를 만들어줄거다! 설치는 간단쓰! npm i cookie-parser 로 설치하기

const express = require('express');
const app = express();
const cookieParser = require('cookie-parser');
const routes = require('./routes');

cookieParser라는 변수를 하나 만들어서 cookie-parser메소드를 불러오고, 그 다음엔 app.use(cookieParser()) app.use 메소드 내에서 저 함수를 실행시켜야 한다.

중첩 라우트

저 위의 코드판에서 routes 변수에 담은 저 값은 뭘까?
같은 경로에 routes.js 파일이 있거나 아니면 같은 경로에 존재하는 routes 디렉토리 내의 index.js를 뜻한다. 나는 후자에 속하는데, 그렇담 routes 디렉토리의 index.js를 까보자

// index.js
const express = require('express');

// ▶︎
const router = express.Router();
const user = require('./user');

// ★
router.get('/login', (req, res, next) => {
  res
    .cookie('usertype', 1)
    .status(200)
    .json({ message: '로그인 테[스트 했습니다' });
});

router.use((req, res, next) => {
  console.log('매 요청마다 작도ㅓㅇ');
  next();
});
module.exports = router;

★ 별쪽 코드를 보면.. router가 get 메소드를 받고있다.
원래 이건 app의 입장에서만 받을 수 있는건데 ▶︎ 부분을 보면 router가 express에서 Router로서 값이 담겼다. express모듈을 불러와서 router라는 변수가 마치 app 인것처럼 행동할 수 있는 것..! 맞나?

그리하여… ★ 코드를 다시 한번 확인해보자면…!
/login url로 접속했을때 res의 쿠키가 usertype:1이고, 마침 그 상태가 200이면 message: 로그인 테스트했습니다. 가 뜨게 하는건데

image.png

짠 이렇게 뜬다! 개발자도구를 열어 Application을 확인해보면 쿠키도 잘 들어와 있다.

image.png

요렇게!

나의 콘솔창도 한번 보자

정리해보자면, 지금 구조가 login 페이지에 접속하면 쿠키가 생성이 되는 거고 checkUser 함수가 적용된 코드에는 권한이 필요한 것이다. 쿠키를 지우고 로그인을 거치지 않은 채, 다른 페이지를 접속하면 권한이 없다고 나온다.

image.png

요렇게! 짱신기~

더 나아가서.. checkUser함수를 controllers 디렉토리의 auth.js에 넣어주자.

app.use((req, res, next) => {
  console.log(req.cookies);
  if (req.cookies.usertype === 1) return next();
  const err = new Error('권한이 없네용');
  err.status = 401;
  next(err);
  // node.js에선 else를 안 쓰고 바로 리턴해버림. 중괄호를 최대한 줄이려는 관습이 있음
});

login 한다음에 user 들어가면 유저목록이 뜨는데
로그인 하기 전에 user 먼저 들어가면 권한이 없다고 에러 발생

cookie의 usertype이 1이 아닐 경우 에러를 던지는 코드다. index.js에서 로그인할때의 쿠키를 지정하는 코드가 있는데 그걸 살짝 바꿔줄거다

router.get('/login', (req, res, next) => {
  res
    .cookie('macaron', 2)
    .status(200)
    .json({ message: '로그인 테[스트 했습니다' });
});

res에서 쿠키가 들어오는 곳을 macaron으로 바꿔주었다.

image.png

그러고 나서 user페이지에 들어가보자.

image.png

쿠키가 usertype, 1이 아니기 때문에 접근 불가쓰~

여기까지 중첩라우터와 guard를 살펴봤고.. 인제 진짜 신기한 걸 할꺼다!

File System Module

노드는 신기하게도 파일의 읽고 쓰기가 가능하다!

// services/json.js
const fs = require('fs');
const path = require('path');

// 옛날방식의 비동기를 promise형으로 바꾼 것
const readJSON = (name) =>
  new Promise((resolve, reject) => {
    // dirname은 절대경로 찍는 명령어
    fs.readFile(path.join(__dirname, `../data/${name}.json`), (err, data) => {
      if (err) return reject(err);
      try {
        const result = JSON.parse(data);
        resolve(result);
      } catch (e) {
        reject(e);
      }
      resolve();
    });
  });

const writeJSON = (name, data) =>
  new Promise((resolve, reject) => {
    try {
      const json = JSON.stringify(data);
      fs.writeFile(
        path.join(__dirname, `../data/${name}.json`),
        json,
        (err) => {
          // 파일저장이 잘 됐는지 안됐는지 확인하는거니까 에러밖에 안 넣어줘도 됨
          if (err) return reject(err);
          resolve(true); // 생략가능
        }
      );
    } catch (e) {
      reject(e);
    }
    // 첫번째가 경로, 두번째가 데이터, 세번째가 콜백
  });

module.exports = {
  readJSON,
  writeJSON, // 똑같은 이름으로 내보내서 키랑 밸류 생략쓰
};

위와 같이 파일 읽기 및 쓰기 코드를 써준다. 그 다음에 routes 디렉토리 안의 user.js 에 아래와 같이 써준다.

// routes/user.js
const express = require('express');
const validator = require('express-validator');
const { validationMiddleware } = require('../controllers/validator');

const router = express.Router();
const { checkUser } = require('../controllers/auth');
// const checkUser = require('../controllers/auth').checkUser 같은거임
const json = require('../services/json');

router.use(checkUser);

router.get('/', checkUser, (req, res, next) => {
  json
    .writeJSON('test', { test: '성공쓰' })
    .then((rs) => {
      console.log(rs);
    })
    .catch((er) => {
      console.log(er);
    });
  const page = req.query;
  console.log(req.query);
  res.status(200).json({ name: '유저 목록' });
});

// user에만 권한이 있고, user/id 에는 영향 안줌. 독립적으로 작동함
router.get(
  '/:id',
  validationMiddleware(
    validator
      .param('id')
      .toInt()
      .isInt()
  ),
  (req, res, next) => {
    const id = req.params.id;
    console.log(id);
    res.status(200).json({
      name: '허선생님',
      id,
    }); // id: id 객체 값과 프로퍼티가 동일하면 지워짐.
  }
);

module.exports = router;

그 다음에 서버를 켜고 routes에 등록되어 있는 user로 접속을 해보자!

image.png

원래 data 디렉토리 안에는 아무 것도 없었으나…

image.png

서버를 켜고 접속하는 순간 test.json 파일이 data 폴더 내부에 생성된다. 그리고 메시지는 user.js에서 내가 설정한대로 성공쓰라고 뙇!!

없던 파일을 이렇게 만들어내다니.. 넘나 신기한 노드의 세상~
아직도 이해못하는 부분들이 많지만.. Promise랑 call back함수 열심히 공부해야지 ㅠ