장바구니 데이터 처리(feat. 에러)

낄낄박사·2024년 9월 23일

Gotcha

목록 보기
21/22

장바구니 데이터를 추가할 때 객체 배열을 jsonb 필드와 비교하려는 시도 중 아래와 같은 에러가 발생:

selectError {
  code: '22P02',
  details: 'Token "object" is invalid.',
  hint: null,
  message: 'invalid input syntax for type json'
}
  • JSON.stringify()로 변환
    객체 배열을 JSON.stringify()로 변환하여 jsonb 필드와 비교하려고 했으나, 다음과 같은 새로운 에러가 발생:
selectError {
  code: '22P02',
  details: '"[" must introduce explicitly-specified array dimensions.',
  hint: null,
  message: 'malformed array literal: "[object Object],[object Object]"'
}

eq() 대신 contains() 사용

객체 배열을 부분적으로 비교하기 위해 contains() 메서드를 사용하여 객체 그대로 전달해봄. 똑같이 에러 발생

supabase에서 "carts"테이블의 options 타입 변경

타입을 jsonb가 아닌 일반 json으로 하여 다시 json 문자열로 변환하여 전달해도 동일.

문제의 원인

  • PostgreSQL에서 jsonb 필드를 배열로 정의한 것이 문제였음.
  • Supabase에서 Define as array 옵션이 활성화된 상태에서는, 배열 리터럴을 잘못 처리하여 malformed array literal 오류가남..

Supabase 테이블의 jsonb 필드 설정 수정

Supabase에서 jsonb 필드Define as array 옵션이 체크되어 있던 것을 해제하니, 객체 배열이 제대로 처리되기 시작..

jsonb 필드에 객체 배열을 그대로 전달

이후에는 jsonb 필드를 배열로 처리하지 않고 객체 배열을 직접 저장 및 비교할 수 있게 됨

export async function addProductsToCart(
  cartOptions: CartOption[]
): Promise<CartResponse[]> {
  const res = await Promise.all(
    cartOptions.map(async (opt) => {
      // 1. 동일한 상품, 사용자, 옵션이 있는지 확인 
      const { data: existingCart, error: selectError } = await supabase
        .from("carts")
        .select("*")
        .eq("userId", opt.userId)
        .eq("productId", opt.productId)
        .eq("options", opt.optionItems) 
        .single();

      if (selectError && selectError.code !== "PGRST116") {
        console.error("selectError", selectError);
        throw new Error(selectError.message);
      }

      // 2. 기존 항목이 있으면 수량 업데이트
      if (existingCart) {
        console.log("똑같은 거 있어!", existingCart);
        const { data: updatedCart, error: updateError } = await supabase
          .from("carts")
          .update({
            quantity: existingCart.quantity + opt.quantity,
            updatedAt: new Date().toISOString(),  // 업데이트된 시간 설정
          })
          .eq("id", existingCart.id)
          .select("*")
          .single();

        if (updateError) {
          console.error(updateError);
          throw new Error(updateError.message);
        }

        return updatedCart as CartResponse;
      }

      // 3. 기존 항목이 없으면 새로 삽입
      const { data, error } = await supabase
        .from("carts")
        .insert({
          userId: opt.userId,
          productId: opt.productId,
          quantity: opt.quantity,
          options: opt.optionItems,
          updatedAt: null,
        })
        .select("*")
        .single();

      if (error) {
        throw new Error(error.message);
      }

      return data as CartResponse;
    })
  );

  return res;
}

정리

    • Supabase에서 jsonb 필드를 배열로 정의한 것이 원인임.
    • cartOptions 데이터를 다루는 방식을 여러번 테스트 하였는데, 변경전 타입이 그대로 적용된 것이 문제.
    • 어쨌든 base에서 Define as array 옵션을 해제하고, jsonb 필드에 객체 배열을 그대로 전달
  1. 결과:
    • 객체 배열이 제대로 jsonb 필드에 저장되고, 동일한 항목이 있을 경우 수량과 업데이트 날짜만 조정되며, 없을 경우 새로운 항목이 추가되는 로직이 잘 구현 됨.

0개의 댓글