안녕하세요 예옹이입니다~
이번 웹프로젝트에서 제가 맡은 메뉴는 한번에 54개의 컬럼을 작업해주어야했습니다.
컬럼 값이 너무 많아 애초에 서버에서 schema를 나눠서 클라이언트로 줄까 생각했지만,
한번에 기본값으로 길게 주되 받고나서 그 값을 나누는 작업을 서버에서 진행해보고 싶었습니다!
const schema = z.object({
id: z.string().optional(),
accidentMgmtNo: z.string().min(1, { message: '사고관리번호를 입력해주세요.' }),
companyBusinessRegistrationNo: z.string({ required_error: '사업자등록번호를 입력해주세요.' }),
companyId: z.string({ required_error: '회사를 선택해주세요.' }),
companyName: z.string().min(1, { message: '회사명을 입력해주세요.' }),
companyEmployeeCnt: z.string().min(1, { message: '근로자수를 입력해주세요.' }),
companyIndustryType: z.object({
id: z.string().min(1, { message: '업종을 선택해주세요.' }),
name: z.string(),
}),
companyAddress1: z.string().min(1, { message: '주소를 입력해주세요.' }),
companyAddress2: z.string().nullable().optional(),
...
writerContact: z.string().min(1, { message: '작성자 연락처를 입력해주세요.' }),
submissionDate: z.string().min(1, { message: '작성일을 입력해주세요.' }),
industrialAccidentEmployer: z.object({
id: z.string().min(1, { message: '사업주를 선택해주세요.' }),
name: z.string(),
}),
industrialAccidentWorkerRepresentative: z.object({
id: z.string().min(1, { message: '근로자대표를 선택해주세요.' }),
name: z.string(),
}),
isElectronicSignature: z.enum(['Y', 'N']).default('N'),
injuryTypes: z.string().optional(),
injuryParts: z.string().optional(),
customInjuryTypes: z.string().optional(),
customInjuryParts: z.string().optional(),
});
그래서 이렇게 긴 스키마에서 필요한 부분만 가져오고 싶을때는
const injurySchema = schema.pick({
injuryTypes: true,
injuryParts: true,
customInjuryTypes: true,
customInjuryParts: true,
});
schema.pick() 을 하면 원하는 값만 가져올 수 있습니다.
마찬가지로 원하지 않는 부분을 제외해서 가져오고 싶을때는
const industrialAccidentSchema = schema.omit({
injuryTypes: true,
injuryParts: true,
customInjuryTypes: true,
customInjuryParts: true,
})
schema.omit() 을 하면 원하지 않는 값은 제외하고 가져올 수 있습니다.
그리고 복잡한 유효성 검사가 필요할 시에는 기존 schema에 검사를 진행하고
그 스키마에 .pick() 혹은 .omit()을 하면 될 줄 알았는데 에러가 발생할겁니다.
그럴땐 기존 스키마를 처리해서 만든 새 변수에 유효성 검사를 진행하면 됩니다.
const industrialAccidentSchema = schema
.omit({
injuryTypes: true,
injuryParts: true,
customInjuryTypes: true,
customInjuryParts: true,
})
.superRefine((data, ctx) => {
if (data.isInhouseContractor === 'Y') {
if (!data.contractorName) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ['contractorName'],
message: '사내수급인 소속일 경우 원도급인 사업장명은 필수입니다.',
});
}
if (!data.contractorAccidentMgmtNo) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ['contractorAccidentMgmtNo'],
message: '사내수급인 소속일 경우 사업장 산재관리번호는 필수입니다.',
});
}
}
if (data.isDispatchedWorker === 'Y') {
if (!data.dispatchEmployerName) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ['dispatchEmployerName'],
message: '파견근로자일 경우 파견사업주 사업장명은 필수입니다.',
});
}
if (!data.dispatchAccidentMgmtNo) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ['dispatchAccidentMgmtNo'],
message: '파견근로자일 경우 사업장 산재관리번호는 필수입니다.',
});
}
}
});
만약 action에서 새롭게 처리한 두가지 스키마를 모두 활용하고싶어서
export const actions = {
default: async ({ locals: { db }, request }) => {
const form = await superValidate(request, zod(industrialAccidentSchema));
const injuryForm = await superValidate(request, zod(injurySchema));
이렇게 request를 2번 요청하면 에러가 발생합니다.
그럴땐
export const actions = {
default: async ({ locals: { db }, request }) => {
const formData = await request.formData();
const form = await superValidate(formData, zod(industrialAccidentSchema));
const injuryForm = await superValidate(formData, zod(injurySchema));
새로운 변수(formData)로 request를 받고 superValidate를 진행하면 됩니다
출처
https://zod.dev/README?id=pickomit
GitHub - colinhacks/zod: TypeScript-first schema validation with static type inference
TypeScript-first schema validation with static type inference - colinhacks/zod
github.com
FAQ
FAQ I see the data in $form, but it’s not posted to the server? The most common mistake is to forget the name attribute on the input field. If you’re not using dataType: 'json' (see nested data), the form is treated as a normal HTML form, which require
superforms.rocks
'⚙️백엔드 : Backend > DataBase' 카테고리의 다른 글
[QueryDSL] CaseBuilder 활용 조건식 표현 (1) | 2025.06.16 |
---|---|
mysql connect 안되는 에러 해결(DataGrip/DBeaver) (3) | 2025.03.19 |
Raw SQL 쿼리를 Sequelize ORM 쿼리로 바꾸는 방법 (3) | 2024.09.14 |
SQL ) event_scheduler를 바로 등록시키는 방법 (2) | 2024.08.28 |
mysql workbench 사용법 | 맥 | macOS (3) | 2024.05.17 |