WEB/JavaScript

[Konva] 유사 CAD 프로그램 제작 - 성능 향상의 기록

디벨로펄 2023. 11. 20.
반응형

 

 

Web으로 편집 프로그램 제작을 위해서 회사에서 선택한 것은

Konva.js

왜 선택했는지에 대해서는 넘어가고,

이미 konva로 프로젝트를 진행중이고,

성능 개선이 필요하다면 읽어보면 좋을 것 같다.

 

문제 상황

사내용으로 만드는 유사 CAD 프로그램이었다.

한 번에 그려지는 객체수는 (1)약 5만개 이상

그리고 각 객체는 (2)위치 이동이 가능해야하며

독립적이지 않고 (3)연관되어 있다.

 

성능 이슈

작은 개수는 충분히 편집이 가능할 정도의 성능이 나왔다.

하지만, 5만개 정도면 한 번 움직이는데 수 초가 걸릴 정도로 성능이 저하되었다. 

도저히 편집기로 사람이 쓸 수 없을 정도였다.

크게 세 가지로 정리하면

1. 대량의 데이터를 한 화면에 보여줄 것

2. 한 화면에서 편집이 가능할 것

3. 1, 2가 너무 느리지 않을 것 

위 세 가지를 만족시켜야 했다.

 

 

 

1. 대량의 데이터를 한 화면에 보여주기 - Caching, Grouping

대량의 데이터를 한 화면에 뿌려주기 위해서 Cache()라는 konva의 기능과 구역별로 Grouping하여 성능 개선을 꾀했다.

1) Cache - 캐싱 - 대량의 데이터 그리기

Konva 제작자 측에서 Caching으로 성능을 올릴 수 있는 팁을 정리해두었다.

cache() 메서드를 통해서 konva 객체인 node이미지 객체로 변환된다.

caching은 layer, group, shapes에 적용이 가능하다. 

 

동작 방식 

konva가 메모리 상에 새로운 canvas를 생성하고 거기에 node를 그린다.

-> 다음, layer가 다시 그려지면, 노드를 그리는 대신 캐싱된 canvas이미지를 그려준다.

투명도나 transform 변경에는 re-cache를 할 필요가 없으며, 이외의 경우에는 re-cache가 필요하다.

 

★ 주의사항!! 

1. 너무 많은 객체를 각각 cache하지 말 것. group이나 layer단위로 caching진행

-> 실제 업무에서 각각의 객체를 cache해서 느린 것을 발견하고 group단위로 caching을 진행했다.

2. 자주 변경되는 객체를 caching 하지 말 것. 정적인 것 위주로 caching

3. 간단한 object보다는 복잡한 object를 caching. 간단한건 금방그림

4. pixelRatio 속성을 이용해서 caching되는 이미지의 해상도 조절이 가능하다.

 

caching만 잘해줘도 몇 만개의 데이터가 쉽게 그려지고, drag, 확대, 축소 등이 가능하다.

 

참고

https://konvajs.org/docs/performance/Shape_Caching.html

 

HTML5 Canvas Shape Caching Performance Tip

HTML5 Canvas Shape Caching Performance TipOne way to drastically improve drawing performance for complex Konva shapes is to cache them as images.This can be achieved by using the cache() method to con

konvajs.org

 

2) Grouping - 대량의 데이터 편집하기

 caching을 통해서 대량의 데이터를 한 화면에 그려낼 수 있었다.

하지만, 문제는 변경사항이 발생할 때마다 clearCache() 및 cache() 과정을 반복해야했고, 이 과정에서 전체 Layout에 대해 접근하는 과정에서 많은 리소스가 소모되었다.

 

제작하려는 프로그램 특성상, 인접한 객체끼리의 편집이 자주 일어났기 때문에, 전체를 작은 조각으로 나누어서,

편집할 때는 근처의 객체들만 사용할 수 있도록 해주었다.

 

단순하게 생각만해도, 120px을 건드는 것보다 10px만 건드는 것이 훨씬 효율적일 것이다.

 

 

 

Grouping을 하면 두 가지 이점이 있었다.

첫 번째로, caching과정이 빨라진다.

위에서 보듯이 120px 대신 10px만 수정하면 되니까~

 

두번째 : 특정 좌표 근처의 객체를 빠르게 찾을 수 있다.

탐색 범위가 줄어들기 때문!

 

2. 더욱더 빠르게 - find함수에 대한 고찰

konva에서 자식 노드를 찾기 위해서는 find, findOne, children 등을 활용할 수 있다.

하지만, 여기서find와 findOne 함수는 구현상 느릴 수 밖에 없는 구조이다.

모든 객체를 하나씩 탐색하도록 구현되었다. 특히, 자식노드를 끝까지 탐색하고 다음 노드를 본다.

아래와 같이 노란색을 전부 살펴본 후, 파란색을 탐색한다는 것이다.

 

이는 현재 진행하는 프로젝트에서 객체 하나하나에 id를 부여했기 때문에,

Map 자료구조를 활용하면 훨씬 빠를거라 판단했고, konva 소스코드를 일부 수정하기로 했다.

Container라이브러리에 mappedChildren을 추가하였다.

 

추가하는 것보다는 어디에 어떤 코드를 추가해야하는지 찾는 게 어려웠다.

소스코드 : https://github.com/dhdnjswnd/konva

 

그리고, 코드 변경이후 이를 다시 konva.js로 변환하는 과정이 어려웠다.

없는 library가 너무 많아서 다시 받고 지지고 볶고...

 

암튼 성능 향상의 기록은 여기까지이다.

 

위에 나열된 것만 처리해도 web으로 cad를 만들 수 있을 것이다.!

 

 

정리하며...

 

정리하고 보니 양이 얼마되지 않는데,

문제를 찾아내고 구글링하는 과정이 꽤나 오래 걸렸던 것 같다.

 

왜 소스코드를 보는지 알게되는 경험이었다.

 

 

* find가 느린걸 발견한 것은 생각보다 탐색하는데 걸리는 시간이 너무 오래걸려서 하나씩 테스트 해보다가 알게되었다.

모든 소스코드를 확인할 수는 없었고, 이슈가 발생하는 method쪽의 소스코드를 위주로 살펴보고 문제를 발견했었다.

그래도 개선의 여지가 있어서 참 다행이다.

 

 

 

반응형

댓글