MIRROR 구축: Perfect Corp API를 활용한 럭셔리 AI 패션 가상 피팅 앱
Source: Dev.to
MIRROR이란?
MIRROR는 고급 제품 탐색 경험과 AI 기반 가상 착용을 결합한 풀스택 웹 앱입니다.
- 사용자가 제품을 탐색합니다.
- 착용 모달을 열고 사진을 업로드하면 AI가 생성한 미리보기를 통해 해당 아이템을 착용한 모습을 확인합니다.
- 페이지를 떠나지 않고 바로 장바구니에 아이템을 추가합니다.
앱은 각각 고유한 Perfect Corp 엔드포인트와 페이로드 구조를 가진 네 가지 제품 카테고리를 지원합니다:
- 의류
- 신발
- 가방
- 귀걸이

기술 스택
| 레이어 | 기술 |
|---|---|
| 프론트엔드 | React, React Router, Context API, custom CSS (UI 프레임워크 없음) |
| 백엔드 | Node.js + Express |
| AI | Perfect Corp S2S (Server‑to‑Server) API |
| 사진 저장 | localStorage (최대 10개의 저장된 사용자 사진) |
| 카트 | localStorage와 수량 집계 |
아키텍처
핵심 아키텍처 결정은 프론트엔드를 Perfect Corp와 완전히 분리하는 것이었습니다. React 앱은 Perfect Corp를 직접 호출하지 않으며, 모든 AI 요청은 Express 백엔드를 통해 전달됩니다.
Client (React) → POST /api/tryon → Express Server → Perfect Corp S2S API
Perfect Corp의 API는 사용자 사진과 제품 참조 이미지 모두에 대해 공개 접근 가능한 URL을 요구합니다. 따라서 서버는 다음과 같이 동작합니다:
- 업로드된 사용자 사진을 디스크에 저장합니다.
- 공개 URL을 생성합니다 (ngrok을 개발 환경에서 사용).
제품 유형별 동적 엔드포인트 라우팅
Perfect Corp는 제품 카테고리마다 다른 엔드포인트를 사용하며, 각각 고유한 페이로드 형태를 기대합니다. 저는 깔끔한 switch‑기반 설정 조회로 이를 해결했습니다:
function getPerfectConfig(productType) {
switch (String(productType || "").toLowerCase()) {
case "cloth":
return {
startUrl: "https://yce-api-01.makeupar.com/s2s/v2.0/task/cloth",
/* …other config… */
};
case "earrings":
return {
startUrl:
"https://yce-api-01.makeupar.com/s2s/v2.0/task/2d-vto/earring",
/* …other config… */
};
case "shoes":
return {
startUrl: "https://yce-api-01.makeupar.com/s2s/v2.0/task/shoes",
/* …other config… */
};
case "bag":
return {
startUrl: "https://yce-api-01.makeupar.com/s2s/v2.0/task/bag",
/* …other config… */
};
default:
throw new Error(`Unsupported product type: ${productType}`);
}
}
buildPayload()는 각 유형에 맞는 요청 본문을 생성합니다:
- 의류 –
garment_category와change_shoes가 필요합니다. - 신발 / 가방 –
gender필드가 필요합니다. - 귀걸이 – 가장 복잡함:
ref_file_urls(배열),source_info,object_infos가 필요합니다.

작업‑폴링 패턴
Perfect Corp의 API는 비동기식입니다:
- POST → 작업 시작 →
task_id수신. - GET →
/task/{task_id}를 폴링하여task_status === "success"가 될 때까지.
재사용 가능한 폴러를 만들었습니다:
async function pollPerfect({
pollBaseUrl,
token,
taskId,
intervalMs = 2000,
maxAttempts = 120,
}) {
const headers = { Authorization: `Bearer ${token}` };
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const res = await fetch(`${pollBaseUrl}/task/${taskId}`, { headers });
const data = await res.json();
if (data.task_status === "success") return data;
if (data.task_status === "failed") throw new Error("Task failed");
await new Promise((r) => setTimeout(r, intervalMs));
}
throw new Error("Polling timed out");
}
로컬 개발 설정
# public URL을 위한 환경 변수 설정 (ngrok)
echo "PUBLIC_BASE_URL=https://your-ngrok-url.ngrok.app" >> server/.env
# 서버 노출 (Perfect Corp는 public URL이 필요합니다)
ngrok http 5000
# 백엔드와 프론트엔드 시작
node server/index.js
cd client && npm start
마무리
MIRROR는 해커톤 형식으로 AI 기반 패션 기술을 탐구할 수 있는 좋은 방법이었습니다. 가장 흥미로운 엔지니어링 과제는 각 제품 카테고리마다 다른 API 계약을 조율하면서 프런트엔드 인터페이스를 깔끔하고 일관되게 유지하는 것이었습니다.
Perfect Corp의 가상 착용 API를 통합하려는 경우, 사전에 알아야 할 가장 큰 사항은 공개 URL 요구사항입니다. 시작하기 전에 이미지 호스팅 전략을 계획하면 디버깅에 많은 시간을 절약할 수 있습니다.
전체 소스는 GitHub에 있습니다 – 자유롭게 살펴보거나 자체 착용 프로젝트의 참고 자료로 사용하세요.