Validation이란 무엇인가?

특별한게 아니지만 개발을 하면서 가장 중요한것중 하나입니다. Validation은 말 그대로 어떤것을 검증한다고 보면 됩니다.

function is1(value) {
	return value === 1;
}

위 코드는 단순히 값이 1인지 아닌지 판단해서 Boolean 타입의 값을 반환하는 함수입니다.

이렇게 단순한 함수조차 Validation. 즉, 검증을 위한 코드가 됩니다.

라이브러리 joi가 그 예가 될 수 있습니다.
joi - npm (npmjs.com)

 

joi

Object schema validation

www.npmjs.com

joi.dev - 17.4.2 API Reference

 

joiSite

## Build Setup

joi.dev

나중에 로그인구현에서 쓰게 될 예정입니다.

 

JWT 

  • JSON 형태의 데이터를 안전하게 교환하여 사용할 수 있게 해줍니다.
  • 인터넷 표준으로서 자리잡은 규격입니다.
  • 여러가지 암호화 알고리즘을 사용할 수 있습니다.
  • header.payload.signature 의 형식으로 3가지의 데이터를 포함한다. (개미처럼 머리, 가슴, 배) 때문에 JWT 형식으로 변환 된 데이터는 항상 2개의 . 이 포함된 데이터여야 합니다.
  • header(머리)는 signature(배)에서 어떤 암호화를 사용하여 생성된 데이터인지 표현합니다.
  • payload(가슴)는 개발자가 원하는 데이터를 저장합니다.
  • signature(배)는 이 토큰이 변조되지 않은 정상적인 토큰인지 확인할 수 있게 도와줍니다.
  • JWT는 암호 키를 몰라도 Decode가 가능합니다. 변조만 불가능 할 뿐, 누구나 복호화하여 보는것은 가능하다는 의미가 됩니다!
  • 때문에 민감한 정보(개인정보, 비밀번호 등)는 담지 않도록 해야합니다.
  • 특정 언어에서만 사용 가능한것은 아닙니다! 단지 개념으로서 존재하고, 이 개념을 코드로 구현하여 공개된 코드를 우리가 사용하는게 일반적입니다.

 

정보열람(decode) 누구나 가능하지만

발급하는 것도 검증하는 것도 서버만 가능

 

기본세팅

$ npm i express mongoose jsonwebtoken joi -S
//익스프레스와 몽구스 jwt joi를 한번에 설치해 준다.

 

간단한 jwt인증 미들웨어를 구현해 보았다.

const jwt = require("jsonwebtoken");
const User = require("../models/user")


module.exports = (req, res, next) => {
    const { authorization } = req.headers;
    const [toKenType, tokenValue] = authorization.split(' ');
    console.log(tokenValue)

    if (toKenType !== 'Bearer'){
        res.status(401).send({
            errorMessage: '로그인 후 사용하세요',
        })
        return;
    }

    try {
        const { userId } = jwt.verify(tokenValue, "my-secret-key");

        User.findById(userId).then((user)=> {
            res.locals.user = user;
            next();
        });
        
    } catch (error) {
        res.status(401).send({
            errorMessage: "로그인 후 사용하세요",
        })
        return
    }

}

 

 

joi 라이브러리를 이용해서 간단히 로그인과 회원가입 페이지를 만들어 보았다.

const postUsersSchema = Joi.object({
    nickname: Joi.string().required(),
    email: Joi.string().email().required(),
    password: Joi.string().required(),
    confirmPassword: Joi.string().required(),
})

router.post("/users", async (req, res) => {
    try{
        const { nickname, email, password, confirmPassword } = await postUsersSchema.validateAsync(req.body);

        if (password !== confirmPassword) {
          res.status(400).send({
            errorMessage: "패스워드가 패스워드 확인란과 동일하지 않습니다.",
          });
          return;
        }
      
        const existUsers = await User.find({
          $or: [{ email }, { nickname }],
        });
        if (existUsers.length) {
          res.status(400).send({
            errorMessage: "이미 가입된 이메일 또는 닉네임이 있습니다.",
          });
          return;
        }
      
        const user = new User({ email, nickname, password });
        await user.save();
      
        res.status(201).send({});
    } catch(err) {
        console.log(err)
        res.status(400).send({
            errorMessage: "요청한 데이터 형식이 올바르지 않습니다.",
        })
    }
  
});



const postAuthSchema = Joi.object({
    email: Joi.string().email().required(),
    password: Joi.string().required(),
})
router.post("/auth", async (req, res) => {
    try{
        const { email, password } = await postAuthSchema.validateAsync(req.body);

        const user = await User.findOne({ email, password }).exec();
      
        if (!user) {
          res.status(400).send({
            errorMessage: "이메일 또는 패스워드가 잘못됐습니다.",
          });
          return;
        }
      
        const token = jwt.sign({ userId: user.userId }, "my-secret-key");
        res.send({
          token,
        });
    } catch (err) {
        res.status(400).send({
            errorMessage: "요청한 데이터 형식이 올바르지 않습니다.",
    })
    }
});

 

+ Recent posts