icon
9장 : 웹 API와 브라우저 기능

Canvas API 기초

우리는 9장를 통해 Fetch API로 서버와 통신하고, 로컬/세션 스토리지로 클라이언트 데이터를 관리하며, History API로 SPA의 라우팅을 구현하는 등 웹 애플리케이션의 동적인 상호작용 및 내비게이션 기능을 학습했습니다. 이제 웹 페이지를 더욱 시각적으로 풍부하고 인터랙티브하게 만들 수 있는 강력한 브라우저 기능 중 하나인 Canvas API에 대해 알아볼 차례입니다.

Canvas API는 HTML5에 도입된 <canvas> 요소를 사용하여 웹 페이지에서 2D 그래픽을 직접 그릴 수 있도록 해주는 JavaScript API입니다. 픽셀 단위로 이미지를 조작하거나, 도형, 텍스트, 애니메이션 등을 자유롭게 렌더링할 수 있습니다. 이는 정적인 이미지로는 표현하기 어려운 동적인 시각화, 간단한 게임, 이미지 편집기, 데이터 시각화(차트 등) 등 다양한 분야에서 활용됩니다.

이번 장에서는 Canvas API의 기본적인 사용법, 즉 캔버스 요소 준비부터 컨텍스트 가져오기, 그리고 선, 사각형, 원, 텍스트 등 다양한 도형을 그리는 방법까지 상세히 다루겠습니다.


Canvas API 개요 및 <canvas> 요소

Canvas는 말 그대로 '도화지'와 같습니다. HTML 문서에는 <canvas>라는 빈 도화지 요소를 배치하고, 실제 그림은 JavaScript 코드를 사용하여 이 도화지 위에 그리는 방식입니다.

<canvas> 요소 준비

HTML 문서에 <canvas> 태그를 추가하여 그림을 그릴 공간을 정의합니다. widthheight 속성으로 캔버스의 크기를 지정할 수 있습니다. (CSS로 크기를 조절할 수도 있지만, 렌더링 품질에 영향을 줄 수 있으므로 HTML 속성으로 고정 크기를 지정하는 것이 좋습니다.)

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canvas API 기초</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background-color: #f0f0f0;
            margin: 0;
        }
        canvas {
            border: 2px solid #333; /* 캔버스 경계를 시각적으로 보여주기 위함 */
            background-color: #fff;
        }
    </style>
</head>
<body>
    <canvas id="myCanvas" width="500" height="300">
        이 브라우저는 Canvas를 지원하지 않습니다.
    </canvas>

    <script src="canvas-script.js"></script>
</body>
</html>

렌더링 컨텍스트 가져오기

<canvas> 요소 자체는 그림을 그릴 수 있는 인터페이스를 직접 제공하지 않습니다. 그림을 그리기 위해서는 렌더링 컨텍스트(Rendering Context) 를 얻어야 합니다. 가장 흔히 사용되는 것은 2D 그래픽을 위한 '2d' 컨텍스트입니다.

// canvas-script.js
const canvas = document.getElementById('myCanvas');

// getContext() 메서드를 사용하여 렌더링 컨텍스트를 가져옵니다.
const ctx = canvas.getContext('2d');

// 캔버스가 정상적으로 초기화되었는지 확인
if (ctx) {
    console.log("2D 렌더링 컨텍스트를 성공적으로 가져왔습니다.");
    // 이제 ctx 객체를 사용하여 그림을 그릴 수 있습니다.
} else {
    console.error("이 브라우저는 Canvas 2D 컨텍스트를 지원하지 않습니다.");
}

ctx (Context) 객체는 캔버스에 도형, 텍스트, 이미지 등을 그리는 데 필요한 모든 메서드와 속성을 가지고 있습니다.


기본적인 도형 그리기

Canvas에서 그림을 그리는 과정은 보통 다음과 같습니다.

  1. 경로 시작: ctx.beginPath()로 새로운 그림 경로를 시작합니다.
  2. 경로 정의: moveTo(), lineTo(), arc(), rect() 등으로 경로를 정의합니다.
  3. 그림 그리기: stroke()로 선을 그리거나, fill()로 도형을 채웁니다.
  4. (선택) 경로 닫기: closePath()로 현재 경로를 시작점으로 연결하여 닫습니다.

선(Lines) 그리기

// 선의 색상 설정
ctx.strokeStyle = 'blue';
// 선의 두께 설정
ctx.lineWidth = 5;

// 첫 번째 선: (50, 50)에서 (200, 50)까지
ctx.beginPath();       // 새로운 경로 시작
ctx.moveTo(50, 50);    // 시작점 이동
ctx.lineTo(200, 50);   // (200, 50)까지 선 그리기
ctx.stroke();          // 경로를 따라 선 그리기 (stroke)

// 두 번째 선: (200, 50)에서 (200, 150)까지
// beginPath()를 다시 호출하면 이전 경로와 독립적으로 그림
ctx.beginPath();
ctx.moveTo(200, 50);
ctx.lineTo(200, 150);
ctx.stroke();

// 삼각형 그리기
ctx.strokeStyle = 'red';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(300, 100);
ctx.lineTo(350, 200);
ctx.lineTo(250, 200);
ctx.closePath(); // 시작점으로 경로를 닫아 삼각형 완성
ctx.stroke();

사각형(Rectangles) 그리기

사각형을 그리는 전용 메서드가 있습니다.

  • ctx.rect(x, y, width, height): 사각형 경로를 정의
  • ctx.strokeRect(x, y, width, height): 윤곽선 사각형 그리기
  • ctx.fillRect(x, y, width, height): 채워진 사각형 그리기
  • ctx.clearRect(x, y, width, height): 지정된 영역을 투명하게 지우기
// 채워진 사각형 (fillStyle 설정)
ctx.fillStyle = 'green'; // 채울 색상 설정
ctx.fillRect(50, 100, 100, 50); // (x, y, width, height)

// 윤곽선 사각형 (strokeStyle, lineWidth 설정)
ctx.strokeStyle = 'purple';
ctx.lineWidth = 3;
ctx.strokeRect(200, 100, 100, 50);

// 특정 영역 지우기
ctx.clearRect(70, 110, 60, 30); // 초록색 사각형의 일부를 지움

원(Arcs/Circles) 그리기

arc() 메서드를 사용하여 원 또는 호를 그립니다.

  • ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise)
    • x, y: 원의 중심 좌표
    • radius: 반지름
    • startAngle, endAngle: 호의 시작 및 끝 각도 (라디안 단위)
    • counterclockwise: true면 반시계 방향, false면 시계 방향 (기본값)
// 라디안 계산: Math.PI는 파이 (180도)
// 전체 원: 0부터 2 * Math.PI
// 반원: 0부터 Math.PI

// 채워진 원
ctx.fillStyle = 'orange';
ctx.beginPath();
ctx.arc(150, 230, 40, 0, 2 * Math.PI, false); // (x, y, 반지름, 시작각, 끝각, 반시계방향)
ctx.fill();

// 윤곽선 원
ctx.strokeStyle = 'darkblue';
ctx.lineWidth = 4;
ctx.beginPath();
ctx.arc(350, 230, 40, 0, 2 * Math.PI, false);
ctx.stroke();

// 반원 (파이차트 조각처럼)
ctx.fillStyle = 'lightblue';
ctx.beginPath();
ctx.moveTo(400, 50); // 중심점에서 시작
ctx.arc(400, 50, 40, 0, Math.PI, false); // 오른쪽 절반 원
ctx.closePath(); // 시작점으로 다시 돌아와 닫음 (채우려면 필요)
ctx.fill();

텍스트(Text) 그리기

텍스트를 그리는 메서드와 스타일 속성이 있습니다.

  • ctx.fillText(text, x, y, maxWidth): 채워진 텍스트 그리기
  • ctx.strokeText(text, x, y, maxWidth): 윤곽선 텍스트 그리기

텍스트 스타일 속성

  • ctx.font: 폰트 스타일 (예: '48px serif')
  • ctx.textAlign: 텍스트 정렬 ('left', 'right', 'center', 'start', 'end')
  • ctx.textBaseline: 텍스트 기준선 ('alphabetic', 'top', 'hanging', 'middle', 'ideographic', 'bottom')
ctx.fillStyle = 'black';
ctx.font = '30px Arial'; // 폰트 크기와 패밀리
ctx.textAlign = 'center'; // 수평 정렬
ctx.textBaseline = 'middle'; // 수직 정렬

// 캔버스 중앙에 텍스트 그리기
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;

ctx.fillText('Hello Canvas!', centerX, centerY);

ctx.strokeStyle = 'gray';
ctx.lineWidth = 1;
ctx.font = '20px Sans-serif';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.strokeText('Web Graphics', 10, 10);

경로(Paths) 상태 저장 및 복원

캔버스 컨텍스트의 현재 그리기 상태(색상, 선 두께, 변형 등)를 저장하고 나중에 복원할 수 있습니다. 이는 복잡한 그림을 그릴 때 매우 유용합니다.

  • ctx.save(): 현재 그리기 상태를 스택에 저장합니다.
  • ctx.restore(): 스택의 가장 최근 상태를 복원합니다.
// 기본 상태: 빨간색, 두께 2
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 50, 50); // (0,0)에 빨간색 사각형

ctx.save(); // 현재 상태 저장 (빨간색, 두께 2)

ctx.fillStyle = 'blue'; // 새로운 상태: 파란색
ctx.fillRect(60, 0, 50, 50); // (60,0)에 파란색 사각형

ctx.save(); // 현재 상태 저장 (파란색, 두께 2)

ctx.fillStyle = 'green'; // 새로운 상태: 초록색
ctx.fillRect(120, 0, 50, 50); // (120,0)에 초록색 사각형

ctx.restore(); // 스택에서 가장 최근 상태 복원 (파란색)
ctx.fillRect(180, 0, 50, 50); // (180,0)에 파란색 사각형

ctx.restore(); // 스택에서 다음 상태 복원 (빨간색)
ctx.fillRect(240, 0, 50, 50); // (240,0)에 빨간색 사각형

save()restore()는 색상, 선 스타일, 그림자, 변형(이동, 회전, 크기 조절) 등 모든 컨텍스트 속성들을 저장하고 복원합니다.


Canvas API 활용 분야

  • 게임 개발: 2D 게임 엔진이나 캐주얼 게임 개발에 널리 사용됩니다.
  • 데이터 시각화: 차트(막대 그래프, 파이 차트, 선 그래프 등)나 복잡한 통계 데이터를 시각적으로 표현하는 데 활용됩니다 (예: Chart.js).
  • 이미지 편집: 이미지 필터 적용, 크롭, 회전, 그림 그리기 등의 기능 구현.
  • 애니메이션: 프레임 단위로 그림을 지우고 다시 그리면서 동적인 애니메이션 효과를 만듭니다.
  • 사용자 정의 UI 컴포넌트: SVG만으로는 부족한 복잡한 그래픽이 필요할 때 사용됩니다.

마무리하며

이번 장에서는 HTML5에 도입된 강력한 웹 그래픽 도구인 Canvas API의 기초를 심도 있게 학습했습니다.

여러분은 <canvas> 요소를 HTML에 추가하고, JavaScript에서 getContext('2d')를 통해 2D 렌더링 컨텍스트를 얻는 방법을 배웠습니다. 그리고 이 컨텍스트(ctx) 객체를 사용하여 선, 사각형, 원과 같은 기본적인 도형을 그리는 방법(beginPath(), moveTo(), lineTo(), stroke(), fill(), arc(), fillRect() 등)과 텍스트를 그리는 방법(fillText(), strokeText(), font, textAlign 등)을 익혔습니다. 또한, save()restore()를 사용하여 그리기 상태를 효율적으로 관리하는 방법도 살펴보았습니다.

Canvas API는 웹 페이지에서 정적인 이미지로는 표현하기 어려운 복잡하고 동적인 그래픽을 직접 제어할 수 있는 무한한 가능성을 제공합니다. 앞으로 여러분이 웹 게임, 데이터 시각화, 인터랙티브 아트 등 다양한 분야에 도전할 때 이 Canvas API 지식이 큰 자산이 될 것입니다. 직접 다양한 도형을 그려보고, 색상을 변경하며 Canvas의 매력을 느껴보세요.