๐ง ์ํฉ
๊ฐ์ธ๊ณผ์ ์์ ์๋ฌ์ฒ๋ฆฌ์ ๋๋ถ์ด ์๋ํด ๋ณธ๊ฒ ์๋ค.
์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํด์ฃผ๋ ์ข์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ์๋ค๊ณ ํด์ ๋ค์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค ์ค 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
Node.js + Joi how to display a custom error messages?
It seems pretty straight forward to validate user's input in Node.js RESTapi with Joi. But the problem is that my app is not written in English. That means I need to send a custom written messages...
stackoverflow.com
joi.dev
joi.dev
joi๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ํจ์ฑ๊ฒ์ฌ
์ด๋ฒ ํ๋ก์ ํธ์ joi๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํ ์ ํจ์ฑ๊ฒ์ฌ์ ๊ทธ์ ๋๋ฅธ ์๋ฌ ํธ๋ค๋ฌ ๋ฏธ๋ค์จ์ด๋ฅผ ์์ฑํ๊ฒ ๋์๋ค. ์ฝ๋ฉ ์ด๊ธฐ if๋ก ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํ๊ฒ๋๋ฉด ๊ทธ ์ฝ๋์ ๊ธธ์ด๋ ์์ด ๋ง์ด ๋์ด๋๊ณ , ์ฝ๋
velog.io