사용환경 : Next.js 15, Typescript, prisma 6.2.1, prostgresql 16
오류 원인
원인은 prisma.모델객체.create(/*저장객체*/)를 호출할 때 저장객체가 다음과 같은 경우일 때 발생한다.
1. null 이거나
2. 객체의 속성 중에 이름이 일치하지 않는 것이 있거나
3. 객체의 속성 중에 하나라도 형식이 일치하지 않는 것이 있거나
오류 원인 확인하기
저장하려는 객체를 콘솔에 출력해보면서 객체가 존재하는지 확인한다.
객체의 속성명이 일치하는지 확인한다.
형식이 일치하는지도 확인한다.
속성명도 문제가 없다면 형식을 출력해서 형식이 올바른지 확인한다.
async execute(menuCreateDto: MenuCreateDto): Promise<MenuCreatedDto | { message: string }> {
try {
// 1. DTO를 이용해 새 메뉴 엔티티 생성
const newMenu: Partial<Menu> = {
korName: menuCreateDto.korName,
engName: menuCreateDto.engName,
price: menuCreateDto.price,
description: menuCreateDto.description,
categoryId: menuCreateDto.categoryId,
regMemberId: "8e359789-c81f-4de1-9df5-4ef23db2d16e",
};
console.log("==DFMenuCreateUsecase()");
console.log("categoryId type : ", typeof newMenu.categoryId);
console.log("price type : ", typeof newMenu.price);
console.log("regMemberId type : ", typeof newMenu.regMemberId);
console.log("========================");
console.log("categoryId type : ", typeof newMenu.categoryId);
console.log("price type : ", typeof newMenu.price);
console.log("regMemberId type : ", typeof newMenu.regMemberId);
console.log("========================");
위의 코드는 formData 로 넘겨 받은 값들을 MenuCreateDto 형식의 menuCreateDto 객체로 넘겨받고 있다.
위의 코드를 실행해보면 메뉴의 price 형식이 number가 아니라 string 이라는 것을 확인할 수 있다.
그 이유는 클라이언트에서 멀티파트 formData로 넘겨 받는 데이터 또는 Rest API 방식으로 POST 된 데이터는 모든 속성이 string으로 전달되는 경우가 일반적이기 때문이다.
POST나 formData로 전달된 값을 사용할 때는 다음처럼 형식을 확인해서 형식을 적절히 변환해서 사용해야 한다.
다음 코드에서는 formData로 전달된 값에서 price와 categoryId 속성을 Number() 함수를 이용해서 string형식을 number 형식으로 변환해주고 있다.
// 1. DTO를 이용해 새 메뉴 엔티티 생성
const newMenu: Partial<Menu> = {
korName: menuCreateDto.korName,
engName: menuCreateDto.engName,
price: Number(menuCreateDto.price),
description: menuCreateDto.description,
categoryId: Number(menuCreateDto.categoryId),
regMemberId: "8e359789-c81f-4de1-9df5-4ef23db2d16e",
};
이 오류가 발생하던 당시, 오류를 찾는 과정(픽션)
prisma를 이용해서 데이터를 입력할 때 제목으로 언급한 오류가 발생했다.
그런데, 오류 메시지가 말해주는 것은 payload 형식이 올바르지 않다는 문구 뿐이었다.
이 오류 메시지만으로 원인을 찾기가 쉽지 않았다. 그래서 용의자(?)를 찾기 위해 코드 범위를 좁혀가는 방법을 사용했다.
오류 메시지의 전문을 다시 확인해보기로 했다.
오류 메시지 전문 :
prisma:info Starting a postgresql pool with 25 connections.
Error creating menu: TypeError: The "payload" argument must be of type object. Received null
at PrMenuRepository.save (file:....ts:28:20)
at async DfMenuCreateUsecase.execute (file:/....ts:28:24)
at async POST (file:...:30:19)
26 | return savedMenu;
27 | } catch (error) {
> 28 | console.error("Error saving menu:", error);
| ^
29 | throw new Error("메뉴 저장 중 오류가 발생했습니다.");
30 | }
31 | } {
code: 'ERR_INVALID_ARG_TYPE'
위의 메시지에서 오류의 시작은 save 함수라는 것을 확인할 수 있었다. 그래서 그 함수를 들여다 보기로 했다.
오류 관련 소스 코드
async save(menu: Menu): Promise<Menu> {
try {
console.log("==PrMenuRepository.save() / before create()", menu);
const savedMenu = await prisma.menu.create({
data: menu
});
console.log("==PrMenuRepository.save() / after create()", savedMenu);
return savedMenu;
} catch (error) {
console.error("Error saving menu:", error);
throw new Error("메뉴 저장 중 오류가 발생했습니다.");
}
}
혹시 몰라서 다음처럼 menu 값부터 출력해보았다.
console.log("==PrMenuRepository.save() / before create()", menu);
출력된 결과로 볼 때 데이터에는 아무런 문제가 없어보였다.
null 은 아닌데, 딱히 이유를 알 수가 없었다.
객체의 속성명도 문제가 없었기 때문이다.
혹시 몰라서 각 속성의 형식도 확인해보기로 했다.
그 결과 price 와 categoryId가 string으로 출력되는 것을 확인했다.
그래서 형식을 올바르게 수정 후 코드를 다시 시작했더니, 정상적으로 데이터가 등록되었다.
감사합니다.
출처: https://www.newlecture.com
뉴렉처에 오신 것을 환영합니다.
뉴렉처는 인공지능(AI) 프로젝트 전문 교육기관인
www.newlecture.com