SVG와 캔버스 기초
지금까지 우리는 HTML을 사용하여 웹 페이지의 구조를 만들고, 텍스트, 링크, 일반 이미지(<img>
), 그리고 비디오/오디오와 같은 멀티미디어 콘텐츠를 삽입하는 방법을 학습했습니다. 이제는 웹에서 그래픽을 다루는 두 가지 강력한 기술인 SVG와 Canvas에 대해 알아볼 차례입니다.
HTML5는 웹 표준만으로도 복잡하고 동적인 그래픽을 웹 페이지에 구현할 수 있는 길을 열었습니다. 이 장에서는 벡터 기반 그래픽의 대표주자인 SVG(Scalable Vector Graphics) 와 픽셀 기반 그래픽을 위한 Canvas의 기본적인 개념과 각각의 장단점, 그리고 간단한 사용법을 살펴보겠습니다. 이 두 기술은 웹 애플리케이션에서 다이어그램, 차트, 게임, 인터랙티브 애니메이션 등 다양한 시각적 요소를 구현하는 데 필수적인 기반이 됩니다.
SVG: 확장 가능한 벡터 그래픽
SVG는 XML 기반의 벡터 그래픽을 웹에 표현하기 위한 마크업 언어입니다. '벡터 그래픽'이라는 것은 그림을 점, 선, 면 등의 수학적인 형태로 정의한다는 의미입니다. JPG, PNG와 같은 '비트맵 그래픽'(픽셀 기반)과는 근본적으로 다릅니다.
SVG의 특징 및 장점
확장성 (Scalable): 가장 큰 특징이자 장점입니다. 벡터 방식이므로 아무리 확대해도 이미지가 깨지거나 흐려지지 않습니다. 로고, 아이콘, 다이어그램 등 다양한 해상도의 기기에서 선명하게 보여야 하는 그래픽에 매우 적합합니다.
작은 파일 크기: 복잡하지 않은 벡터 그래픽의 경우, 비트맵 이미지보다 파일 크기가 훨씬 작아 로딩 속도를 개선할 수 있습니다.
편집 용이성: SVG 코드는 XML 기반의 텍스트이므로, 텍스트 편집기나 SVG 편집 소프트웨어에서 쉽게 수정할 수 있습니다. 또한 CSS와 자바스크립트를 사용하여 색상, 크기, 위치 등을 동적으로 제어하고 애니메이션을 적용할 수 있습니다.
웹 접근성: SVG 요소는 의미론적인 정보(예: <title>
, <desc>
)를 포함할 수 있어, 스크린 리더와 같은 보조 기술이 그래픽의 내용을 이해하는 데 도움을 줍니다.
검색 가능: SVG는 텍스트 기반이므로, 검색 엔진이 이미지 내부의 텍스트를 인식할 수 있어 SEO에 유리할 수 있습니다.
SVG 기본 문법과 활용
SVG는 HTML 문서 내에 <svg>
태그를 사용하여 직접 삽입하거나, .svg
파일로 저장하여 <img>
태그나 CSS의 background-image
속성을 통해 참조할 수 있습니다. 여기서는 HTML 내에 직접 삽입하는 방식을 위주로 살펴봅니다.
-
<svg>
태그: SVG 그래픽을 그릴 캔버스 역할을 합니다.width
와height
속성으로 영역을 지정합니다.<svg width="200" height="200"> </svg>
-
기본 도형 그리기
<rect>
(직사각형):x
,y
,width
,height
,fill
,stroke
,stroke-width
등의 속성을 사용합니다.<svg width="200" height="100"> <rect x="10" y="10" width="80" height="80" fill="blue" stroke="black" stroke-width="3" /> </svg>
<circle>
(원):cx
,cy
(중심점 좌표),r
(반지름),fill
,stroke
등의 속성을 사용합니다.<svg width="200" height="100"> <circle cx="50" cy="50" r="40" fill="red" stroke="purple" stroke-width="2" /> </svg>
<line>
(선):x1
,y1
(시작점),x2
,y2
(끝점),stroke
,stroke-width
등의 속성을 사용합니다.<svg width="200" height="100"> <line x1="10" y1="10" x2="190" y2="90" stroke="green" stroke-width="4" /> </svg>
<polygon>
(다각형):points
속성에 점들의 좌표를 공백으로 구분하여 나열합니다.<svg width="200" height="200"> <polygon points="100,10 190,90 10,90" fill="orange" stroke="brown" stroke-width="2" /> </svg>
<text>
(텍스트):x
,y
(텍스트 시작 좌표),fill
,font-size
등의 속성을 사용합니다.<svg width="200" height="100"> <text x="10" y="50" fill="darkblue" font-size="20">Hello SVG!</text> </svg>
-
CSS와 자바스크립트를 이용한 제어: SVG 요소는 HTML 요소와 마찬가지로 CSS로 스타일링하거나 자바스크립트로 조작할 수 있습니다.
<style> .my-circle { fill: #ffd700; /* 금색 */ stroke: #cc0000; stroke-width: 5; transition: fill 0.3s ease; /* 호버 시 색상 변화 애니메이션 */ } .my-circle:hover { fill: #ff4500; /* 오렌지색 */ } </style> <svg width="100" height="100"> <circle cx="50" cy="50" r="40" class="my-circle" id="interactiveCircle" /> </svg> <script> const circle = document.getElementById('interactiveCircle'); circle.addEventListener('click', () => { alert('SVG 원을 클릭했습니다!'); circle.setAttribute('r', '50'); // 반지름 변경 }); </script>
Canvas: 비트맵 그래픽 그리기
Canvas는 HTML5에서 도입된 <canvas>
태그와 자바스크립트 API를 사용하여 비트맵(픽셀) 기반의 2D 그래픽을 웹 페이지에 직접 그릴 수 있도록 하는 기술입니다. '캔버스'라는 이름처럼, 마치 그림을 그리는 도화지와 같습니다.
Canvas의 특징 및 장점
픽셀 기반: 이미지를 픽셀 단위로 직접 조작합니다. 복잡한 그래픽, 이미지 필터, 게임 그래픽 등 픽셀 단위의 정교한 제어가 필요할 때 적합합니다.
자바스크립트 제어: 모든 그리기는 자바스크립트 코드를 통해 이루어집니다. 이를 통해 매우 동적이고 인터랙티브한 그래픽을 생성할 수 있습니다.
고성능: 복잡한 애니메이션이나 게임처럼 빠른 업데이트가 필요한 경우, Canvas는 웹 브라우저의 GPU 가속을 활용하여 높은 성능을 발휘할 수 있습니다.
다양한 활용: 차트, 그래프, 사진 편집기, 게임, 웹 기반 드로잉 툴 등 다양한 웹 애플리케이션에서 활용됩니다.
Canvas 기본 문법과 활용
-
<canvas>
태그: 그림을 그릴 영역을 정의합니다.width
와height
속성으로 캔버스의 크기를 지정합니다.<canvas id="myCanvas" width="400" height="200" style="border:1px solid #000;"></canvas>
<canvas>
태그 자체는 비어 있습니다. 모든 그리기 작업은 자바스크립트를 통해 이루어집니다.style
속성은 단순히 캔버스 요소 자체의 시각적 스타일을 지정할 뿐, 캔버스 내부의 그림에는 영향을 주지 않습니다.
-
자바스크립트를 이용한 그리기
캔버스 요소 가져오기:
document.getElementById()
를 사용하여<canvas>
요소를 가져옵니다.렌더링 컨텍스트 얻기: 캔버스에 그림을 그리기 위한 '컨텍스트' 객체를 얻습니다. 2D 그래픽의 경우
getContext('2d')
를 사용합니다.그리기 명령 실행: 컨텍스트 객체의 메서드를 사용하여 도형, 텍스트, 이미지 등을 그립니다.
<canvas id="myDrawingCanvas" width="300" height="150" style="border:2px solid #ccc;"></canvas> <script> const canvas = document.getElementById('myDrawingCanvas'); const ctx = canvas.getContext('2d'); // 2D 렌더링 컨텍스트 가져오기 // 1. 사각형 그리기 ctx.fillStyle = 'green'; // 채우기 색상 설정 ctx.fillRect(10, 10, 100, 50); // (x, y, width, height) // 2. 원 그리기 ctx.beginPath(); // 새로운 경로 시작 ctx.arc(180, 75, 40, 0, 2 * Math.PI); // (x, y, 반지름, 시작각도, 끝각도) ctx.fillStyle = 'orange'; ctx.fill(); // 채우기 ctx.lineWidth = 3; // 선 두께 ctx.strokeStyle = 'red'; // 선 색상 ctx.stroke(); // 선 그리기 // 3. 텍스트 그리기 ctx.font = '24px Arial'; ctx.fillStyle = 'darkblue'; ctx.textAlign = 'center'; ctx.fillText('Hello Canvas!', canvas.width / 2, 130); // (텍스트, x, y) </script>
SVG와 Canvas의 차이점 및 선택 기준
특징 | SVG (Scalable Vector Graphics) | Canvas |
---|---|---|
기반 | 벡터 기반 (수학적 도형, XML 코드) | 비트맵/픽셀 기반 (래스터 이미지) |
조작 방식 | 각 도형이 DOM 요소로 존재, CSS/JS로 개별 조작 용이 | 전체 캔버스를 하나의 비트맵으로 JS로 픽셀 조작 |
확장성 | 무한히 확대해도 깨지지 않음 (해상도 독립적) | 확대하면 픽셀이 보이며 깨짐 (해상도 의존적) |
성능 | 복잡한 장면에서 많은 요소가 있으면 성능 저하 가능 | 대량의 픽셀 조작 및 애니메이션에 고성능 |
주요 용도 | 로고, 아이콘, 다이어그램, 일러스트, 인터랙티브 차트 | 게임, 이미지 편집, 복잡한 데이터 시각화 |
접근성 | 요소 자체가 의미를 가지므로 접근성 높음 | 캔버스 자체는 이미지이므로 접근성 고려 필요 |
파일 크기 | 단순한 그래픽은 작고, 복잡한 그래픽은 커질 수 있음 | 해상도와 내용에 따라 다름 |
언제 무엇을 사용할까?
- SVG
- 로고, 아이콘, 지도를 포함한 확장성이 필요한 그래픽.
- 데이터 변화에 따라 요소별로 색상이나 크기를 바꿔야 하는 인터랙티브 차트/다이어그램.
- 간단한 애니메이션이나 상태 변화를 CSS/JS로 제어할 필요가 있는 경우.
- 검색 엔진이나 스크린 리더가 그래픽 내용을 이해해야 하는 경우.
- Canvas
- 픽셀 단위의 정교한 그래픽 제어가 필요한 경우 (이미지 필터, 사진 편집기).
- 높은 프레임 속도를 요구하는 게임이나 복잡한 애니메이션.
- 수백, 수천 개의 요소가 동적으로 생성/소멸되어야 하는 대규모 데이터 시각화.
- 그려진 결과물만 중요하고, 각 객체에 대한 개별적인 DOM 조작이 불필요한 경우.
실습: 간단한 Canvas 애니메이션 만들기
두 기술의 기본적인 차이를 직접 경험해 봅시다.
새 파일 준비
web-dev-practice
폴더 안에graphics_playground.html
파일을 새로 생성합니다.
HTML 구조와 SVG, Canvas 코드 작성
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG와 Canvas 기초 실습</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 20px;
background-color: #f8f8f8;
color: #333;
text-align: center;
}
.container {
max-width: 900px;
margin: 20px auto;
background-color: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
display: flex;
flex-wrap: wrap;
justify-content: space-around;
gap: 30px;
}
section {
flex: 1 1 45%; /* 유연하게 공간 차지, 최소 너비 45% */
min-width: 350px;
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
background-color: #fafafa;
}
h1 {
color: #007bff;
margin-bottom: 40px;
}
h2 {
color: #0056b3;
margin-top: 0;
}
svg {
display: block;
margin: 20px auto;
border: 1px solid #ccc;
background-color: #fff;
border-radius: 5px;
}
.svg-icon-example {
display: inline-block; /* 아이콘들이 한 줄에 있도록 */
margin: 10px;
padding: 10px;
border: 1px solid #eee;
border-radius: 5px;
transition: transform 0.2s ease-out;
}
.svg-icon-example:hover {
transform: scale(1.1);
box-shadow: 0 0 8px rgba(0,0,0,0.1);
}
.svg-icon-example svg {
border: none; /* 개별 아이콘은 보더 제거 */
margin: 0;
}
canvas {
border: 1px solid #ccc;
background-color: #fff;
border-radius: 5px;
display: block;
margin: 20px auto;
}
button {
padding: 10px 20px;
background-color: #28a745;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 1em;
margin-top: 15px;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #218838;
}
</style>
</head>
<body>
<h1>SVG와 Canvas 기초 실습</h1>
<div class="container">
<section>
<h2>SVG 아이콘 예시 (벡터 그래픽)</h2>
<p>SVG는 확대해도 깨지지 않는 선명한 벡터 이미지를 제공합니다.</p>
<div class="svg-icon-example" title="홈 아이콘">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
</div>
<div class="svg-icon-example" title="사용자 아이콘">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
</div>
<div class="svg-icon-example" title="메일 아이콘">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
</div>
<h3>간단한 SVG 도형 그리기</h3>
<svg width="200" height="150">
<rect x="20" y="20" width="60" height="60" fill="#ff7f50" stroke="#cd5b45" stroke-width="3">
<title>주황색 사각형</title>
</rect>
<circle cx="150" cy="75" r="50" fill="#6a5acd" stroke="#483d8b" stroke-width="3">
<title>보라색 원</title>
</circle>
<text x="100" y="140" text-anchor="middle" font-size="18" fill="#333">SVG 도형들</text>
</svg>
</section>
<section>
<h2>Canvas 애니메이션 예시 (비트맵 그래픽)</h2>
<p>Canvas는 자바스크립트로 픽셀 단위의 동적인 그림을 그립니다.</p>
<canvas id="animatedCanvas" width="350" height="200"></canvas>
<button id="startButton">애니메이션 시작/정지</button>
<script>
const canvas = document.getElementById('animatedCanvas');
const ctx = canvas.getContext('2d');
const startButton = document.getElementById('startButton');
let animationFrameId; // requestAnimationFrame ID
let x = 50;
let dx = 2; // x 방향 속도
let radius = 20;
function drawCircle() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // 캔버스 지우기
ctx.beginPath();
ctx.arc(x, canvas.height / 2, radius, 0, Math.PI * 2);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.closePath();
}
function animate() {
drawCircle();
x += dx;
// 벽에 부딪히면 방향 반전
if (x + radius > canvas.width || x - radius < 0) {
dx = -dx;
}
animationFrameId = requestAnimationFrame(animate); // 다음 프레임 요청
}
let isAnimating = false;
startButton.addEventListener('click', () => {
if (isAnimating) {
cancelAnimationFrame(animationFrameId); // 애니메이션 정지
startButton.textContent = '애니메이션 시작';
} else {
animate(); // 애니메이션 시작
startButton.textContent = '애니메이션 정지';
}
isAnimating = !isAnimating;
});
// 페이지 로드 시 초기 상태 그리기
drawCircle();
</script>
</section>
</div>
</body>
</html>
결과 확인
- Live Server를 통해
graphics_playground.html
파일을 열어보세요. - SVG 섹션에서는 다양한 아이콘과 도형이 선명하게 보일 것입니다. 브라우저에서 확대/축소해도 깨지지 않는지 확인해 보세요.
- Canvas 섹션에서는 '애니메이션 시작' 버튼을 눌러 원이 좌우로 움직이는 간단한 애니메이션을 확인해 보세요.
이번 장에서는 웹에서 그래픽을 다루는 두 가지 강력한 기술인 SVG와 Canvas에 대해 알아보았습니다. SVG가 벡터 기반으로 확장성과 편집 용이성에 강점이 있다면, Canvas는 픽셀 기반으로 복잡한 동적 그래픽과 고성능 게임 구현에 유리하다는 것을 이해하셨을 것입니다.