๐ง ์ํฉ
๊ฐ์ธ๊ณผ์ ์์ ์๋ฌ์ฒ๋ฆฌ์ ๋๋ถ์ด ์๋ํด ๋ณธ๊ฒ ์๋ค.
์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํด์ฃผ๋ ์ข์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ์๋ค๊ณ ํด์ ๋ค์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค ์ค Joi๋ฅผ ์๋ํด ๋ดค๋ค.
Joi๋ฅผ ์๋ํ ์ด์ ๋ ๋ง์ด ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ฌธ์ด์๋ค.
ํ์ง๋ง Joi ์ธ์๋ ๋ค์ํ validation ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์กด์ฌํ๋ค.
Joi | ์คํค๋ง๋ฅผ ์ ์ํ์ฌ, ๋ฐ์ดํฐ ๊ฐ์ฒด์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ค. |
express-validator | Express ์น ํ๋ ์ ์ํฌ์ ํนํ. ์ฃผ๋ก HTTP ์์ฒญ์ ๋ฐ์ดํฐ์ ์ ํจ์ฑ์ ๊ฒ์ฆํ๋ค. |
Validator.js | ๋ฌธ์์ด ์ ํจ์ฑ ๊ฒ์ฌ์ ํนํ. |
express-validator๋ ๋ค๋ค๋ณด๊ณ ์ถ์ง๋ง, ์ค๋์ Joi์ ๋ํด์๋ง ๋ค๋ค๋ณด๊ฒ ๋ค.
๐ฃ์ก์
๋จผ์ Joi๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํด์ผ ํ๋ค.
npm i joi
๋์ ๊ฒฝ์ฐ joi๋ฅผ ๋ค๋ฅธ ํ์ผ๋ก ๊ตฌ๋ถํด์ ์ฌ์ฉํ๋ค.
๊ทธ๋์ JoiValidation.js ํ์ผ์ ๋ง๋ค๊ณ , ๊ทธ ์์์ ์ค์นํ joi๋ฅผ require ํด์๋ค.
์๋๋ Joi ๊ณต์๋ฌธ์์์ ๊ฐ์ ธ์จ ๋ด์ฉ์ ์ฃผ์์ ์ฒจ๋ถํ ์ฝ๋์ด๋ค.
const Joi = require('joi');
const schema = Joi.object({
username: Joi.string()
.alphanum()
.min(3)
.max(30)
.required(), // required()๋ ํ์๋ก ์ ์ด์ผ ํ๋ ์ปฌ๋ผ์๋ง ์ ์ด์ฃผ์.
password: Joi.string()
.pattern(new RegExp('^[a-zA-Z0-9]{3,30}$')),
repeat_password: Joi.ref('password'), //ref()๋ฅผ ์ด์ฉํด ์ฐธ์กฐํ๊ณ ์๋ ๋ฐ์ดํฐ์ ๋์ผํ์ง ๊ฒ์ฆํ ์ ์๋ค.
email: Joi.string()
.email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } })
})
try {
// Joi์์ ์ ๊ณตํ๋ validateAsync๋ฅผ ์ด์ฉํด ํด๋น ์คํค๋ง๋ฅผ ๊ฒ์ฆํ ์ ์๋ค.
const value = await schema.validateAsync({ username: 'abc', birth_year: 1994 });
}
catch (err) {
}
์ ๋ณ๊ฑฐ ์๋ค ํ๊ณ ์์ฑ์ ์์ํ์ง๋ง, ์์ํ์ง ๋ชปํ ๋๊ด์ด ์์๋ค.
๊ฐ ์ํฉ์ ๋ฐ๋ผ ์๋ฌ๋ฉ์ธ์ง ์ฒ๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ํด์ค์ผ ํ ์ง ๋ง๋งํ๋ค.
if๋ฌธ์ผ๋ก ์๋ฌ์ฒ๋ฆฌ๋ฅผ ํด์ผํ ๊น ๊ณ ๋ฏผํ์ง๋ง,
๊ทธ๋ผ joi๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๊ฐ ์๋ ๋ฏ ํ๋ค.
Joi error message ๋ผ๊ณ ๊ฒ์ํ์ ์คํ ์ค๋ฒํ๋ก์ฐ ์์ ์ํ๋ ๋ต์ ์ป์ ์ ์์๋ค.
์๋๋ ์ฐธ๊ณ ํ ๋ต๋ณ์ด๋ค.
const Joi = require('@hapi/joi');
const joiSchema = Joi.object({
a: Joi.string()
.min(2)
.max(10)
.required()
.messages({
'string.base': `"a" should be a type of 'text'`,
'string.empty': `"a" cannot be an empty field`,
'string.min': `"a" should have a minimum length of {#limit}`,
'any.required': `"a" is a required field`
})
});
const validationResult = joiSchema.validate({ a: 2 }, { abortEarly: false });
console.log(validationResult.error); // expecting ValidationError: "a" should be a type of 'text'
์์์ ๋ณด๋ค์ถ์ด
.massages({})๋ฅผ ์ด์ฉํด, error๊ฐ ๋ฌ์ ๊ฒฝ์ฐ ์ด๋ค ๋ฉ์ธ์ง๋ฅผ ๋ณด์ฌ์ค์ง ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๋ฉด ๋๋๊ฒ ๊ฐ๋ค.
์์ ์ ํ์๋ 'string.min' ๊ฐ์ ๋ฌธ์๋ ์ด๋์ ๋์จ๊ฑด์ง ๊ถ๊ธํด, ์๋ฌ๊ฐ ๋ ๊ฒฝ์ฐ res.send(err)๋ฅผ ๋ณด๋ด๋ดค๋ค.
์๋๋ ์ถ๋ ฅ ๊ฒฐ๊ณผ์ด๋ค.
{
"_original": {
"nick_name": "๋ฐฉ์ดw22wssํ",
"email": "",
"password": "123123",
"passwordRe": "123123",
"birth_date": "1995-06-24",
"address": "dd"
},
"details": [
{
"message": "\"email\" is not allowed to be empty",
"path": [
"email"
],
"type": "string.empty",
"context": {
"label": "email",
"value": "",
"key": "email"
}
}
]
}
๋ณด๋ err.details[0].type์ ๋ด์ฉ๋ฌผ์ ์ ์ด์ฃผ๊ณ , ๊ทธ๊ฒ์ ํด๋นํ๋ ๋ฉ์ธ์ง๋ฅผ ๋ฆฌํดํ๋ ๋ฏ ํ๋ค.
๊ทธ๋ผ try์์ validateAsync()๋ฅผ ํด์ฃผ๊ณ , ์๋ฌ๊ฐ ๋ ๊ฒฝ์ฐ catch(err)๋ก ๋์ด์ค๋ฉด์,
res.json์ผ๋ก ํด๋น ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ด์ฃผ๋ฉด ๋ ๊ฒ ๊ฐ์ ์๋ํด ๋ดค๋ค.
๊ทธ๋ฆฌ๊ณ ,
์ํ๋ ๋๋ก ๊ฒฐ๊ณผ๊ฐ ์ ์ถ๋ ฅ์ด ๋์๋ค!!!
์๋๋ ์ค์ ๋ก ๊ตฌํํ Joi๋ฅผ ํ์ฉํ ํ์๊ฐ์ ์ ํจ์ฑ ๊ฒ์ฌ ์ฝ๋์ด๋ค.
const Joi = require('joi');
//ํ์๊ฐ์
์ ํจ์ฑ ๊ฒ์ฌ
const registerValidation = async (req, res, next) => {
const schema = Joi.object({
nick_name: Joi.string().min(2).max(30).required().messages({
'string.empty': '๋๋ค์์ ์
๋ ฅํด ์ฃผ์ธ์.'
}),
email: Joi.string()
.email({ minDomainSegments: 2, maxDomainSegments: 2, tlds: { allow: ['com', 'net'] } })
.required()
.messages({
'string.email': '์ด๋ฉ์ผ์ ํ์ธํด ์ฃผ์ธ์.',
'string.empty': '์ด๋ฉ์ผ์ ์
๋ ฅํด ์ฃผ์ธ์'
}),
password: Joi.string().min(6).required().messages({
'string.empty': '๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์',
'string.min': '๋น๋ฐ๋ฒํธ๋ 6์๋ฆฌ ์ด์์ด์ฌ์ผ ํฉ๋๋ค.'
}),
passwordRe: Joi.any().valid(Joi.ref('password')).required().messages({
'any.only': '๋น๋ฐ๋ฒํธ๊ฐ ์ผ์นํ์ง ์์ต๋๋ค.'
}),
birth_date: Joi.date().allow('').iso().min('1-1-1920').max('1-1-2021').messages({
'date.format': '1920 ~ 2020 ์ถ์์๋ง ์
๋ ฅ์ด ๊ฐ๋ฅํฉ๋๋ค. (๋
-์-์ผ ํ์).'
}),
address: Joi.string().allow('')
});
try {
await schema.validateAsync(req.body);
next();
} catch (err) {
const message = err.details[0].message;
res.status(400).json({ message });
next(err);
}
};
module.exports = registerValidation
๐ฃ ๋๋์
Joi๋ฅผ ์ฌ์ฉํ๋ฉด ํธํ๋ค๊ณ ํ๋ ์ด์ ๋ฅผ ์ด์ ์ดํดํ ์ ์๊ฒ ๋์๋ค.
์์ด๊ถ์ด๋ผ๋ฉด ํจ์ฌ ํธํ๊ฒ ์ง๋ง, ํ๊ตญ์ ์ด๊ณ ์๊ธฐ ๋๋ฌธ์, ์ปค์คํ ๋ฉ์ธ์ง๋ฅผ ์ ์ด์ผ ํ๋ ์ ์ ์ฝ๊ฐ ์์ฌ์ ๋ค.
๊ทธ๋๋ ์ผ๊ด์ ์ผ๋ก ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํ๊ณ , ๋ณด๊ธฐ ํธํ๋ค.
๋ํ ๊ฐ ์ ๋ ฅ์ ๋ํ ํ์ ์ ํจ์ฑ ๊ฒ์ฌ๋ Joi๋ง ๊ด๋ฆฌํ๋ ํ๋์ ํ์ผ ์์์ ๊ตฌ๋๋๊ธฐ ๋๋ฌธ์, ๊ด๋ฆฌ๊ฐ ํธํ๋ค๊ณ ๋๊ปด์ก๋ค.
๋ค๋ฅธ validation๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ด๋จ์ง ๊ถ๊ธํ๋ค.
๋ค์์ ๊ธฐํ๊ฐ ๋๋ค๋ฉด express-validator๋ฅผ ์ฌ์ฉํด ๋ณด๊ณ ์ถ๋ค.
์ฐธ๊ณ ํ ์ฌ์ดํธ
https://stackoverflow.com/questions/48720942/node-js-joi-how-to-display-a-custom-error-messages