export용 PNG/SVG/JSON 생성 전략
export는 하나가 아닙니다. 저장용 JSON, 미리보기 PNG, 교환용 SVG는 서로 목적이 다릅니다.
export 함수를 분리하는 코드
저장용 JSON과 미리보기 PNG, 교환용 SVG는 목적이 다르므로 서로 다른 경로로 만듭니다.
function exportDocumentJson(editor) {
const snapshot = editor.getSnapshot();
return JSON.stringify({
version: snapshot.document.version,
pages: snapshot.document.pages,
assets: snapshot.document.assets
});
}
async function exportPngPreview(renderer, bounds) {
const canvas = await renderer.renderToCanvas({ bounds, pixelRatio: 2 });
return await new Promise((resolve) => canvas.toBlob(resolve, "image/png"));
}
function exportSvg(scene, bounds) {
return sceneToSvg({
nodes: scene.nodes,
bounds,
unsupportedPolicy: "rasterize"
});
}
역할 분리
JSON: 다시 편집하기 위한 source of truth
PNG: 공유/미리보기
SVG: vector 교환
모든 editor 기능이 SVG로 완벽히 나가지 않을 수 있습니다. 지원 범위와 손실 가능성을 명시해야 합니다.
export 전에 지원 범위를 검사한다
function validateExport(scene, format) {
const warnings = [];
for (const node of scene.nodes) {
if (format === "svg" && node.effects?.some((effect) => effect.type === "blur")) {
warnings.push({ nodeId: node.id, reason: "blur will be rasterized" });
}
if (format === "png" && node.asset?.loading) {
warnings.push({ nodeId: node.id, reason: "asset is not loaded yet" });
}
}
return { ok: warnings.length === 0, warnings };
}
export 버튼을 누른 뒤 실패하는 것보다, export 전에 어떤 node가 rasterize되거나 누락될 수 있는지 알려주는 편이 제품적으로 안전합니다.
오늘의 핵심
export format은 사용자 약속입니다. 무엇을 보존하고 무엇을 잃는지 명확해야 합니다.