재고를 정확하고 최신 상태로 유지하는 것은 모든 대량 소매업체에게 매우 중요합니다. 웰케어와 Raf Pharmacy—카타르의 두 주요 약국 체인으로, 10,000개 이상의 SKU, 100개 이상의 오프라인 매장, 그리고 Shopify 웹 스토어, 모바일 앱, POS 시스템에서의 활발한 판매를 보유하고 있습니다—우리는 강력하고 실시간으로 ERP에서 Shopify로 재고 업데이트 솔루션을 구축했습니다. 아래에서 우리는 우리의 엔드 투 엔드 아키텍처, 코드 스니펫, 그리고 성능 결과를 공유합니다.
- 프로젝트 범위 및 도전 과제
- 1. 초기 접근: Shopify REST API
- 2. Migrating to Shopify GraphQL API
- 3. Architecture Overview
- 4. Fetching Current Inventory via GraphQL
- 5. Adjusting Inventory via GraphQL
- 6. Optimization Highlights
- 7. Performance Comparison
- 8. Technology and Tools
- 9. Wellcare 및 Raf Pharmacy의 이점
- 10. Frequently Asked Questions
프로젝트 범위 및 도전 과제
- 클라이언트: Wellcare Pharmacy와 Raf Pharmacy, 카타르
- 카탈로그 크기: 10,000+ SKU
- 판매 채널: Shopify 매장, 헤드리스 모바일 앱, 100개 이상의 오프라인 매장
- ERP: INNSOF ERP 재고 업데이트 전송
- 요구 사항:
- 과잉 판매를 방지하기 위한 실시간 동기화
- 높은 업데이트 볼륨에 대한 확장성
- 최소한의 API 대기 시간 및 오류
- 정확한 다중 위치 재고 처리
1. 초기 접근 방식: Shopify REST API
우리는 먼저 Shopify의 REST Admin API 엔드포인트 /admin/api/2024‑01/inventory_levels/set.json 를 사용하여 재고 업데이트를 푸시했습니다.
// Sample REST payload
$payload = [
'location_id' => $locationId,
'inventory_item_id'=> $inventoryItemId,
'available' => $newStock
];
$response = $this->shopifyService->restRequest('POST', "/inventory_levels/set.json", $payload);
REST API 제한 사항
- 일괄 업데이트 없음: 요청당 하나의 SKU
- 엄격한 비율 제한: ~초당 2회 호출 per 스토어 → 수천 개 SKU의 병목 현상
- 높은 대기 시간: 요청당 50–100 ms, 지연 누적
- 오류 발생 가능: 부하 하에서 빈번한 속도 제한 오류
2. Shopify GraphQL API로 마이그레이션하기
REST의 한계를 극복하기 위해 우리는 Shopify의 GraphQL Admin API로 전환하여 다음을 가능하게 했습니다:
- 배치 업데이트
inventoryAdjustQuantities변경 - 비용 기반 스로틀링 (REST보다 더 유연함)
- 필요한 필드만 요청하여 네트워크 오버헤드 감소
- 델타 기반 조정 (주식이 실제로 변경될 때만 업데이트)
3. 아키텍처 개요
- ERP → 미들웨어
- INNSOF ERP는 HTTP POST를 통해 우리의
StockController에 JSON 페이로드를 보냅니다.
- INNSOF ERP는 HTTP POST를 통해 우리의
- 정보 보강 및 로깅
- 우리는 요청을 파싱하고, 검증하며, 로컬 DB(
api_request_log)에 기록합니다. - 우리는 각 SKU에
location_id와inventory_item_id(캐시된 테이블에서)를 보강합니다.
- 우리는 요청을 파싱하고, 검증하며, 로컬 DB(
- 현재 재고 가져오기
- 위치 및 SKU별로 GraphQL을 통해 기존 재고 수준 가져오기.
- 델타 계산
- ERP 재고와 Shopify 재고를 비교하여
델타를 결정합니다.
- ERP 재고와 Shopify 재고를 비교하여
- 재고 조정
- 배치당 단일 GraphQL 변형을 전송합니다(최대 100개 SKU).
- 응답 처리
- 성공/실패를 기록하고 업데이트 상태를 ERP로 다시 전송합니다.
- 재시도 및 대체
- 자동화된 크론 작업이 실패한 배치를 재시도하며, 필요시 REST로 대체합니다.
4. GraphQL을 통한 현재 주식 가져오기
정확한 델타 계산은 기존 수량을 검색하는 것에서 시작됩니다. 우리는 쿼리당 최대 60개 항목 를 배치합니다:
query inventoryItems {
item1: inventoryItem(id: "gid://shopify/InventoryItem/123456789") {
id
tracked
sku
inventoryLevels(first: 10) {
edges {
node {
location { id name }
quantities(names: "available") {
quantity
}
}
}
}
}
# item2, item3… up to 60
}
우리의 PHP 메서드는 이를 배열로 수집합니다:
private function getCurrentStock(array $products): array {
$batches = array_chunk($products, 60);
$results = [];
foreach ($batches as $batch) {
// Build GraphQL query dynamically…
$response = $this->shopifyService->executeGraphQl($query, []);
// Parse `$response['data']` into $results[]
}
return $results; // [ ['inventory_item_id'=>…, 'location_id'=>…, 'quantity'=>…], … ]
}
5. GraphQL을 통한 재고 조정
현재 재고를 알게 되면, 우리는 델타 업데이트 페이로드를 준비합니다:
변이 템플릿
mutation AdjustMultipleInventoryQuantities($input: InventoryAdjustQuantitiesInput!) {
inventoryAdjustQuantities(input: $input) {
inventoryAdjustmentGroup {
createdAt
changes { name delta }
}
userErrors { field message }
}
}
PHP 변수 형식
$changes = [];
foreach ($updatedProducts as $p) {
$changes[] = [
'inventoryItemId'=> "gid://shopify/InventoryItem/{$p['inventory_item_id']}",
'locationId' => "gid://shopify/Location/{$p['location_id']}",
'delta' => $p['erp_stock'] - $p['current_stock']
];
}
$variables = [
'input' => [
'reason' => 'correction',
'name' => 'available',
'referenceDocumentUri' => 'logistics://erp/batch-2025-07-29',
'changes' => $changes
]
];
$response = $this->shopifyService->executeGraphQl($mutation, $variables);
이 단일 호출은 최대 100개의 SKU 를 한 번에 업데이트하여 네트워크 잡음을 크게 줄입니다.
6. 최적화 하이라이트
- 배치 및 청크: 읽기 시 60개 항목/쿼리; 쓰기 시 100개 항목/변경.
- 로컬 캐싱: 반복적인 조회를 피하기 위해 MySQL에
inventory_item_id와location_id를 저장하세요. - Delta Logic: 현재 재고가 ERP 재고와 다른 SKU만 업데이트하십시오.
- 요금 제한 인식: 전략적으로
sleep()/usleep()를 삽입하고 긴급 재시도를 위해 REST로 대체하십시오. - 강력한 로깅: 모든 요청 및 응답은
api_request_log및stock_update_log테이블에 기록됩니다.
7. 성능 비교
| 미터법 | REST API | GraphQL API |
|---|---|---|
| 배치 업데이트 지원 | ||
| 100개의 SKU당 평균 시간 | ~60 초 | ~5 초 |
| 비율 제한 오류 (부하 하에서) | 자주 | 희귀한 |
| 실시간 정확성 | 중간 | 높은 |
| ERP 피드백 통합 | 부분 | 전체, 기록됨 |
8. 기술 및 도구
- Shopify GraphQL Admin API
- PHP (StockController) 와
ShopifyService,LogManager,DBOps,ApiService - MySQL 로 로컬 캐싱 및 로그 저장
- INNSOF ERP 웹후크
- Cron Jobs 재시도 및 ERP 콜백용
9. Wellcare 및 Raf Pharmacy의 이점
실시간 재고 정확성 100개 이상의 매장 및 채널에서
제로 오버셀 및 원활한 고객 경험
높은 처리량: 시간당 수천 개의 SKU 업데이트
준수 및 디버깅을 위한 상세 감사 추적
웹 및 모바일 상점에서 개선된 SEO 및 UX
10. 자주 묻는 질문들
- 업데이트하기 전에 현재 재고를 가져와야 하는 이유?
올바른 델타를 계산하여 우발적인 덮어쓰기나 중복 조정을 방지합니다. - GraphQL은 배치에서 몇 개의 SKU를 처리할 수 있나요?
변경 사항당 최대 100개의 SKU와 쿼리당 60개, 상점 계획에 따라 구성 가능합니다. - REST와 GraphQL을 혼합할 수 있나요?
네. GraphQL이 제한될 때 중요한 업데이트를 위해 REST를 대체 수단으로 유지합니다. - 다중 위치 재고는 작동합니까?
절대적으로 그렇습니다. 우리는locationId를 사용하여 위치별 수준을 쿼리하고 업데이트합니다. - 이 접근 방식은 다른 ERP에 적응할 수 있나요?
네. 우리의 모듈형 디자인은 Odoo, SAP, Oracle 6i 등과 통합할 수 있습니다.
Seamedia 전자상거래 솔루션을 선택해야 하는 이유
Seamedia에서는 깊이 있는 Shopify 전문성과 강력한 ERP 통합 노하우를 결합하여 실제 비즈니스 결과를 이끌어내는 맞춤형 고성능 솔루션을 제공합니다. 경험이 풍부한 컨설턴트인 Prajosh VM이 이끄는 우리 팀은 다중 위치 재고, 높은 SKU 볼륨 및 옴니채널 소매의 복잡성을 이해하고 있습니다. 우리는 재고를 정확하게 유지하고 고객을 만족시키며 운영을 원활하게 하는 확장 가능한 API 기반 워크플로우를 설계합니다. 빠르게 성장하는 약국 체인, 전국 소매업체 또는 대기업 제조업체에 관계없이 Seamedia는 엔드 투 엔드 개발, 원활한 ERP 연결 및 24/7 지원을 제공합니다.
재고를 간소화하고 판매를 극대화할 준비가 되셨나요?
오늘 저희에게 연락해 주세요: hello@seamedia.in 또는 방문해 주세요: www.seamedia.in 어떻게 귀사의 맞춤형 실시간 재고 동기화 솔루션을 구축할 수 있는지 논의해 보겠습니다.