Project_xxx

[Project_] FO - 2 (Trouble Shooting)

wakelight23 2024. 12. 6. 22:06

고유 제약 조건 위반 - P2002

- 처음보는 에러... 어떤 에러일까?

 

Error Log ▼

Invalid `prisma.inventory.update()` invocation:

code: 'P2002',
  clientVersion: '6.0.1',
  meta: {
    modelName: 'Inventory',
    target: 'Inventory_managerId_teamMemberId_isEquipped_key'
  }
}

 

● 왜 발생했는가

  - 아이템 장착에 대한 기능을 구현하던 중에 발생한 에러

  - 데이터베이스를 정의할 때 설정해둔 Unique 제약 조건이 존재

      → 'Inventory_managerId_teamMemberId_isEquipped_key' 

  - 해당 제약 조건을 위반 했을 때 해당 에러가 발생함

      → managerId, teamMemberId, isEquipped 필드의 조합이 고유해야 함

  - 동일한 매니저(managerId)의 동일한 팀 멤버(teamMemberId)에 대해 이미 장착된
    아이템이 존재할 때 또 다른 아이템을 장착 시도를 하여 에러 발생

      → 데이터베이스 설계상 한 멤버가 동시에 하나의 아이템만 장착하도록 제한되어 있음

teamMemberId를 할당해버렸다...

● 어떻게 해결했는가?

  - 아이템 장착 로직에 기존에 장착된 아이템을 해제하지 않고 새 아이템을 장착하려고 시도하여
    해당 에러가 발생한 것이다

await prisma.$transaction(async (tx) => {
  // 기존 장착 아이템 해제
  await tx.inventory.updateMany({
    where: {
      managerId: manager.managerId,
      teamMemberId: Number(teamMemberIds[i]),
      isEquipped: true,
    },
    data: {
      isEquipped: false,
      teamMemberId: null,
    },
  });

  // 새 아이템 장착
  await tx.inventory.update({
    where: {
      inventoryId: Number(itemIds[i]),
    },
    data: {
      isEquipped: true,
      teamMemberId: Number(teamMemberIds[i]),
    },
  });
});

- 위의 코드 처럼 트랜잭션으로 기존 아이템을 해제 후 장착이 가능하도록 코드를 수정

 

● 해결이 되었는가?

{
	"message": "아이템이 성공적으로 장착되었습니다."
}

 

- Insomnia 앱으로 API를 실행했을 때 성공적으로 작동함

 

● 혹시나 Error를 방지하여...

if (
            error &&
            typeof error === 'object' &&
            error.constructor &&
            error.constructor.name === 'PrismaClientKnownRequestError'
        ) {
            if (error.code === 'P2002') {
                return res.status(409).json({
                    error: '이미 장착된 아이템이 있습니다. 먼저 해제해 주세요.',
                });
            }
            // 다른 Prisma 관련 에러 처리
            return res.status(400).json({
                error: '데이터베이스 작업 중 오류가 발생했습니다.',
            });
        }
        // 기타 예상치 못한 에러
        res.status(500).json({ error: '서버 내부 오류가 발생했습니다.' });

- 예기치 않은 에러가 발생하여 서버가 작동 중지되는 것을 막기 위해 추가적으로 에러 처리를 했다.

 

● 결론

 - 데이터베이스를 정의할 때 여러 상황을 고려하여 정의해야할 거 같다.

 

 - 세밀한 설정으로 코드를 작성하던 도중에 데이터베이스를 재정의하는 일이 없도록
   기획단계에서 자세하게 계획해야겠다는 교훈을 얻었다.