본문 바로가기
Coding

높은 수준의 관점에서 전자 상거래 웹 사이트 디자인하는 방법

by Jakegyllenhaal 2022. 4. 19.
반응형

높은 수준의 관점에서 전자 상거래 웹 사이트 디자인하는 방법

 

소프트웨어 아키텍처 모자를 쓰세요

Unsplash의 Yang Deng 사진

지난 2주 동안 건축가 모임이 있었습니다. 전자 상거래 웹 사이트에 실제로 규칙적인 패턴이 있다는 이야기를 했습니다. 높은 수준의 디자인을 빠르게 제공하고 싶다면 어떻게 하시겠습니까?

이 기사는 그 토론의 기록이며, 나는 나의 인상을 바탕으로 우리의 아이디어를 나열한 다음 이 고전적인 디자인 패턴에 대한 건축가의 생각을 제시할 것입니다.

일반적으로 시작 시스템이나 아키텍처의 경우 모놀리스로 시작하는 것이 좋습니다. MVP(최소 실행 가능한 제품)를 구성한 후 아키텍처는 기능 및 비기능 요구 사항에 따라 진화하여 몇 년 전에 마이크로 서비스 또는 더 인기 있는 서비스 지향 아키텍처로 분해해야 하는지 확인합니다.

그러나 어떤 경우에도 아이디어의 빠른 출시와 검증을 위한 기반으로 모놀리스가 있을 것입니다.

하지만 전자상거래 사이트의 경우 기능보다는 상품과 노출 전략이 전자상거래 사이트의 성패를 좌우하기 때문에 빠른 검증이 필요하지 않다. 따라서 전자 상거래 사이트의 경우 예측 가능한 미래에 직면하게 될 문제를 해결할 수 있는 것이 더 중요합니다.

다음은 몇 가지 실용적인 예입니다.

사용자의 급속한 성장에 따라 사용자 관리에 대한 수요가 크게 증가할 것이므로 개발 주기의 빠른 반복을 용이하게 하기 위해 사용자 관련 기능을 별도의 서비스로 만드는 것이 필요합니다.

인벤토리, 사이트의 사용자 수가 증가함에 따라 제품 관련 기능이 대부분의 트래픽을 유도합니다. 고객은 항상 사이트에서 원하는 제품을 찾고 인벤토리를 확인하므로 많은 트래픽을 처리하려면 자체적으로 수평으로 확장할 수 있어야 합니다. 따라서 인벤토리도 독립형 서비스가 됩니다.

전자상거래 웹사이트의 또 다른 핵심 기능은 구매 및 주문 관리입니다. 고객이 주문을 하면 현금흐름, 물류 등 외부 서비스를 배후에서 통합해야 하고, 서로 다른 현금흐름을 연결하는 등 새로운 기능을 지속적으로 구현해야 한다. 그러나 이 개발 주기는 사용자 관련 기능과 분명히 다르며 테스트 및 통합의 필요성은 사용자 서비스와 완전히 다릅니다. 즉, 주문도 서비스가 되어야 합니다.

마지막으로 기본 도메인 서비스를 다음과 같이 정의합니다.

이전 섹션에서 사용자, 주문 및 인벤토리의 세 가지 독립적인 서비스가 있다고 언급했습니다. 그런 다음 우리는 그들이 사용해야 할 데이터베이스를 결정해야 했습니다.

이제 막 시작하는 시스템의 경우 다양한 사용 사례를 고려하면서 항상 팀이 가장 잘 알고 있는 가장 성숙한 기술을 사용하는 것이 좋습니다.

이러한 이유로 MySQL은 강력한 일관성이 필요한 Order Service 및 Inventory Service와 같은 서비스에 가장 적합한 선택이 되어야 한다고 생각합니다. MySQL은 수평적 확장성 부족으로 항상 비판을 받아왔지만 최근 몇 년 동안 새로운 돌파구가 많이 생겼고 점점 더 분산된 SQL이 등장하고 있습니다. 전자 상거래 사이트의 트래픽이 병목 현상이 발생하면 MySQL에서 분산 SQL로 마이그레이션하는 데 따른 고통이 크지 않을 것이며 결국 응용 프로그램을 거의 수정할 필요가 없을 것입니다.

사용자 서비스의 경우 이것이 더 흥미롭습니다. 사용자 관련 관리 기능은 일반적으로 강력한 일관성 요구 사항이 없으며 사용자 정보 및 기타 데이터 구조가 다양하고 풍부합니다. 문서 기반 데이터베이스인 MongoDB는 다양한 종류의 풍부한 데이터 표현을 지원할 수 있으며 많은 관리 편의성을 제공합니다. 물론 사용자 서비스에 MySQL을 사용할 수도 있지만 데이터 정규화에 약간의 노력이 필요합니다.

게다가, 사용자 서비스를 구현하기 위해 MongoDB를 사용한다면, 예를 들어 고객에게 할인 쿠폰을 제공하려는 경우와 같이 미래에 강력한 일관성이 필요하더라도 MongoDB에도 트랜잭션이 있기 때문에 MongoDB는 여전히 충분한 강력한 일관성 보장을 제공할 수 있습니다. . 그러나 MongoDB 트랜잭션은 코딩하기가 쉽지 않아 개발 노력이 증가할 것이라고 말해야 합니다.

이제 우리는 그들의 도메인을 담당하는 3개의 서비스가 있습니다. 하지만 서로 어떻게 통신합니까? 예를 들어 고객이 제품을 선택한 다음 주문, 청구 및 배송을 발송할 때 세 가지 서비스는 시나리오를 완료하기 위해 서로 통신해야 합니다.

제 관점에서는 이 세 가지 서비스를 비동기식으로 사용하는 것이 좋습니다. 전체 프로세스가 일관성을 보장해야 구현 노력이 크게 증가하지만 비동기화만이 고가용성 및 높은 확장성을 허용할 수 있습니다. 가용성과 확장성은 전자 상거래 사이트를 운영하기 위한 필수 비기능적 요구 사항입니다.

예를 들어 블랙프라이데이 프로모션에서 많은 고객이 웹사이트로 달려가 많은 주문을 하고 세 가지 서비스가 동시에 서로 통신한다고 가정하면 세 가지 서비스가 동일한 비율로 확장되어야 합니다. , 그것은 분명히 비합리적입니다.

또한 세 가지 서비스 모두에서 주문을 처리해야 하고 그 중 하나가 일시적으로 실패하거나 네트워크가 일시적으로 다운되면 전체 주문이 실패합니다. 즉, 비동기 통신을 통해서만 전자상거래 사이트에 필요한 가용성과 확장성을 확보할 수 있습니다.

이 시점에서 우리는 시스템 아키텍처의 프로토타입을 가지고 있었습니다.

그러나 아직 결정하지 못한 한 가지 구성 요소가 있는데, 그것은 비동기화를 위해 어떤 종류의 대기열 시스템을 사용해야 하는지입니다. 제 생각에는 Kafka. 다음과 같은 순수 메시지 대기열을 사용하지 않는 이유는 무엇입니까? RabbitMQ? 한 가지 중요한 이유는, Kafka 프로모션 이벤트에서 많은 트래픽을 처리할 때 처리량이 더 높습니다.

또한 주문 및 지불과 같은 행동은 순차적이라는 것을 우리 모두 알고 있습니다. 많은 수의 메시지가 대기열을 채우는 동안 메시지 순서를 유지하려면 다음을 통해 수평으로 확장해야 합니다. Kafka의 소비자 그룹을 사용하여 메시지를 더 빠르고 동시에 순서대로 처리할 수 있습니다.

간단한 시스템 아키텍처가 확보되면 전체 주문 배치 프로세스를 스케치하기 시작합니다.

처음에 고객은 재고 서비스에 주문을 하고 재고 서비스는 재고 관련 작업(예: 재고 사전 공제)만 처리합니다. 결제 전 재고를 줄이는 목적은 다수의 사용자가 소비할 때 경쟁을 피하기 위한 것으로, 실제로 마지막 단계까지 재고가 줄어들지 않으면 소비자가 공기를 살 위험성이 높다.

재고 서비스가 처리를 완료하면 주문 서비스가 전체 거래를 인수했음을 알리고 고객에게 주문이 접수되었음을 알립니다. 이 순간에는 주문만 성립되며, 고객이 주문 서비스와 제대로 통신하여 결제를 진행할 수 있도록 결제가 프런트엔드를 통해 리디렉션되어야 합니다.

결제가 완료되면 주문 서비스에서 사용자 서비스에 알립니다. 그러면 사용자 서비스는 쿠폰 발행이나 사용자 레벨 업그레이드와 같은 사용자 관련 작업을 진행할 수 있습니다. 마지막으로 재고 서비스와 주문 서비스에 거래가 성공적으로 완료되었음을 알립니다.

또는 주문 서비스 또는 사용자 서비스에 오류가 있는 경우 다른 참여 서비스에 알리는 메시지를 보내야 합니다. 그러면 알림을 받는 서비스가 그에 따라 처리할 수 있습니다. 예를 들어 인벤토리 서비스는 사전 감소된 인벤토리를 다시 추가해야 합니다.

내 기사를 구독하는 독자는 이것이 매우 일반적인 분산 트랜잭션임을 알았어야 하며 분산 트랜잭션에 대한 적절한 접근 방식은 항상 탄력적, 즉 오류에 대한 탄력성을 유지하는 것입니다.

이전 기사에서 설명한 것처럼 이벤트 중심 아키텍처에서 분산 트랜잭션을 처리하려면 중재자(crontab)가 필요합니다. crontab은 올바르게 처리되지 않은 이벤트를 주기적으로 감지하고 해당 조치를 취하여 복구합니다.

구체적인 내용은 이 글에서 다시 설명하지 않겠습니다. 그러나 세 가지 도메인 서비스 외에도 전체 워크플로를 모니터링하는 또 다른 서비스가 있음을 알 수 있습니다.

전체 트랜잭션 프로세스가 비동기식이기 때문에 사용자는 주문 상태가 무엇인지, 어떤 단계에 있는지 등을 정확히 알 수 있어야 합니다. 따라서 각 서비스에서 보낸 메시지를 구독하고 모든 트랜잭션의 상태를 기록하고 저장할 자체 데이터베이스를 갖는 서비스도 필요합니다.

이 접근 방식을 CQRS라고도 합니다. 전체 워크플로는 독립 실행형 도메인 간 서비스를 통해 관찰되지만 중재자와 달리 이 관찰자는 실제로 워크플로에 참여하지 않으며 워크플로를 변경하지도 않습니다.

관찰자는 고객이 워크플로에 대한 적절한 개요를 얻을 수 있도록 하기 위해서만 존재합니다.

전자 상거래 웹 사이트는 모든 백엔드 아키텍처의 교과서로 간주될 수 있습니다. 백엔드 엔지니어가 처리해야 하는 모든 종류의 문제는 전자 상거래 웹 사이트에 나타나지만 현재 시중에 나와 있는 책은 종종 모놀리식 솔루션만 제공하고 이러한 기능 요구 사항을 구현하는 방법에 중점을 둡니다.

그러나 백엔드 전문가로서 우리 모두는 전자 상거래 사이트를 운영하기 위해 모놀리스를 사용하는 것이 궁극적으로 막다른 골목이라는 것을 알고 있습니다. 제품이 완전히 판매 불가능한 경우가 아니면 조만간 트래픽 및 가용성 문제에 직면하게 될 것입니다.

이 기사는 건축가들 사이의 우연한 대화이지만 실제로는 일상 생활에서 마주하는 어려움을 다른 관점에서 살펴보는 것입니다. 스타트업 전자 상거래 사이트에 5가지 서비스가 필요한 이유는 무엇입니까?

  • 새로운 기능을 더 빨리 추가하고 독립적인 통합 및 테스트 프로세스를 가지려면 마이크로서비스를 도메인으로 분할해야 합니다.
  • 고가용성과 확장성을 갖기 위해서는 도메인 간의 결합을 줄여야 합니다.
  • 더 나은 내결함성을 위해 탄력적인 오류 복구 메커니즘을 설정해야 합니다.
  • 더 나은 사용자 경험을 위해서는 전체 그림의 포괄적인 표현이 구현되어야 합니다.

이전에 저는 마이크로서비스의 원죄, 1부 및 마이크로서비스의 원죄, 2부와 같이 마이크로서비스의 단점을 자주 언급했습니다.

하지만 그렇다고 해서 내가 마이크로서비스를 완전히 거부하는 것은 아니며, 오히려 우리 모두가 성배가 아니라 악마로서가 아닌 올바른 태도로 마이크로서비스에 직면할 수 있기를 바랍니다.

올바른 절충안은 항상 소프트웨어 아키텍처의 가장 중요한 핵심 개념입니다.