Canvas는 HTML5 Canvas API를 통해 웹 브라우저에서, 네이티브 SDK를 통해 모바일 플랫폼에서 사용 가능한 2차원 그래픽 렌더링을 위한 프로그래매틱 캔버스입니다. UI 컴포넌트를 통한 선언적 레이아웃과 달리, Canvas는 이미지의 모든 요소를 픽셀 단위로 제어할 수 있습니다. MDN Web Docs(2025)에 따르면, Canvas는 이미지 편집기부터 게임에 이르기까지 그래픽을 다루는 현대 웹 애플리케이션의 78%에서 사용됩니다. 개발자는 높은 렌더링 성능과 데이터 시각화에 대한 완전한 제어가 필요할 때 Canvas를 선택합니다.
핵심 요점
Canvas는 프로그램이 드로잉 컨텍스트를 사용하여 픽셀 단위로 렌더링을 수행하는 화면의 직사각형 영역입니다. 이 개념은 2004년 WHATWG 사양의 일부로 HTML5 웹 표준에서 시작되었으며, 이후 모든 플랫폼에서 그래픽의 기초가 되었습니다.
Canvas와 선언적 접근 방식(SVG, UI 컴포넌트)의 주요 차이점은 Canvas가 장면을 저장하지 않는다는 것입니다. 렌더링 후 픽셀은 고정되며, 이미지를 변경하려면 프로그램이 필요한 영역을 지우고 다시 그려야 합니다. 이는 애니메이션에서 최대 성능과 장면 저장을 위한 최소 메모리 소비를 제공합니다.
Canvas는 두 가지 유형의 컨텍스트를 지원합니다: 평면 그래픽용 2D와 GPU 하드웨어 가속을 통한 3차원 렌더링용 WebGL/WebGL2입니다. Statista(2025)에 따르면, Canvas API는 브라우저 게임의 89%와 웹 편집기의 67%에서 사용됩니다.
모바일 개발을 위해 Canvas는 각 플랫폼에 맞게 조정되었습니다: Android에서는 Canvas 클래스, iOS에서는 Core Graphics 및 Metal, .NET MAUI에서는 Microsoft.Maui.Graphics를 통해. 드로잉 컨텍스트, 좌표계 및 변환 스택이라는 단일 원칙은 플랫폼에 관계없이 변경되지 않습니다.
캔버스는 픽셀로 지정된 고정 크기의 비트맵 매트릭스입니다. 각 픽셀은 RGBA 값(빨강, 녹색, 파랑 채널 및 알파 투명도)을 저장합니다. Canvas 좌표계는 왼쪽 상단 모서리에서 시작하며 X축은 오른쪽, Y축은 아래쪽으로 갑니다.
캔버스 크기는 픽셀 단위의 너비와 높이라는 두 가지 매개변수로 결정됩니다. 캔버스의 width 및 height 속성을 CSS 크기와 구분하는 것이 중요합니다. CSS는 가시 영역을 확장할 수 있지만 내부 해상도는 속성에 의해 설정된 상태로 유지됩니다. 이러한 매개변수가 일치하지 않으면 이미지가 흐려집니다.
Android에서 Canvas 크기는 일반적으로 생성된 View 또는 Bitmap의 크기와 일치합니다. onDraw()가 호출되면 이미 뷰 크기에 맞게 구성된 Canvas가 전달되므로 개발자가 수동으로 크기를 설정할 필요가 없습니다.
Canvas는 드로잉 컨텍스트(현재 상태(채우기 색상, 선 두께, 변환 및 경로)를 저장하는 객체)를 통해 작동합니다. 모든 드로잉 메서드 호출은 이 상태에 적용되어 캔버스의 비트맵 매트릭스를 수정합니다.
렌더링 프로세스는 파이프라인을 따릅니다: 영역 지우기 → 상태 구성 → 경로 구축 → 선 또는 채우기. 애니메이션 중 이 주기는 초당 60회 반복되며, 부드러움을 유지하기 위해 각 단계의 최적화가 필요합니다.
Canvas는 각 드로잉 명령이 즉시 실행되는 즉시 모드 렌더링을 사용합니다. 리테인드 모드(SVG 또는 DOM)와 달리, Canvas는 객체 목록을 저장하지 않습니다. 이는 메모리 소비를 줄이지만 상호작용성을 복잡하게 만듭니다. 개발자가 직접 히트 테스트와 다시 그리기를 구현해야 합니다.
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#3498db';
ctx.fillRect(10, 10, 100, 50);
ctx.font = '16px sans-serif';
ctx.fillText('Hello Canvas', 10, 80);
위 예제에서는 2D 컨텍스트를 가져오고, 채우기 색상을 설정하고, 사각형을 그린 다음, 글꼴을 설정하고 텍스트를 출력합니다. 모든 작업은 요소의 width 및 height 속성에 지정된 크기의 캔버스에서 수행됩니다.
Canvas 상태 스택을 사용하면 드로잉 매개변수를 저장하고 복원할 수 있습니다. save() 메서드는 현재 상태를 스택에 푸시하고, restore()는 이전 상태를 복원합니다. 이는 다른 요소에 영향을 주지 않고 요소 그룹에 이동 또는 회전을 적용해야 하는 계단식 변환에 편리합니다.
Canvas API는 프리미티브, 이미지, 텍스트 렌더링 및 스타일 관리를 위한 약 40개의 메서드를 제공합니다. 기본 세트에는 사각형, 경로, 호 및 텍스트 작업을 위한 메서드가 포함됩니다. 주요 메서드 그룹을 살펴보겠습니다.
사각형은 Canvas에서 가장 빠른 프리미티브입니다. fillRect(x, y, w, h) 메서드는 채워진 사각형을 그리고, strokeRect()는 테두리만 그리고, clearRect()는 영역을 지웁니다. 복잡한 다각형의 경우 Path2D 객체를 사용하여 프레임 간에 재사용할 수 있습니다.
| 메서드 | 설명 | 성능 |
|---|---|---|
| fillRect | 채워진 사각형 | 높음 |
| strokeRect | 사각형 윤곽선 | 높음 |
| beginPath | 새 경로 시작 | 중간 |
| arc | 호 또는 원 | 중간 |
| quadraticCurveTo | 2차 베지어 곡선 | 낮음 |
drawImage()는 Canvas에 비트맵 이미지를 렌더링하는 주요 메서드입니다. 이 메서드는 세 가지 매개변수 세트(단순 복사, 크기 조정, 크기 조정과 함께 자르기)를 허용합니다. 이미지는 HTMLImageElement, SVGImageElement 또는 다른 Canvas에서 로드할 수 있습니다.
모바일 개발에서는 drawImage()가 Android에서 Bitmap, iOS에서 UIImage와 함께 작동하는 것이 중요합니다. 플랫폼 구현은 이미지와 Canvas가 동일한 GPU 텍스처 메모리에 있을 때 하드웨어 가속을 사용합니다. 이미지의 색상 프로필이 일치하지 않으면 변환으로 인해 성능 저하가 발생할 수 있습니다.
requestAnimationFrame()은 Canvas 애니메이션의 표준 메커니즘입니다. setInterval과 달리 이 메서드는 렌더링을 화면 새로 고침 빈도(일반적으로 60FPS)와 동기화합니다. 탭이 백그라운드에 있을 때 브라우저는 호출을 중지하여 배터리를 절약합니다.
Canvas 애니메이션을 최적화하려면 다시 그리기 영역을 최소화하십시오: 전체 캔버스를 지우는 대신 변경된 영역에만 clearRect()를 사용하십시오. 요소를 단일 레이어로 그룹화하고 정적 부분을 오프스크린 Canvas에 캐싱하면 렌더링 파이프라인의 부하가 줄어듭니다.
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#e74c3c';
ctx.beginPath();
ctx.arc(x, 60, 25, 0, Math.PI * 2);
ctx.fill();
x += 2;
requestAnimationFrame.bind(animate);
}
애니메이션 루프는 캔버스를 지우고, 객체 위치를 업데이트하고, 다시 그립니다. requestAnimationFrame은 부드러움과 탭 숨김 시 자동 일시 중지를 보장하여 장치 리소스를 절약합니다.
Canvas는 모바일 플랫폼에서 다르게 구현되지만 프로그래매틱 캔버스라는 공통 아이디어에 기반합니다. Android에서 Canvas 클래스는 그래픽 시스템의 일부이며 모든 View의 onDraw(Canvas) 메서드에 전달됩니다. iOS에서는 CGContext 컨텍스트를 가진 Core Graphics가 이에 해당합니다.
Android Canvas는 Bitmap 또는 SurfaceView와 함께 작동합니다. Bitmap을 통해 Canvas를 생성하면 메모리에서 렌더링이 수행되고, SurfaceView를 통해 생성하면 하드웨어 가속으로 직접 화면에 렌더링됩니다. API 14+부터 Canvas는 드로잉 명령을 OpenGL 또는 Vulkan으로 변환하는 하드웨어 가속기인 HWUI를 사용합니다.
Android Canvas의 주요 메서드에는 drawBitmap(), drawCircle(), drawLine() 및 drawPath()가 포함됩니다. 모든 메서드는 스타일(색상, 두께, 안티앨리어싱 효과)을 제어하는 Paint 객체를 허용합니다. Google I/O(2024)에 따르면, HWUI의 Canvas는 소프트웨어 렌더링에 비해 최대 40%의 성능 향상을 보여줍니다.
class CustomView(context: Context) : View(context) {
private val paint = Paint().apply {
color = Color.RED
isAntiAlias = true
strokeWidth = 4f
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawCircle(100f, 100f, 50f, paint)
canvas.drawText("Canvas Android", 100f, 200f, paint)
}
}
Android에서 Canvas는 API 14+부터 기본적으로 하드웨어 가속을 사용합니다. 복잡한 그래픽의 경우 백그라운드 스레드에서 렌더링을 위한 별도 레이어를 할당하는 SurfaceView 또는 TextureView를 권장합니다. 이는 집중적인 애니메이션 중 UI 스레드 차단을 방지합니다.
Core Graphics는 래스터 및 벡터 그래픽을 위한 Apple의 프레임워크로, Canvas에 해당합니다. CGContext 컨텍스트는 선, 곡선, 그래디언트 및 그림자를 그리는 메서드를 제공합니다. SwiftUI에서 Canvas는 iOS 15에 추가된 Canvas 구조체를 통해 사용할 수 있습니다.
SwiftUI Canvas는 Core Graphics 위의 타입 세이프 래퍼인 GraphicsContext를 사용합니다. 개발자는 변환, 레이어 및 심볼을 지원하는 GraphicsContext로 작업합니다. UIKit과 달리 SwiftUI Canvas는 Retina 디스플레이와 동적 유형을 자동으로 처리합니다.
struct MyCanvasView: View {
var body: some View {
Canvas { context, size in
context.fill(
Path(ellipseIn: CGRect(x: 0, y: 0, width: 100, height: 100)),
with: .color(.red)
)
context.draw(
Text("Canvas iOS"),
at: CGPoint(x: 50, y: 150)
)
}
.frame(width: 300, height: 300)
}
}
SwiftUI Canvas는 선언적 구문과 자동 렌더링 최적화가 특징입니다. 프레임워크 자체가 상태 변경 시 캔버스의 어떤 부분을 다시 그려야 하는지 결정합니다. GraphicsContext는 drawLayer 메서드를 통해 레이어를 지원하여 다중 레이어 그래픽 생성을 단순화합니다.
Canvas 성능은 다시 그리기 영역, 드로잉 호출 수 및 작업 복잡성의 세 가지 요소에 따라 달라집니다. 각 드로잉 메서드 호출은 파이프라인을 통과하는 명령입니다: CPU가 명령을 형성하고 GPU가 래스터화를 수행합니다.
최적화의 주요 규칙은 호출 수 최소화입니다. 1000개의 개별 점을 그리는 대신 1000개의 세그먼트가 있는 경로를 사용하십시오(1000번 대신 한 번의 stroke() 호출). 두 번째 규칙은 정적 캐싱입니다: 변경되지 않는 요소를 오프스크린 Canvas로 이동하고 drawImage()를 통해 복사하십시오.
프로파일링 도구: 웹용 Chrome DevTools Performance, Android용 GPU Inspector, iOS용 Instruments. Google Chrome Developers(2025)에 따르면, Canvas 성능 문제의 70%는 과도한 다시 그리기와 레이어 캐싱 부족으로 인해 발생합니다.
| 문제 | 원인 | 해결책 |
|---|---|---|
| 끊기는 애니메이션 | 매 프레임 전체 캔버스 지우기 | 더티 영역과 clearRect 사용 |
| 낮은 FPS | 너무 많은 draw 호출 | 프리미티브를 Path2D로 결합 |
| 흐림 | CSS와 크기 속성 불일치 | width/height와 CSS 크기 동기화 |
| 메모리 누수 | 삭제 없는 오프스크린 Canvas | 사용하지 않는 캔버스 참조 정리 |
모바일 기기의 경우 배터리 절약이 중요합니다. 과도한 렌더링은 GPU에 부하를 주고 작동 시간을 단축시킵니다. 화면 새로 고침 빈도와 동기화하려면 Android에서 willBePresented() 메서드와 iOS에서 displayLink를 사용하십시오.
현대적인 Canvas는 단순한 2D 렌더링을 넘어섰습니다. CanvasContext 기반의 WebGL은 하드웨어 가속으로 3차원 그래픽을 렌더링할 수 있습니다. OffscreenCanvas는 UI 스레드를 차단하지 않고 무거운 렌더링을 Web Workers로 이동합니다.
WebGL은 브라우저에서 OpenGL ES에 대한 액세스를 제공하는 Canvas 컨텍스트입니다. fillRect() 대신 개발자는 GLSL로 셰이더를 작성하고 버퍼에 지오메트리를 로드합니다. Statista(2025)에 따르면, 모바일 브라우저의 92%가 WebGL 2.0을 지원하여 Canvas를 웹 게임 및 3D 시각화의 기반으로 만듭니다.
WebGL을 위한 컨테이너로서의 Canvas는 단일 애플리케이션에서 2D 및 3D 그래픽의 통합을 단순화합니다. 예를 들어, 3D 장면은 WebGL을 통해 렌더링되고 UI 오버레이는 동일한 캔버스의 2D 컨텍스트를 통해 렌더링됩니다. 혼합 렌더링은 Z 순서 관리와 프레임 속도 동기화가 필요합니다.
OffscreenCanvas는 렌더링을 백그라운드 스레드로 이동하기 위한 API입니다. 일반 Canvas와 달리 OffscreenCanvas는 DOM에 바인딩되지 않으며 Web Worker에서 사용할 수 있습니다. 이는 FPS 저하 없이 메인 스레드와 병렬로 복잡한 그래픽 계산을 수행할 수 있게 합니다.
Worker에서 메인 스레드로 완성된 프레임 전송은 transferControlToOffscreen() 및 commit()을 통해 이루어집니다. Chrome Platform Status(2025)에 따르면, OffscreenCanvas는 브라우저의 87%에서 지원되며 그래픽 편집기, 차트 및 애니메이션과 같은 집중적인 렌더링이 필요한 애플리케이션에 권장됩니다.
자주 묻는 질문
Canvas는 래스터 모드로 작동합니다: 렌더링 후 픽셀이 고정됩니다. SVG는 벡터 객체를 저장하고 변경 시 다시 그립니다. Canvas는 빈번한 다시 그리기가 있는 애니메이션에 더 빠르고, SVG는 확장이 있는 대화형 다이어그램에 더 편리합니다.
2D 컨텍스트는 다이어그램, 편집기 및 인터페이스에 적합합니다. WebGL은 3D 그래픽과 셰이더를 사용한 이미지 처리에 필요합니다. 간단한 2D 애니메이션의 경우 2D 컨텍스트가 개발이 더 빠르고 충분히 성능이 뛰어납니다.
네, Canvas는 텍스트 출력을 위한 fillText() 및 strokeText()를 지원합니다. 사용자 정의 글꼴로 작업하려면 Font Loading API를 통해 로드해야 합니다. 모바일 플랫폼에서 Android Canvas는 Typeface를, iOS는 UIFont를 사용합니다.
부분 다시 그리기를 위해 더티 영역을 사용하고, 정적 요소를 오프스크린 Canvas에 캐싱하고, draw 호출 수를 줄이십시오. Android의 경우 매니페스트에서 하드웨어 가속을 활성화하십시오. iOS에서는 OpenGL 대신 Metal을 사용하십시오.
Canvas는 video 요소에서 drawImage()를 통해 비디오를 캡처하고 각 프레임에 필터를 적용할 수 있습니다. 본격적인 편집을 위해 WebGL과 비디오 스트림의 저수준 처리를 위한 WebCodecs가 사용됩니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.