V-logue

[Node.js] Express.joi 모듈을 활용해 validation을 검증하자 본문

발자취/Node.js

[Node.js] Express.joi 모듈을 활용해 validation을 검증하자

보그 2022. 6. 9. 14:41

Joi

joi는 JavaScript에서 가장 강력한 Schema를 설명하는 언어 및 데이터 유효성(validation) 검사기이다.

 

설치는 다음과 같이 시작한다

npm install joi

사용법은 간단하다.

 

먼저, 조이를 require를 통해 불러와주고

const joi = require("joi")

유효성을 검증할 Schema와 검증을 시도할 body를 구성한다.

const UserSchema = joi.object.key({
	userId: joi.string().min(4).max(20).required(),
    password: joi.string().min(8).max(20).required(),
    email: joi.string().email().required()
})

const user = {
	userId: vlogue,
    password: 1234,
    email: test@email.com
}

위 처럼 구성된 스키마와 바디를 validate를 통해 검증한다.

const user = {
	userId: "vlogue",
    password: 1234,
    email: "test@email.com"
}

// const { error , value } = joi.validate(user, UserSchema)
// 기존의 문법은 이렇게 사용했는데, 최신 문법은 아래인 것 같다.
// 위 방법처럼 사용하면 TypeError: joi.validate is not a function이 뜬다.

const validation = UserSchema.validate(user);
console.log(validation) 
// 다음과 같이 터미널에 출력된다.
{
    value: { userId: 'vlogue', password: 1234, email: 'test@email.com' },
    error: [Error [ValidationError]: "password" must be a string] {
      _original: { userId: 'vlogue', password: 1234, email: 'test@email.com' },
      details: [ [Object] ]
    }
  }

코드를 보면 알겠지만, password는 string이여야 하는데, 입력된 값이 Number라 error가 나버린 모습이다.

pw를 다시 string으로 바꾸고 시도하면,

const user = {
	userId: "vlogue",
    password: "1234",
    email: "test@email.com"
}

// const { error , value } = joi.validate(user, UserSchema)
const validation = UserSchema.validate(user);
console.log(validation) //
// console.log(value) //

{
    value: { userId: 'vlogue', password: '1234', email: 'test@email.com' },
    error: [Error [ValidationError]: "password" length must be at least 8 characters long] {
      _original: { userId: 'vlogue', password: '1234', email: 'test@email.com' },
      details: [ [Object] ]
    }
}

또 다시 에러가 나는데, 이번에는 password는 최소 8자 이상이어야 하기 때문에 에러가 났다.

 

이렇게 쉽게 외부에서 입력된 값의 validation을 검증할 수 있게 됐다.

 

이외에도 추가적인 문법들이 존재하는데, 먼저

Schema 에 정의되지 않은 key가 존재한다면 validate error가 나타나게 되는데,

이런 에러를 막으려면 .unknown()을 사용하면 된다.

const joi = require("joi")

const UserSchema = joi.object({
	userId: joi.string().min(4).max(20).required(),
    password: joi.string().min(8).max(20).required(),
    email: joi.string().email().required()
})

const user = {
	userId: "vlogue",
    password: "12345678",
    email: "test@email.com",
    nickname:"Vogue"
}

// const { error , value } = joi.validate(user, UserSchema)
const validation = UserSchema.validate(user);
console.log(validation) // error: [Error [ValidationError]: "nickname" is not allowed]

key값에 존재하지 않는  nickname이라는 값을 추가하게 되면, not allowed라는 ValidationError가 생기게 된다.

이때에 .unknown()을 사용하게 되면,

const UserSchema = joi.object({
	userId: joi.string().min(4).max(20).required(),
    password: joi.string().min(8).max(20).required(),
    email: joi.string().email().required()
}).unknown(); // unknown() 추가

허용되지 않는 key값도 허용되게 된다. 실제로 위위코드와 똑같이 작성하고 unknown만 입력했는데

에러가 발생하지 않게 됐다.

 

이외에도 .and.or.nand.xor가 있는데

bit 연산과 동일하다고 생각하면 된다. or는 정의된 키가 하나이상이나 모두 있다면 Ok지만,

xor은 정의된 key가 모두 있는 경우 validationError가 생기게 된다.

const UserSchema = joi.object({
	userId: joi.string().min(4).max(20).required(),
    password: joi.string().min(8).max(20).required(),
    email: joi.string().email().required()
}).xor('userId','email'); // xor을 통해 userId와 email이 같이 입력되는 것을 막음
const validation = UserSchema.validate(user);
console.log(validation) 

{
  value: { userId: 'vlogue', password: '12345678', email: 'test@email.com' },
  error: [Error [ValidationError]: "value" contains a conflict between exclusive peers [userId, email]] {
    _original: { userId: 'vlogue', password: '12345678', email: 'test@email.com' },
    details: [ [Object] ]
  }
}

에.. 위 코드처럼 cotains a conflic 블라블라 ValidationError가 생기게 된다.

 

with와 without이 있는데, with는 a가 있는데 b가 없는 경우에 error가 발생하고

without은 a가 없는데 b가 있는 경우에 발생한다.

const user = {
	// userId: "vlogue",
    password: "12345678",
    email: "test@email.com",
}

console.log(validation) // error: [Error [ValidationError]: "userId" is required]

userId를 잠시 주석으로 처리하고 console.log를 실행시키면

userId가 필요하다고 나오게 된다.

 

그리고 마지막으로 when이 있는데, when은 key값에 조건을 달아 놓는 것이다.

const UserSchema = joi.object({
	userId: joi.string().min(4).max(20).required(),
    password: joi.string().min(8).max(20).required(),
    email: joi.string().email().required().when('userId', {
        is: joi.exist(),
        then: joi.string().required(),
        otherwise: joi.forbidden()
    })
})

UserSchema의 email값에 when이라는 조건을 달게된다면, when은 userId가 존재하는 경우에만

유효하게 되고, 없다면 ValidationError가 발생하게 된다.

console.log(validation) //  error: [Error [ValidationError]: "userId" is required]

이상으로 Joi에 대해서 알아본 시간이었다.

 

 

 

참조

https://gumpcha.github.io/blog/joi-overview

 

Joi, Javascript object schema validator

시작하기 API 수준이든, 함수 수준이든 외부 입력을 항상 validation하는 습관은 중요하다. 귀찮다고 빼 먹는다면 언젠가는 분명 문제를 일으킬 것이다. 많은 node용 validator가 있지만 Joi가 우수한 점

gumpcha.github.io

 

Comments