Firebase를 이용한 커스텀 이커머스 구축

저는 처음부터 직접 커스텀 이커머스 사이트를 구축했습니다. 기성 플랫폼을 사용하지 않고, 대신 Firebase Realtime Database와 Netlify를 사용했습니다.

클라이언트는 특정한 설정이 필요했습니다. 가격 변동이 있는 제품 카탈로그와 관리자 패널을 원했습니다. 또한 영업팀이 사이트에서 직접 주문을 넣을 수 있어야 했습니다.

주요 기술적 과제들을 어떻게 해결했는지 소개합니다.

데이터 분리

이커머스 데이터베이스를 내부 관리용 데이터베이스와 분리했습니다. 이를 통해 상업적 데이터가 직원 급여나 예산과 같은 민감한 파일과 섞이는 것을 방지했습니다.

가격 책정을 위한 데이터 모델링

가격 플랜은 여러 제품에 걸쳐 반복되는 경우가 많습니다. 모든 제품 내부에 플랜 데이터를 중복해서 넣으면 업데이트할 때 매우 힘들어집니다.

  • 모든 플랜을 위한 글로벌 아카이브를 생성했습니다.
  • 각 제품은 플랜 ID의 배열만 보유합니다.
  • 이를 통해 업데이트 속도를 높이고 데이터 오류를 방지했습니다.

원자적 주문 번호 생성 (Atomic Order Numbering)

여러 사람이 동시에 주문을 할 때 레이스 컨디션(race condition)이 발생할 수 있습니다. 두 사용자가 동일한 마지막 주문 번호를 읽으면, 한 주문이 덮어씌워질 수 있습니다.

  • 이를 해결하기 위해 Firebase transactions를 사용했습니다.
  • runTransaction 함수는 많은 동시 접속자가 있더라도 번호가 정확하게 증가하도록 보장합니다.
  • 이를 통해 모든 주문이 고유한 번호를 갖도록 보장합니다.

안전한 관리자 액세스

소스 코드에 비밀번호를 저장하고 싶지 않았습니다. 또한 MD5와 같은 단순한 해시 방식도 피했습니다.

  • Web Crypto API를 통해 PBKDF2를 사용했습니다.
  • 이는 해시에 수천 번의 반복 작업을 적용합니다.
  • 해커들이 무차별 대입 공격(brute-force attacks)을 수행하기에 비용이 너무 많이 들게 만듭니다.
  • 코드에는 salt와 hash만 저장합니다.

'0' 버그 수정

가격이 0인 제품이 "가격 미정(price to be defined)"으로 표시되는 버그를 발견했습니다.

  • 이는 JavaScript가 0을 "falsy"로 취급하기 때문에 발생했습니다.
  • 로직을 변경하여 이를 수정했습니다.
  • "price || null" 대신 "price != null"을 사용했습니다.
  • 이를 통해 시스템이 0을 유효한 숫자로 인식하도록 했습니다.

CSP 설정

Firebase는 동적 서브도메인을 사용합니다. 콘텐츠 보안 정책(CSP)을 위한 표준 HTML meta 태그로는 이러한 와일드카드를 처리할 수 없습니다.

  • CSP를 HTML에서 Netlify HTTP 헤더로 옮겼습니다.
  • 이를 통해 와일드카드를 사용하여 Firebase 서비스가 올바르게 작동하도록 할 수 있었습니다.

커스텀 시스템을 구축하는 것은 단순히 코드를 작성하는 것 이상의 작업이 필요합니다. 운영 환경에서의 장애를 방지할 수 있는 아키텍처적 선택이 필요합니다.

출처: https://dev.to/androve2k/custom-e-commerce-on-firebase-catalog-atomic-orders-and-admin-panel-42ec