2D 그래픽 렌더링 - Canvas vs WebGL, Excalidraw의 선택과 성능 이슈

created:
last-updated:

회사에서 Excalidraw를 채택해 양방향 실시간 화이트보드 필기 기능을 개발하고 이슈 대응 담당을 한지 꽤 시간이 지났습니다. 처음엔 단순 화이트보드 기능으로, 그 다음엔 선생님과 학생의 실시간 양방향 협업 화이트보드로, 최근엔 학교 수업 현장에서 쓰일 판서, 수학이나 과학 과목 등 텍스트로만 학습하기 어려운 유형들의 활동과 모둠활동을 지원하기 위한 형태로 고도화를 진행했습니다.

꾸준히 발전시켜온 기능에 비해 네트워크 환경이 좋지 못하거나 태블릿이나 아이패드의 메모리 제한, 기기 성능의 문제로 화이트보드 기능을 더 안정적으로 제공할 수 없는 아쉬움이 있었습니다.

최근 리드분과의 원오원미팅에서 그래픽과 저작도구 고도화에 관심이 많은 제가 앞으로 해당 기능을 더 안정적으로 제공할 개선 프로젝트의 기회가 생기면 좋겠다고 말씀을 드렸습니다.

사실 그동안 늘 개선하면 좋겠다는 이야기가 나왔지만 비즈니스적인 상황으로 인해 다른 프로젝트가 바삐 진행되었습니다. 또, 리드분은 자체 구현하자, 왜 이런 화이트보드 라이브러리가 webgl이 아닌 2dcanvas를 사용하는지 모르겠다 (3dcanvas가 gpu를 사용해 우리가 겪고있는 성능이슈를 해결할 여지가 있다)고 하셨습니다.

사실 저는 자체 구현을 할만큼의 시간과 리소스가 주어지지 않을 것 같다는 현실적인 한계와 더불어 2d가 아닌 3d로 화이트보드 기능을 제공하는 라이브러리를 본 적이 없기 때문에 이상적인 접근은 아니라는 회의감과 막연함이 들었습니다.

그래서 이참에 2dcanvas와 webgl 구현의 차이점과 가능하다면 자체 구현할 시 좀 더 편리한 방법이 있을지 서치해보기로 했습니다. 그리고 그 내용을 아래 정리합니다.


디지털 화이트보드, 게임, 애니메이션과 같은 다양한 애플리케이션에서 2D 그래픽을 렌더링할 때 두 가지 주요 기술인 Canvas 2D API와 WebGL을 선택하게 됩니다. 두 기술은 각기 다른 장단점을 가지고 있으며, 각기 다른 사용 사례에 적합합니다. 이 글에서는 Excalidraw와 PixiJS와 같은 실제 예시를 통해 두 기술을 비교하고, 성능 이슈를 어떻게 해결할 수 있을지에 대해 다뤄보겠습니다.


1. Canvas 2D API와 WebGL의 차이

Canvas 2D API

Canvas 2D API는 웹 브라우저에서 제공하는 2D 그래픽 렌더링을 위한 가장 기본적인 방법입니다. HTML5 <canvas> 요소를 사용하여 도형, 이미지, 텍스트 등을 그릴 수 있으며, 모든 작업이 CPU에서 처리됩니다.

특징

<canvas id="canvas" width="500" height="500"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

// 간단한 사각형 그리기
ctx.fillStyle = 'blue';
ctx.fillRect(50, 50, 100, 100);
</script>

WebGL

WebGL은 GPU 가속을 활용하여 2D 및 3D 그래픽을 처리하는 기술입니다. OpenGL ES를 웹 환경에 맞게 구현한 것으로, 복잡한 그래픽 작업에 최적화되어 있습니다.

특징

<canvas id="webgl" width="500" height="500"></canvas>
<script>
const canvas = document.getElementById('webgl');
const gl = canvas.getContext('webgl');

// WebGL 컨텍스트 확인
if (!gl) {
    console.error('WebGL not supported');
}

// WebGL 초기화 코드 작성 필요
</script>


2. Excalidraw: 왜 Canvas 2D API를 선택했을까?

Excalidraw 개요

Excalidraw는 디지털 화이트보드 애플리케이션으로, 사용자가 선, 도형, 텍스트 등을 그릴 수 있도록 지원합니다. Excalidraw는 Canvas 2D API를 사용하여 간단한 2D 그래픽을 구현하며, 복잡한 그래픽 처리에는 WebGL을 사용하지 않습니다.

Canvas 2D를 선택한 이유

  1. 간단한 그래픽 처리 요구:
    • Excalidraw는 간단한 도형과 텍스트를 그리는 데 초점이 맞춰져 있습니다. Canvas 2D API는 이러한 기본적인 작업을 매우 효율적으로 처리할 수 있습니다.
  2. 개발 생산성:
    • WebGL은 셰이더 코드 작성 및 고급 그래픽 설정이 필요해 복잡하고 시간이 많이 소요됩니다. 반면, Canvas 2D API는 간단하고 직관적인 메서드를 제공하여 개발과 유지보수가 용이합니다.
  3. 브라우저 호환성:
    • Canvas 2D API는 모든 주요 브라우저에서 기본적으로 지원되며, Excalidraw는 넓은 호환성을 제공하기 위해 이를 사용합니다.
  4. 저사양 장치에서도 원활한 작동:
    • WebGL을 사용하지 않음으로써 CPU와 메모리 자원이 적은 장치에서도 안정적으로 동작할 수 있습니다.

3. Excalidraw에서 발생할 수 있는 성능 이슈

CPU 100% 문제

대부분의 경우, Excalidraw는 CPU 중심으로 렌더링을 처리하기 때문에 복잡한 드로잉 작업에서 성능이 저하될 수 있습니다. 그러나 Excalidraw가 일반적인 사용 환경에서는 CPU 100% 문제를 경험하지 않는 경우가 많습니다. 다만, 메모리와 CPU 성능이 제한적인 환경에서는 성능 문제가 더 자주 발생할 수 있습니다.

메모리 제한이 있는 장치에서 발생하는 문제

특히 태블릿이나 아이패드와 같은 메모리 제한이 있는 장치에서 Excalidraw를 실행할 때 성능 이슈가 더 빈번하게 발생합니다. 이런 장치들은 메모리와 CPU 리소스가 제한되어 있어, 많은 도형과 텍스트를 처리할 때 렌더링이 느려지거나, **CPU 사용률이 100%**에 도달할 수 있습니다.

원인

해결 방안

  1. 리소스 최적화: 불필요한 객체를 정리하거나 배치 렌더링 방식을 도입하여 렌더링 성능을 최적화할 수 있습니다.
  2. Web Worker 활용: Web Worker와 offscreencanvas를 활용하여 렌더링을 메인 쓰레드와 분리하고, canvas의 복잡한 작업을 비동기적으로 처리할 수 있습니다.
  3. GPU 가속 도입: WebGL을 통해 GPU 가속을 활용하는 방식도 고려할 수 있습니다. GPU에서 처리하면 렌더링 성능을 크게 개선할 수 있지만, 이를 위해서는 추가적인 구현과 복잡한 설정이 필요합니다.

GPU 가속의 작동 원리

그래픽 연산(또는 병렬 처리가 가능한 계산 작업)을 일반적으로 CPU가 처리하던 것을 GPU로 넘겨서 실행하는 기술입니다. GPU는 수천 개의 코어를 이용한 병렬 처리에 특화되어 있기 때문에, 대량의 데이터를 빠르게 처리할 수 있다는 장점이 있습니다. 이를 통해 애니메이션, 3D 렌더링, 고급 그래픽 효과 등이 훨씬 효율적으로 수행됩니다.

1. 일반적인 CPU 기반 작업 흐름

2. GPU 가속이 적용된 작업 흐름

  1. CPU에서 명령 준비: CPU는 그래픽 데이터를 준비하고, 명령(예: "여기에 삼각형을 그려라")을 생성합니다.
  2. 명령을 GPU로 전달: 준비된 데이터를 GPU로 넘깁니다(WebGL, WebGPU 등 API를 통해).
  3. GPU에서 병렬 처리: GPU는 수천 개의 코어를 사용해 픽셀, 정점, 텍스처 데이터를 병렬로 처리합니다. 이 작업은 매우 빠르게 실행되며, 동시에 많은 데이터를 처리할 수 있습니다.
  4. 결과를 화면에 출력: GPU가 처리한 데이터를 화면에 렌더링합니다.

4. PixiJS: WebGL을 활용한 고성능 2D 그래픽 처리

PixiJS 개요

PixiJS는 WebGL을 활용하여 고성능 2D 그래픽을 처리하는 라이브러리입니다. PixiJS는 GPU 가속을 활용하여 대규모 그래픽 작업을 빠르게 처리할 수 있습니다. 이 라이브러리는 애니메이션파티클 효과게임과 같은 복잡한 그래픽을 다룰 때 뛰어난 성능을 발휘합니다.

GPU 가속의 장점

PixiJS의 주요 특징

  1. WebGL 컨텍스트 초기화: PixiJS는 브라우저에서 WebGL 컨텍스트를 생성하여 GPU와의 통신을 시작합니다. WebGL을 추상화하여, 복잡한 그래픽 작업을 GPU 가속으로 간단히 처리할 수 있도록 합니다.
  2. 자동 리소스 관리: 텍스처와 이미지를 자동으로 관리하고, 배치 렌더링을 통해 효율적인 GPU 호출을 지원합니다.
  3. 고급 애니메이션: GPU를 활용한 빠르고 부드러운 애니메이션과 효과를 구현할 수 있습니다. 정점(Vertex) 데이터 관리: 도형, 이미지, 텍스트 등의 렌더링 데이터를 **정점(Vertex)**으로 변환하여 GPU로 전송. 셰이더를 통한 렌더링: PixiJS는 기본 셰이더를 사용해 텍스처 매핑, 변환(transform), 색상 처리를 GPU에서 처리.
  4. 크로스 플랫폼: PixiJS는 다양한 플랫폼에서 안정적으로 동작하며, WebGL을 지원하지 않는 브라우저에서는 자동으로 Canvas 2D로 폴백합니다.