위 사진에서 볼 수 있는 것이 바로 Typewirter 타자기이다.
이 타자기에 종이를 끼워 넣고 원하는 문자를 누르면 활자가 튀어나가 종이에 잉크를 찍어낸다.
글자는 정확히 타자기의 중앙에 찍히며 종이가 정해진 간격만큼 왼쪽으로 움직이게 된다.
이때 이 종이를 움직이게 만드는 것이 바로 Carriage이다.
그리고 종이에 한 줄을 다 채우게 되면 다음 줄을 작성하기 위해서 종이를 위로 올려줘야 하는데 이 작업을 Line Feed라고 하는 것이다. 또한 종이가 단순히 위로 올라가기만 해서는 안된다. 종이를 다시 오른쪽 끝으로 보내줘야 한다. 이를 Carriage Return이라고 한다.
그래서 타자기에서 볼 수 있듯이 타입스크립트에서 빨간줄이 뜨는 에러는 이러한 코드를 작성해줘야 해결할 수 있다.
rules: {
'prettier/prettier': [
'error',
{
endOfLine: 'auto'
}
]
}
오늘은 주소 생성 및 수정 시 입력값 검증 로직을 작성하였습니다. 이 과정에서 Joi를 활용하여 스키마를 정의하고, 이를 기반으로 요청(Request)의 유효성을 검사하는 기능을 구현하였습니다. 주요 내용은 아래와 같습니다.
createSchema와 updateSchema 정의createSchema: 새로운 주소를 생성할 때 필요한 입력값을 검증하는 스키마를 정의하였습니다.
address: 필수 문자열addressName: 필수 문자열 MESSAGES 상수에서 가져옵니다.updateSchema: 기존 주소를 수정할 때 필요한 입력값을 검증하는 스키마를 정의하였습니다.
addressId: 필수 숫자address: 필수 문자열addressName: 필수 문자열 createAddressValidator 미들웨어createSchema를 통해 요청 바디(req.body)의 유효성을 검사합니다.req.user?.userId)가 존재하는지 확인합니다.MESSAGES.ADDRESS.COMMON.NOT_FOUND_USER 메시지를 반환하며 에러를 발생시킵니다.next()를 호출하여 다음 미들웨어로 진행합니다.updateAddressValidator 미들웨어updateSchema를 통해 요청 바디(req.body)와 URL 파라미터(req.params)를 결합한 데이터를 유효성 검사합니다.next()를 호출하여 다음 미들웨어로 진행합니다.Joi를 활용하여 간단하면서도 강력한 검증 로직을 구현할 수 있었습니다.다음 개선 사항
address와 addressName의 검증 로직)를 최소화하여 스키마를 더 간결하게 작성하는 방법을 탐구해야겠습니다.address-validator.middleware.js
import Joi from 'joi';
import { MESSAGES } from '../../constants/message.constant.js';
import addressRepository from '../../repositories/address.repository.js';
const createSchema = Joi.object({
address: Joi.string().trim().required().messages({
'any.required': MESSAGES.ADDRESS.COMMON.ADDRESS.REQUIRED,
'string.empty': MESSAGES.ADDRESS.COMMON.ADDRESS.REQUIRED,
}),
addressName: Joi.string().trim().required().messages({
'any.required': MESSAGES.ADDRESS.COMMON.ADDRESSNAME.REQUIRED,
'string.empty': MESSAGES.ADDRESS.COMMON.ADDRESSNAME.REQUIRED,
}),
});
const updateSchema = Joi.object({
addressId: Joi.number().required().messages({
'any.required': MESSAGES.ADDRESS.COMMON.NOT_FOUND_USER,
}),
address: Joi.string().trim().required().messages({
'any.required': MESSAGES.ADDRESS.COMMON.ADDRESS.REQUIRED,
'string.empty': MESSAGES.ADDRESS.COMMON.ADDRESS.REQUIRED,
}),
addressName: Joi.string().trim().required().messages({
'any.required': MESSAGES.ADDRESS.COMMON.ADDRESSNAME.REQUIRED,
'string.empty': MESSAGES.ADDRESS.COMMON.ADDRESSNAME.REQUIRED,
}),
});
export const createAddressValidator = async (req, res, next) => {
try {
await createSchema.validateAsync(req.body);
const userId = req.user?.userId || 0;
if (!userId) {
throw new Error(MESSAGES.ADDRESS.COMMON.NOT_FOUND_USER);
}
const userAddresses =
await addressRepository.getAllAddressesByUserId(userId);
if (userAddresses.length >= 5) {
return res.status(400).json({
message: MESSAGES.ADDRESS.CREATE.EXCEED_LIMIT,
});
}
next();
} catch (error) {
next(error);
}
};
export const updateAddressValidator = async (req, res, next) => {
try {
await updateSchema.validateAsync({
...req.body,
...req.params,
});
next();
} catch (error) {
next(error);
}
};