마젠토 2 API 사용법: 완벽한 이커머스 통합 가이드 (2026년)

@apidog

@apidog

25 March 2026

마젠토 2 API 사용법: 완벽한 이커머스 통합 가이드 (2026년)

TL;DR

Magento 2(Adobe Commerce) API는 개발자들이 전자상거래 상점과 프로그램적으로 통합할 수 있도록 지원합니다. OAuth 1.0a 및 토큰 기반 인증을 사용하여 REST, SOAP, GraphQL 엔드포인트를 제공하며, 제품, 주문, 고객, 재고 등에 접근할 수 있고, 속도 제한을 설정할 수 있습니다. 이 가이드에서는 인증 설정, CRUD 작업, 웹훅, 커스텀 엔드포인트 및 운영 환경 통합 전략에 대해 다룹니다.

소개

Adobe Commerce(Magento)는 연간 총 상품 가치 1,550억 달러 이상을 자랑하며 25만 개 이상의 전자상거래 상점을 운영하고 있습니다. 전자상거래 통합, ERP 커넥터 또는 모바일 앱을 구축하는 개발자에게 Magento API 통합은 선택 사항이 아니라, 이 방대한 판매자 기반에 도달하기 위한 필수 요소입니다.

현실은 다음과 같습니다. 여러 판매 채널을 관리하는 판매자들은 Magento와 다른 시스템 간의 수동 데이터 입력에 매주 20~30시간을 낭비하고 있습니다. 견고한 Magento API 통합은 제품 동기화, 주문 처리, 재고 업데이트 및 고객 데이터 관리를 자동화합니다.

이 가이드는 Magento 2 API 통합 프로세스 전체를 안내합니다. OAuth 1.0a 및 토큰 인증, REST/SOAP/GraphQL 엔드포인트, 제품 및 주문 관리, 웹훅, 맞춤형 API 개발, 그리고 운영 배포 전략에 대해 배우게 될 것입니다. 마지막에는 운영 환경에 즉시 사용 가능한 Magento 통합을 갖게 될 것입니다.

💡
Apidog는 API 통합 테스트를 간소화합니다. 단일 작업 공간에서 Magento 엔드포인트를 테스트하고, 인증 흐름을 검증하고, API 응답을 검사하며, 통합 문제를 디버깅하십시오. API 사양을 가져오고, 응답을 모의하고, 테스트 시나리오를 팀과 공유하세요.
버튼

Magento 2 API란 무엇인가요?

Magento 2는 전자상거래 데이터에 접근하기 위한 세 가지 API 유형을 제공합니다:

API는 다음을 처리합니다:

주요 기능

기능 설명
다중 프로토콜 REST, SOAP, GraphQL
OAuth 1.0a 안전한 타사 액세스
토큰 인증 관리자 및 통합 토큰
웹훅 큐를 통한 비동기 작업
속도 제한 설치별로 구성 가능
맞춤형 엔드포인트 맞춤형 API로 확장
멀티 스토어 단일 API, 여러 스토어 뷰

API 비교

API 유형 프로토콜 사용 사례
REST JSON 모바일 앱, 통합
SOAP XML 엔터프라이즈 시스템 (SAP, Oracle)
GraphQL GraphQL 스토어프론트, PWA

Magento 버전

버전 상태 지원 종료
Magento 2.4.x 현재 활성
Adobe Commerce 2.4.x 현재 활성
Magento 1.x EOL (지원 종료) 2020년 6월 (사용 금지)

시작하기: 인증 설정

1단계: 관리자 계정 또는 통합 생성

API에 접근하기 전에:

  1. Magento 관리자 패널에 로그인합니다.
  2. 시스템(System) > 권한(Permissions) > 모든 사용자(All Users)로 이동합니다.
  3. 관리자 사용자(관리자 토큰용)를 생성하거나,
  4. 시스템(System) > 확장 기능(Extensions) > 통합(Integrations)으로 이동합니다.
  5. 새 통합(OAuth용)을 생성합니다.

2단계: 인증 방법 선택

방법 가장 적합한 용도 토큰 수명
관리자 토큰 내부 통합 구성 가능 (기본: 4시간)
통합 토큰 타사 앱 취소될 때까지
OAuth 1.0a 공개 마켓플레이스 앱 취소될 때까지
고객 토큰 고객 대면 앱 구성 가능

3단계: 관리자 토큰 가져오기 (가장 간단한 방법)

내부 통합을 위한 관리자 토큰 생성:

const MAGENTO_BASE_URL = process.env.MAGENTO_BASE_URL;
const MAGENTO_ADMIN_USERNAME = process.env.MAGENTO_ADMIN_USERNAME;
const MAGENTO_ADMIN_PASSWORD = process.env.MAGENTO_ADMIN_PASSWORD;

const getAdminToken = async () => {
  const response = await fetch(`${MAGENTO_BASE_URL}/rest/V1/integration/admin/token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      username: MAGENTO_ADMIN_USERNAME,
      password: MAGENTO_ADMIN_PASSWORD
    })
  });

  if (!response.ok) {
    throw new Error('Invalid admin credentials');
  }

  // Response is a plain string (the token), not JSON
  const token = await response.text();
  return token;
};

// Usage
const token = await getAdminToken();
console.log(`Admin token: ${token}`);
// Store securely - use for subsequent API calls

보안 참고: 토큰을 안전하게 저장하십시오:

# .env file
MAGENTO_BASE_URL="https://store.example.com"
MAGENTO_ADMIN_USERNAME="api_user"
MAGENTO_ADMIN_PASSWORD="secure_password_here"
MAGENTO_ACCESS_TOKEN="obtained_via_auth"

4단계: 통합 생성 (타사에 권장)

관리자 패널을 통해 통합 생성:

시스템(System) > 확장 기능(Extensions) > 통합(Integrations)으로 이동

새 통합 추가(Add New Integration) 클릭

세부 정보 입력:

API 권한(API Permissions) 설정:

저장(Save) 클릭

새 통합에서 활성화(Activate) 클릭

액세스 토큰(Access Token)토큰 시크릿(Token Secret) 복사

5단계: 고객 토큰 가져오기

고객 대면 애플리케이션의 경우:

const getCustomerToken = async (email, password) => {
  const response = await fetch(`${MAGENTO_BASE_URL}/rest/V1/integration/customer/token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      username: email,
      password: password
    })
  });

  if (!response.ok) {
    throw new Error('Invalid customer credentials');
  }

  const token = await response.text();
  return token;
};

// Usage
const customerToken = await getCustomerToken('customer@example.com', 'password123');

6단계: 인증된 API 호출 수행

재사용 가능한 API 클라이언트 생성:

const magentoRequest = async (endpoint, options = {}) => {
  const token = await getAdminToken(); // Or retrieve stored token

  const response = await fetch(`${MAGENTO_BASE_URL}/rest${endpoint}`, {
    ...options,
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json',
      ...options.headers
    }
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Magento API Error: ${error.message}`);
  }

  return response.json();
};

// Usage
const products = await magentoRequest('/V1/products');
console.log(`Found ${products.items.length} products`);

제품 관리

제품 가져오기

필터링하여 제품 가져오기:

const getProducts = async (filters = {}) => {
  const params = new URLSearchParams();

  // Build search criteria
  if (filters.search) {
    params.append('searchCriteria[filterGroups][0][filters][0][field]', 'sku');
    params.append('searchCriteria[filterGroups][0][filters][0][value]', `%${filters.search}%`);
    params.append('searchCriteria[filterGroups][0][filters][0][conditionType]', 'like');
  }

  if (filters.priceFrom) {
    params.append('searchCriteria[filterGroups][1][filters][0][field]', 'price');
    params.append('searchCriteria[filterGroups][1][filters][0][value]', filters.priceFrom);
    params.append('searchCriteria[filterGroups][1][filters][0][conditionType]', 'gteq');
  }

  params.append('searchCriteria[pageSize]', filters.limit || 20);
  params.append('searchCriteria[currentPage]', filters.page || 1);

  const response = await magentoRequest(`/V1/products?${params.toString()}`);
  return response;
};

// Usage
const products = await getProducts({ search: 'shirt', priceFrom: 20, limit: 50 });

products.items.forEach(product => {
  console.log(`${product.sku}: ${product.name} - $${product.price}`);
});

단일 제품 가져오기

SKU로 제품 가져오기:

const getProduct = async (sku) => {
  const response = await magentoRequest(`/V1/products/${sku}`);
  return response;
};

// Usage
const product = await getProduct('TSHIRT-001');
console.log(`Name: ${product.name}`);
console.log(`Price: $${product.price}`);
console.log(`Stock: ${product.extension_attributes?.stock_item?.qty}`);

제품 생성

단순 제품 생성:

const createProduct = async (productData) => {
  const product = {
    product: {
      sku: productData.sku,
      name: productData.name,
      attribute_set_id: productData.attributeSetId || 4, // Default set
      type_id: 'simple',
      price: productData.price,
      status: productData.status || 1, // 1=enabled, 2=disabled
      visibility: productData.visibility || 4, // 4=Catalog & Search
      weight: productData.weight || 1,
      extension_attributes: {
        stock_item: {
          qty: productData.qty || 0,
          is_in_stock: productData.qty > 0 ? true : false
        }
      },
      custom_attributes: [
        {
          attribute_code: 'description',
          value: productData.description
        },
        {
          attribute_code: 'short_description',
          value: productData.shortDescription
        },
        {
          attribute_code: 'color',
          value: productData.color
        },
        {
          attribute_code: 'size',
          value: productData.size
        }
      ]
    }
  };

  const response = await magentoRequest('/V1/products', {
    method: 'POST',
    body: JSON.stringify(product)
  });

  return response;
};

// Usage
const newProduct = await createProduct({
  sku: 'TSHIRT-NEW-001',
  name: 'Premium Cotton T-Shirt',
  price: 29.99,
  qty: 100,
  description: 'High-quality cotton t-shirt',
  shortDescription: 'Premium cotton tee',
  color: 'Blue',
  size: 'M'
});

console.log(`Product created: ${newProduct.id}`);

제품 업데이트

제품 정보 업데이트:

const updateProduct = async (sku, updates) => {
  const product = {
    product: {
      sku: sku,
      ...updates
    }
  };

  const response = await magentoRequest(`/V1/products/${sku}`, {
    method: 'PUT',
    body: JSON.stringify(product)
  });

  return response;
};

// Usage - Update price and stock
await updateProduct('TSHIRT-001', {
  price: 24.99,
  extension_attributes: {
    stock_item: {
      qty: 150,
      is_in_stock: true
    }
  }
});

제품 삭제

제품 제거:

const deleteProduct = async (sku) => {
  await magentoRequest(`/V1/products/${sku}`, {
    method: 'DELETE'
  });

  console.log(`Product ${sku} deleted`);
};

제품 유형

유형 설명 사용 사례
단순 (Simple) 단일 SKU, 변형 없음 표준 제품
구성 가능 (Configurable) 하위 변형을 가진 부모 제품 사이즈/색상 옵션
그룹화 (Grouped) 단순 제품들의 모음 제품 묶음
가상 (Virtual) 비물리적 제품 서비스, 다운로드
번들 (Bundle) 사용자 정의 가능한 제품 묶음 DIY 키트
다운로드 가능 (Downloadable) 디지털 제품 전자책, 소프트웨어

주문 관리

주문 가져오기

필터링하여 주문 가져오기:

const getOrders = async (filters = {}) => {
  const params = new URLSearchParams();

  if (filters.status) {
    params.append('searchCriteria[filterGroups][0][filters][0][field]', 'status');
    params.append('searchCriteria[filterGroups][0][filters][0][value]', filters.status);
    params.append('searchCriteria[filterGroups][0][filters][0][conditionType]', 'eq');
  }

  if (filters.dateFrom) {
    params.append('searchCriteria[filterGroups][1][filters][0][field]', 'created_at');
    params.append('searchCriteria[filterGroups][1][filters][0][value]', filters.dateFrom);
    params.append('searchCriteria[filterGroups][1][filters][0][conditionType]', 'gteq');
  }

  params.append('searchCriteria[pageSize]', filters.limit || 20);
  params.append('searchCriteria[currentPage]', filters.page || 1);

  const response = await magentoRequest(`/V1/orders?${params.toString()}`);
  return response;
};

// Usage - Get pending orders from last 7 days
const orders = await getOrders({
  status: 'pending',
  dateFrom: '2026-03-18 00:00:00',
  limit: 50
});

orders.items.forEach(order => {
  console.log(`Order #${order.increment_id}: ${order.customer_email} - $${order.grand_total}`);
});

단일 주문 가져오기

ID로 주문 가져오기:

const getOrder = async (orderId) => {
  const response = await magentoRequest(`/V1/orders/${orderId}`);
  return response;
};

// Usage
const order = await getOrder(12345);
console.log(`Order #${order.increment_id}`);
console.log(`Status: ${order.status}`);
console.log(`Total: $${order.grand_total}`);
console.log(`Items:`);
order.items.forEach(item => {
  console.log(`  - ${item.name} x ${item.qty_ordered}`);
});

주문 상태 흐름

대기 중 (pending) → 처리 중 (processing) → 완료 (complete)
                  → 취소됨 (canceled)
                  → 보류 중 (on_hold)
                  → 결제 검토 (payment_review)

주문 상태 업데이트

주문 상태 변경:

const updateOrderStatus = async (orderId, newStatus) => {
  // Note: Direct status update requires custom endpoint
  // Use order management workflow instead:

  // For cancel:
  await magentoRequest(`/V1/orders/${orderId}/cancel`, {
    method: 'POST'
  });

  // For hold:
  await magentoRequest(`/V1/orders/${orderId}/hold`, {
    method: 'POST'
  });

  // For unhold:
  await magentoRequest(`/V1/orders/${orderId}/unhold`, {
    method: 'POST'
  });
};

송장 생성

주문에 대한 송장 생성:

const createInvoice = async (orderId, items = [], notify = true, appendComment = false, comment = null) => {
  const invoice = {
    capture: true, // true = capture payment
    last: true,
    items: items // Array of {order_item_id, qty}
  };

  if (comment) {
    invoice.comment = comment;
    invoice.notify_customer = notify ? 1 : 0;
    invoice.append_comment = appendComment ? 1 : 0;
  }

  const response = await magentoRequest(`/V1/order/${orderId}/invoice`, {
    method: 'POST',
    body: JSON.stringify(invoice)
  });

  return response;
};

// Usage - Invoice and capture full order
const invoiceId = await createInvoice(12345, [], true, false, 'Thank you for your order!');
console.log(`Invoice created: ${invoiceId}`);

배송 생성

주문 배송:

const createShipment = async (orderId, items = [], notify = true, appendComment = false, comment = null, tracks = []) => {
  const shipment = {
    items: items, // Array of {order_item_id, qty}
    notify: notify ? 1 : 0,
    append_comment: appendComment ? 1 : 0,
    comment: comment,
    tracks: tracks // Array of {track_number, title, carrier_code}
  };

  const response = await magentoRequest(`/V1/order/${orderId}/ship`, {
    method: 'POST',
    body: JSON.stringify(shipment)
  });

  return response;
};

// Usage - Ship with tracking
const shipmentId = await createShipment(12345, [], true, false, 'Your order has shipped!', [
  {
    track_number: '1Z999AA10123456784',
    title: 'Tracking Number',
    carrier_code: 'ups'
  }
]);
console.log(`Shipment created: ${shipmentId}`);

고객 관리

고객 가져오기

고객 가져오기:

const getCustomers = async (filters = {}) => {
  const params = new URLSearchParams();

  if (filters.email) {
    params.append('searchCriteria[filterGroups][0][filters][0][field]', 'email');
    params.append('searchCriteria[filterGroups][0][filters][0][value]', filters.email);
    params.append('searchCriteria[filterGroups][0][filters][0][conditionType]', 'eq');
  }

  params.append('searchCriteria[pageSize]', filters.limit || 20);

  const response = await magentoRequest(`/V1/customers/search?${params.toString()}`);
  return response;
};

// Usage
const customers = await getCustomers({ email: 'customer@example.com' });
customers.items.forEach(customer => {
  console.log(`${customer.firstname} ${customer.lastname} - ${customer.email}`);
});

고객 생성

새 고객 등록:

const createCustomer = async (customerData) => {
  const customer = {
    customer: {
      websiteId: customerData.websiteId || 1,
      email: customerData.email,
      firstname: customerData.firstname,
      lastname: customerData.lastname,
      middlename: customerData.middlename || '',
      gender: customerData.gender || 0,
      store_id: customerData.storeId || 0,
      extension_attributes: {
        is_subscribed: customerData.subscribed || false
      }
    },
    password: customerData.password
  };

  const response = await magentoRequest('/V1/customers', {
    method: 'POST',
    body: JSON.stringify(customer)
  });

  return response;
};

// Usage
const newCustomer = await createCustomer({
  email: 'newcustomer@example.com',
  firstname: 'John',
  lastname: 'Doe',
  password: 'SecurePass123!',
  subscribed: true
});

console.log(`Customer created: ID ${newCustomer.id}`);

재고 관리 (MSI)

재고 상태 가져오기

제품 재고 확인:

const getStockStatus = async (sku) => {
  const response = await magentoRequest(`/V1/products/${sku}/stockItems/1`);
  return response;
};

// Usage
const stock = await getStockStatus('TSHIRT-001');
console.log(`Qty: ${stock.qty}`);
console.log(`In Stock: ${stock.is_in_stock}`);
console.log(`Min Qty: ${stock.min_qty}`);

재고 업데이트

제품 수량 업데이트:

const updateStock = async (sku, qty, isInStock = null) => {
  const stockItem = {
    stockItem: {
      qty: qty,
      is_in_stock: isInStock !== null ? isInStock : qty > 0
    }
  };

  const response = await magentoRequest(`/V1/products/${sku}/stockItems/1`, {
    method: 'PUT',
    body: JSON.stringify(stockItem)
  });

  return response;
};

// Usage
await updateStock('TSHIRT-001', 100, true);

웹훅 및 비동기 작업

웹훅 설정

Magento는 비동기 알림을 위해 메시지 큐를 사용합니다:

// Magento doesn't have native webhooks
// Use these approaches instead:

// 1. Poll orders endpoint periodically
const pollNewOrders = async (lastOrderId) => {
  const orders = await getOrders({
    dateFrom: new Date().toISOString()
  });

  const newOrders = orders.items.filter(o => o.id > lastOrderId);
  return newOrders;
};

// 2. Use Adobe I/O Events (Adobe Commerce only)
// Configure events in Adobe Developer Console

// 3. Create custom webhook module
// See: https://devdocs.magento.com/guides/v2.4/extension-dev-guide/message-queues/message-queues.html

속도 제한

속도 제한 이해하기

Magento 속도 제한은 구성 가능합니다:

관리자에서 구성: 스토어(Stores) > 구성(Configuration) > 서비스(Services) > 웹 API(Web API) > 보안(Security)

속도 제한 처리 구현

const makeRateLimitedRequest = async (endpoint, options = {}, maxRetries = 3) => {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await magentoRequest(endpoint, options);
      return response;
    } catch (error) {
      if (error.message.includes('429') && attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000;
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
};

운영 배포 체크리스트

실제 서비스 시작 전에:

실제 사용 사례

ERP 통합

제조업체가 재고를 동기화합니다:

모바일 앱

소매업체가 쇼핑 앱을 구축합니다:

결론

Magento 2 API는 포괄적인 전자상거래 기능을 제공합니다. 핵심 요약:

버튼

자주 묻는 질문 (FAQ) 섹션

Magento API로 어떻게 인증하나요?

내부 통합에는 관리자 토큰을 사용하거나, 시스템(System) > 확장(Extensions)에서 OAuth를 위한 통합을 생성하세요. 고객 대면 앱에는 고객 토큰을 사용하세요.

Magento의 REST와 GraphQL의 차이점은 무엇인가요?

REST는 완전한 CRUD 작업을 제공합니다. GraphQL은 효율적인 데이터 가져오기를 통해 프론트엔드 쿼리에 최적화되어 있습니다.

API를 통해 제품을 어떻게 생성하나요?

제품 데이터(SKU, 이름, 가격, extension_attributes의 stock_item 포함)를 가지고 /V1/products에 POST 요청을 합니다.

새 주문에 대한 웹훅을 받을 수 있나요?

Magento에는 네이티브 웹훅이 없습니다. 폴링, Adobe I/O 이벤트(Adobe Commerce), 또는 맞춤형 모듈을 생성하는 방법을 사용하십시오.

재고 수량을 어떻게 업데이트하나요?

/V1/products/{sku}/stockItems/1에 qty 및 is_in_stock 값을 포함하여 PUT 요청을 합니다.

Apidog에서 API 설계-첫 번째 연습

API를 더 쉽게 구축하고 사용하는 방법을 발견하세요