본문 바로가기
frontend

Canvas vs Svg

by marble25 2023. 9. 10.

업무를 진행하면서 브라우저에 다양한 도형을 그리고, 텍스트를 넣고, 도형들을 편집해야 하는 요구사항이 있었다.

도형의 개수가 많고, 많은 편집 작업이 필요하기 때문에 렌더링 성능도 중요하게 생각해야 했다.

Konva

https://github.com/konvajs/vue-konva

가장 간단하게 구현할 수 있고, 기본적인 기능들은 built-in으로 구현되어 있어서 가져다 쓰기만 하면 되었다. 때문에 기존 툴이 konva 기반으로 구현되어 있었다.

하지만, Konva 라이브러리를 사용하다 보니, 라이브러리에 의존적으로 코드가 작성되어 불편한 부분이 많다. 예컨대, zoom-in zoom-out시에 좌표를 일일이 변환하고, 서버에 저장할 때나 이미지 이동시 좌표 변환하는 부분이 있어 버그가 발생하기 쉽다. 또한, 라이브러리 디펜던시가 있으면 필요한 기능이 있을 때 직접적으로 구현하지 못하고 라이브러리에 계속 맞춰서 개발해야 하는 단점이 있다.

Canvas에서 SVG로 바꾸면 html element가 생성되기 때문에 ui testing이나 세부 값 확인 등 html element를 잡아서 할 수 있는 다양한 작업들이 가능해지고, 편해진다. 이런 단점을 해결하고자 konva 기반의 canvas에서 svg로 변환하는 작업을 진행했다.

SVG

svg는 벡터 기반으로 되어 있고, 선언적으로 정의되어 있다.

<svg viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="50" />
</svg>

다음과 같이 dom element를 이용해서 구성할 수 있다. 따라서 dom element를 확인해 보면 되기 때문에 testing도 비교적 편리하고, 결과를 확인하는 것이 편하다. 뿐만 아니라, dom에 적용할 수 있는 모든 특성은 한번에 적용 가능하다. 예를 들어, css style이나 event listener 등을 쉽게 달아줄 수 있다.

다만, html element가 많아지면 많아질 수록 렌더링 성능이 낮아지게 된다. 특히, 동시에 업데이트하는 element가 많으면 더욱 그렇다.

따라서 벡터와 행렬 연산을 직접 적용하는 등의 성능 최적화가 필요하다.

Canvas

canvas는 javascript drawing api로, imperative로 정의되어 있다.

<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
  var canvas = document.getElementById('myCanvas');
  var context = canvas.getContext('2d');
  var centerX = canvas.width / 2;
  var centerY = canvas.height / 2;
  var radius = 70;

  context.beginPath();
  context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
  context.fillStyle = 'green';
  context.fill();
</script>

사용자와 상호작용하는 콘솔같은 게임에서는 적당하다. 하지만, 더 많은 코드를 작성해야 하고, 화면에 나온 결과가 desired output인지 판단하기 어렵다.

canvas의 단점 때문에 konva based canvas → svg로 변환 작업을 진행했고, 처음에 아쉬웠던 성능은 추가적인 성능 최적화 작업을 통해 개선할 수 있었다.

'frontend' 카테고리의 다른 글

[TIL] javascript html parser  (0) 2023.12.16
[TIL] npm ci vs npm install  (0) 2023.10.17
JS로 파일 다운로드  (0) 2023.09.10
가로 세로 스크롤 되는 테이블 만들기  (0) 2023.04.24
[TIL] html에서 돋보기 뷰 구현하기  (0) 2023.04.03