본문 바로가기

코딩(Coding)

나만의 전자 상거래 Keystone.js 기반 시스템 만드는 법 — 장바구니 만들기

반응형

나만의 전자 상거래 Keystone.js 기반 시스템 만드는 법 — 장바구니 만들기

 

자체 전자 상거래 시스템을 만들기 위한 여정의 다음 단계

Unsplash의 Kenny Eliason의 사진

얼마 전 저는 Kesytone.js를 사용하여 전자 상거래 시스템을 구축하겠다는 엉뚱한 생각을 했습니다. 이 여정은 몇 주 전에 시작되었으며 지금까지 시스템 요구 사항, 환경 설정 및 기본 모델, 액세스 제어에 대해 이야기했습니다. 이 기사에서는 주요 장바구니 기능에 중점을 두겠습니다. 또한 이 기사의 완성된 코드는 내 GitHub에서 사용할 수 있습니다.

이 시리즈의 이전 부분에서 기본 스키마를 설정할 때 각 사용자에게 장바구니가 하나만 있고 사용자가 해당 장바구니에서 주문을 생성할 때까지 추가된 모든 제품이 포함되도록 결정했습니다. 이를 기반으로 사용자는 장바구니에서 세 가지 작업을 수행할 수 있습니다. 먼저 장바구니에 항목을 추가한 다음 제거하고 수량을 변경할 수 있습니다.

또한 고려해야 할 한 가지 주요 문제가 있으며 이는 기술적인 문제보다 비즈니스에 더 가깝습니다. 사용자가 현재 사용 가능한 것보다 더 많은 제품을 장바구니에 추가하도록 허용해야 합니까? 내 말은, 예를 들어 제품에 재고가 있는 경우 4개의 항목을 사용할 수 있지만 사용자가 5개의 장바구니에 추가하려고 하면 이 경우 어떻게 해야 합니까?

물론 그 문제는 UI에서 보호되어야 하지만 어떤 경우에는 어쨌든 발생할 수 있습니다. SSR과 Next.js를 사용하는 것은 몇 가지 단점이 있는데 가장 기본적인 경우에는 페이지 렌더링 시에만 사용 가능한 제품의 수량을 확인합니다. 이로 인해 렌더링과 장바구니에 제품을 추가하는 시점 사이의 시간에 제품 가용성이 변경될 수 있습니다.

두 가지 주요 솔루션이 있습니다. 첫 번째는 이 경우 장바구니에 추가하는 것을 차단하거나 이 유효성 검사 단계를 앞으로 이동하고 제품이 품절된 주문 생성을 차단하는 것입니다. 우리의 결정에도 불구하고 이 단계는 보안 관점에서 필요합니다.

나는 이 문제에 대한 세 번째 해결책이 있다고 믿습니다. 앞서 언급한 두 가지 사이에 있는 것입니다. Stock 스키마에는 다음 배송에 대한 정보가 포함되어 있으므로 재고 항목이 충분하지 않지만 함께 있으면 사용자가 장바구니에 추가할 수 있습니다. 그러나 그것 때문에 주문이 지연될 것입니다.

반면 다음 배송 정보가 없으면 차단됩니다. 이 솔루션은 더 나은 사용자 유지를 보장해야 하며 더 중요한 것은 구현하는 것이 더 흥미로울 것입니다.

그 과정에서 우리는 이 세 가지 작업 각각에 집중할 수 있습니다. 먼저 장바구니에 제품을 추가합니다. 기본적으로 두 단계가 있습니다. 장바구니에서 재고를 확인하고 제품을 업데이트합니다. 수량을 업데이트할 때도 마찬가지입니다. 제품 제거는 장바구니 모델의 업데이트일 뿐입니다. 정확히. 우리의 모습을 살펴보자 Cart 개요:

에 관련이 있다 Product 목록에 있지만 추가된 제품의 수량에 대한 정보를 저장할 수 있는 방법이 없습니다. 따라서 다대다 관계를 처리하고 수량 정보를 저장하기 위해 중간 목록(SQL 명명법에서는 피벗 테이블이라고 함)을 만들어야 합니다.

이 목록의 주요 목적은 다음 간의 관계를 저장하는 것입니다. Cart 그리고 Product 엔티티 및 수량 정보. 기본적으로 다음과의 관계로만 요청해야 합니다. Cart. 직접 요청하는 것은 의미가 없습니다. 만들자 cart-product.schema.ts:

하지만 잠깐, 필드가 두 개뿐인가요? 간단합니다. 이 목록은 다음 항목에 대해 알 필요가 없습니다. Cart 또는 이러한 제품이 속한 항목. 그러나 다른 한편으로는, Cart 모델에는 이 정보가 필요하므로 이 목록을 업데이트하고 관계를 다음에서 변경해야 합니다. Product 에게 CartProduct. 또한 더 이상 관리 UI에서 이 엔터티를 만들 가능성을 숨길 필요가 없습니다.

products: relationship({
ref: 'CartProduct',
many: true,
}),

이제 흐름을 업데이트할 수 있습니다.

  • 장바구니에 추가:
    1. 재고 확인
    2. 만들기 CartProduct 엔티티
    3. 업데이트 Cart 모델
  • 장바구니에서 제품 제거:
    1. 제거 CartProduct 실재
    2. 업데이트 Cart
  • 장바구니 수량 변경:
    1. 재고 확인
    2. 업데이트 CartProduct 실재
    3. 업데이트 Cart

하지만 왜 그 모든 문제가 발생합니까? 데이터베이스의 현재 ER 다이어그램을 살펴보겠습니다.

우리는 우리의 Cart, CartProduct그리고 Product 테이블도 있지만 _Cart_products 테이블. 우리가 마지막을 만들지 않았습니까? Undelaying Prisma는 우리를 위해 그렇게 했습니다. 그렇기 때문에 우리가 사용하는 도구에 대한 기본적인 이해가 있는 것이 좋습니다.

Prisma는 명시적 또는 암시적 다대다 관계(자세한 내용은 문서 참조)를 만드는 두 가지 방법이 있습니다. 첫 번째 단계에서 우리는 피벗 테이블과 다른 테이블의 관계를 생성하는 일을 담당합니다. schema.prisma 파일. 두 번째 방법에서는 피벗 테이블을 건너뛰고 ORM에서 생성합니다.

그러나 우리의 경우 우리는 schema.prisma 파일; Keystone은 이를 처리하고 암시적 방법을 사용합니다. 대부분의 경우 완벽하지만 때로는 여기에 불필요한 테이블과 같은 몇 가지 단점이 있을 수 있습니다.

프레임워크는 일반적으로 두꺼운 추상화 계층 아래에 많은 구현 세부 정보를 숨기며, 이는 대부분의 경우 좋은 일입니다. 개발자가 집중할 수 있도록 business 더 빠르고 효율적으로 로직을 처리할 수 있습니다. 그러나 어떤 경우에는 몇 가지 문제를 받아들여야 합니다.

각 카트 작업과 관련된 모든 단계를 수행하려면 업데이트하는 동안 추가 유효성 검사를 포함하여 일부 부작용을 수행할 수 있는 도구가 필요합니다. Cart 개요. 다행히 Keystone에는 이를 위한 완벽한 도구가 있습니다.

거기 Hooks API, 이는 전체 스키마 또는 그 안의 특정 필드에 대해 정확히 수행합니다. 그 중 다섯 가지가 있습니다.

  • resolveInput 생성 또는 업데이트 작업에 대한 유효성 검사 전에 입력 데이터를 수정할 수 있습니다.
  • validateInput 그리고 validateDelete 생성/업데이트 및 삭제 작업에서 각각 추가 유효성 검사 오류를 반환할 수 있는 가능성을 제공합니다.
  • beforeOperation 데이터베이스 작업 전에 부작용을 처리합니다.
  • afterOperation 동일한 작업을 수행합니다.

문서에서 후크에 대해 자세히 읽어보세요.

좋아, 우리 시스템으로 돌아가자. 전체 흐름은 보기보다 간단합니다. 두 개의 후크만 사용하면 됩니다(세 번째는 보너스입니다). 먼저 다음을 가정해 봅시다. updateCart 돌연변이에는 현재 장바구니에 있는 모든 제품이 있어야 합니다(이전에도 추가됨). 그렇게 하면 제품 목록을 제출할 때 장바구니 콘텐츠가 이 목록으로 설정됩니다. 빈 목록이 있으면 장바구니 내용이 지워지고, 상품 목록이 없으면 장바구니 내용이 변경되지 않습니다. 예를 들어 돌연변이는 다음과 같아야 합니다.

그것을 처리하기 위해 우리는 모든 것을 제거해야합니다 CartProduct 엔터티를 만들고 업데이트할 때마다 새 항목을 추가합니다. 그렇게 하려면 다음을 사용해야 합니다. beforeOperation 후크 Cart 개요:

매우 간단합니다. 업데이트 변형에 제품이 있으면 현재 추가된 모든 제품을 쿼리하고 제거합니다. 그 후 현재 작업은 새/업데이트된 재고가 있는 모든 해당 제품을 다시 추가합니다. 또한 데이터가 해결되고 제품 목록이 비어 있으면 장바구니 내용이 지워집니다.

좋습니다. 장바구니 콘텐츠 업데이트에 대한 부분이지만 재고 확인은 어떻습니까? 그 전에 하지 말았어야 했어? 예, 하지만 다음에서 발생해야 합니다. CartProduct 스키마가 아닌 장바구니에 직접 담습니다. 우리는 추가 할 것입니다 validateInput 훅:

여기에서 각 제품의 재고를 확인하고 요청한 금액을 다음 배송의 합산 재고 및 수량과 비교합니다. 충분하지 않으면 전화를 겁니다. addValidationError 유효성 검사 오류를 생성하는 함수입니다. 이 방법은 거의 완벽합니다. 단 하나의 문제가 있습니다. CartProduct 엔터티는 장바구니가 업데이트되기 전에 생성되며 유효성 검사 오류가 발생하면 Cart 엔터티가 업데이트되지 않습니다.

그러나 첫 번째 스키마의 일부 행은 이미 생성되었을 수 있으며 CartProduct 테이블. 트랜잭션을 사용해야 하는 경우의 완벽한 예이지만 현재로서는 Keystone에 그런 옵션이 없습니다. 이 문제에 따르면 가까운 시일 내에 변경될 수 있습니다.

마지막 보너스 훅은 어떻습니까? 에 Cart있다 sum 전체 장바구니 값에 대한 정보가 포함된 필드이며 이를 계산할 방법이 필요합니다. 그만큼 resolveInput 후크가 가장 잘 작동합니다.

이 카트와 관련된 모든 제품을 가져와서 금액과 가격을 합산합니다. 그 후 데이터베이스에 저장할 데이터가 업데이트됩니다.

이제 전자 상거래 시스템의 장바구니 부분을 완료했습니다. 솔직히 말해서, 애플리케이션의 이 부분은 내가 처음에 예상했던 것보다 개발하기가 더 어려웠습니다. 그러나 또한 구현은 그렇게 어렵지 않았습니다. 대부분의 작업은 문제 자체가 아니라 그 문제를 해결하기 위한 최선의 방법을 생각하는 것이었습니다.

여러 가지 이유로 계획보다 시간이 오래 걸렸고 마음에 드셨으면 합니다. 질문이나 의견이 있으면 언제든지 질문하십시오.

사이드 프로젝트에는 한 가지 불쾌한 특성이 있습니다. 처음에는 흥미롭고 흥미롭지만 몇 가지 작업 후에는 더 이상 그런 느낌이 들지 않습니다. 그리고 그것이 내가 이 부분을 쓰는 데 그렇게 오랜 시간이 걸린 이유라고 생각합니다.

오해하지 마세요. 저는 여전히 이 시리즈를 끝내고 이 시스템을 구축할 계획이지만, 재미를 잃지 않고 다음 기사에서 귀찮은 일이 되지 않도록 하기 위해 휴식을 취하고 다른 것에 대해 씁니다.

거기서 보자!

반응형