웹개발 및 최신 테크 소식을 전하는 블로그, 웹이즈프리

HOME > html

canvas 태그 배우기. 장단점과 멀티 레이어 및 이미지 추출 방법

Last Modified : 2024-01-02 / Created : 2023-12-31
514
View Count
HTML5로 넘어오면서 canvas 태그를 사용해 게임 및 화려한 애니메이션을 구현할 수 있습니다. 아래는 canvas 태그를 좀 더 잘 사용하기 위해 canvas 태그가 무엇이고 여러 개의 canvas를 사용한 멀티 레이어 방식의 장단점과 이 경우 이미지 추출은 어떻게 할 수 있을지도 함께 알아보겠습니다.




canvas(캔버스) 태그 알아보기


간략하게 canvas 태그가 무엇인지 알아보겠습니다. HTML5에서 사용되는 canvas 태그는 복잡한 그래픽 구현을 위한 방법으로 애니메이션이나 게임 등을 구현할 수 있는 가장 효과적인 방법이라고 할 수 있습니다. canvas 태그를 사용했을 경우 일반적인 방식과 비교 했을 때 아래와 같은 장점을 가질 수 있습니다.

  • 높은 성능
  • 게임처럼 복잡한 그래픽 구현 가능
  • 더 쉽고 간단한 방법을 지원

canvas 태그의 가장 큰 장점은 높은 성능입니다. 기존의 DOM 방식의 경우 각각의 Node를 화면에 렌더링해서 그래픽을 구현해야 하는데 Node 자체가 여러 프로퍼티와 메소드를 가지고 있어 매우 무거우면서 반복적인 렌더링 방식은 성능이 크게 떨어지기 때문입니다. 또한 게임처럼 복잡한 그래픽 구현도 canvas를 사용해 가능하며 편리한 API를 제공하기 때문에 더 쉽고 간편하게 사용할 수 있죠.


canvas 태그 사용하는 예제


canvas 태그를 사용하는 가장 기본적인 방법은 아래와 같이 canvas 태그를 html에 추가하고 컨텍스트를 생성해야 합니다. 예를 들어 아래와 같이 코드를 작성해야합니다.
<canvas id="myCanvas" width="500" height="500"></canvas>

<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'blue';
ctx.fillRect(0, 0, 50, 50);
</script>

위 코드는 간단한 예제로 캔버스의 컨텍스트를 생성한 후 50, 50 크기의 파란색 사각형을 그려본 예제입니다. 위와 같은 방식으로 캔버스 태그를 사용하게 됩니다.

@ 이동하는 애니메이션 구현은 어떻게할까?
위 예제는 멈춰있는 사각형을 구현한 모습입니다. 움직이는 애니메이션은 해당 canvas를 모두 지우고 다시 그리는 방법을 사용합니다. 즉 fillRect()를 0, 0에 그렸다면 다음에는 조금씩 반복하여 계속 그리는 코드를 작성하면 됩니다. 그런데 이렇게 반복해서 그리게 되면 성능에 안 좋지 않을까하는 고민이 생길 수 있겠죠?

canvas 태그는 여러 번 그려도 성능에 큰 문제가 없도록 설계된 HTML5 방식이라 너무 큰 고민은 하지 않아도 구현 가능합니다. 그런데 만약 0.00000001초마다 0.00000001px씩 이동하는 경우를 생각해보겠습니다. 이 방식이 구현 가능할까요? 물론 구현은 가능하겠지만 매우 불필요한 리소스 낭비가 발생하겠죠. 왜냐하면 실제로 사람이 인지 가능한 초당 프레임을 넘어서기 때문이며 게다가 하드웨어가 지원하는냐의 여부 역시 매우 중요합니다. 이런 최적화 문제를 해결하기 위한 방법으로 가장 효과적인 방안이 바로 requestAnimationFrame()을 사용하는 방법입니다.


requestAnimationFrame 사용하기


애니메이션 구현을 위해 반복된 렌더링을 위해서 requestAnimationFrame()을 사용할 수 있습니다. 쉽게 설명하면 애니메이션의 반복된 구현을 가장 이상적으로 구현할 수 있도록 브라우저에게 요청하는 방법이라고 생각하면 됩니다. 즉 브라우저가 알아서 적절한 반복 루프를 생성해 최적화된 애니메이션을 생성해줍니다. 일반적으로 아래와 같이 사용합니다.
let objectX = 50;
const speed = 2; // 이동할 속도

function draw() {
  objCtx.clearRect(0, 0, objectCanvas.width, objectCanvas.height); // 캔버스 지우기

  // 캔버스에 그리기
  objCtx.fillStyle = 'red';
  objCtx.fillRect(objectX, 100, 50, 50); // 사각형의 오브젝트를 그리기
  objectX += speed; // 우측으로 이동하기 위해 speed 만큼 더하기
  requestAnimationFrame(draw); // 계속해서 반복되도록 하기
}

draw(); // 애니메이션 시작하기

위 예제는 간단한 애니메이션 구현 예제로 requestAnimationFrame() 사용시 해당 콜백 함수에서 자신을 호출하는 재귀 방식으로 사용됩니다. 다음으로 멀티 레이어 방식의 canvas 사용을 알아봅니다.


다중 레이어 캔버스(Multi-Layer Canvas) 태그 사용하기


캔버스에 애니메이션을 구현할 때 만약 여러 개의 오브젝트가 존재하는 경우를 생각해볼 수 있습니다. 이 경우 하나의 canvas 태그에서 모든 오브젝트를 그려야하는데 이동하는 애니메이션이 하나인 경우 모든 오브젝트를 다 그려야할 필요가 있을까 생각이 들 수 있겠죠. 이처럼 성능에 대한 고민을 해결하기 위한 방법으로 다중 레이어 방식의 여러 개의 캔버스 태그를 사용하는 것을 고려하게 됩니다.

@ 멀티 캔버스의 장단점 및 단일 이미지 생성 방법
이처럼 여러개의 캔버스를 사용할 경우 장점은 무엇일까요? 대표적으로 다음과 같은 이점이 있습니다.

- 성능 최적화 : 필요한 오브젝트만 다시 그릴 수 있어 성능상 유리
- 복잡한 효과 및 애니메이션 단순화 : 여러 개의 오브젝트를 레이어로 구분하여 개별로 처리할 수 있어 구조적으로 단순화 가능

반면에 단점이라면 멀티 캔버스를 어떻게 효과적으로 사용할 수 있는지 또 다른 고민이 필요합니다. 각각의 canvas를 겹쳐 사용할 경우 어떤 식으로 처리하는 게 개발 효율 및 리소스 사용 측면에서 유리할 지 생각해야하죠.


@ 멀티 레이어 방식의 canvas 전략과 이미지 추출 방법
다음으로 여러 개의 캔버스를 사용할 경우 이를 어떻게하면 하나의 이미지로 생성하여 추출할 수 있을까요? 이 경우 생각할 수 있는 방법은 메모리상에만 존재하는 별도의 canvas를 추가하고 여기에 모든 오브젝트의 드로잉을 추가하여 이미지로 추출하는 방법입니다. 메모리 상에서 그려주고 실제 화면에 렌더링하지 않기 때문에 성능에 큰 고민없이 이미지 추출이 가능하죠.

이때 각각의 canvas를 메모리상의 임의 canvas에 그려주기 위해서 drawImage()를 사용할 수 있습니다. drawImage() 이미지 파일을 그려주는데 사용하지만 이처럼 멀티 캔버스 방식인 경우에 다른 canvas를 그리는데도 사용할 수 있죠. 아래처럼 말입니다.
exportCtx.drawImage('layerOneCanvas');
exportCtx.drawImage('layerTwoCanvas');

const exportUrl = exportCanvas.toDataUrl('image/png');

쉽게 설명하면 이미지를 추출할 exportCtx 이름의 캔버스 컨텍스트에 각각의 오브젝트를 가지는 다른 캔버스를 그리는 방법입니다. 이처럼 모두 그려준 후 파일로 추출해 다운로드 하면 됩니다. 추가로 다운로드를 위해서는 임시 a 태그를 추가하고 href에 해당 exportUrl을 넣으면 됩니다.


여기까지 canvas 태그에 대하여 많은 부분을 알아보았습니다. 요즘은 웹 화면에서 2d 및 3d 게임까지도 쉽게 찾아볼 수 있는데요 ~ canvas 태그만 잘 알아두어도 높은 퀄리티의 게임이나 애니메이션 구현이 가능하니 알아두면 좋을 것 같습니다.

Previous

[html] base 태그 사용 방법 알아보기