가구 20개 넘어가니까 드래그가 버벅거린다.


Layer 분리

Konva에서 Layer는 별도 Canvas. Layer 안 내용이 바뀌면 그 Layer만 다시 그림.

<v-stage>
  <v-layer ref="gridLayer">
    <!-- 그리드: 거의  바뀜 -->
  </v-layer>
  <v-layer ref="backgroundLayer">
    <!-- 배경 이미지: 거의  바뀜 -->
  </v-layer>
  <v-layer ref="mainLayer">
    <!-- , 가구, : 자주 바뀜 -->
  </v-layer>
  <v-layer ref="uiLayer">
    <!-- Transformer, 측정선: 자주 바뀜 -->
  </v-layer>
</v-stage>

그리드 드래그한다고 가구까지 다시 그릴 필요 없음.


batchDraw

여러 변경을 한 번에:

// 안 좋음: 매번 그림
items.forEach(item => {
  item.x(item.x() + 10);
  layer.draw();  // 불필요한 반복
});

// 좋음: 한 번에
items.forEach(item => {
  item.x(item.x() + 10);
});
layer.batchDraw();  // 한 번만

batchDraw()는 requestAnimationFrame으로 다음 프레임에 그림.


캐싱

복잡한 Shape은 캐싱:

complexShape.cache();

비트맵으로 캐싱해서 매번 다시 그리지 않음.

변경 후에는 clearCache() 해야 함.


드래그 중 업데이트 최소화

드래그할 때마다 스토어 업데이트하면 느림:

// 안 좋음
function onDragMove(e) {
  store.updateFurniture(id, {
    x: e.target.x(),
    y: e.target.y()
  });  // 매 프레임 스토어 업데이트
}

// 좋음
function onDragMove(e) {
  // 아무것도 안 함. Konva가 알아서 움직임.
}

function onDragEnd(e) {
  store.updateFurniture(id, {
    x: e.target.x(),
    y: e.target.y()
  });  // 드래그 끝날 때만
}

불필요한 리렌더링 방지

Vue의 반응성이 너무 민감하면 문제:

// 모든 가구가 리렌더링됨
const items = computed(() => store.items);

// 개별 가구만 리렌더링
const getItem = (id: string) => computed(() => 
  store.items.find(item => item.id === id)
);

Transformer 최적화

Transformer가 무거움. 선택된 것만 붙이기:

// 안 좋음: 모든 가구에 Transformer
<v-transformer v-for="item in items" ... />

// 좋음: 선택된 것만
<v-transformer :nodes="selectedNodes" />

requestAnimationFrame

연속 업데이트는 RAF로:

let rafId: number;

function onMouseMove(e) {
  if (rafId) return;
  
  rafId = requestAnimationFrame(() => {
    updatePosition(e);
    rafId = 0;
  });
}

결과

상황최적화 전최적화 후
가구 30개 드래그20 FPS55 FPS
줌/팬버벅부드러움

다음 글에서 Vue Reactivity와 Konva 충돌.

#20 - Vue Reactivity + Konva 충돌