여러분이 사용하고 계신 브라우저는 HTML5를 지원하지 않기 때문에 몇몇 요소가 제대로 보이도록 JScript를 사용하고 있습니다. 하지만 여러분의 브라우저 설정에서 스크립트 기능이 꺼져있으므로, 현재 페이지를 제대로 확인하시려면 스크립트 기능을 켜주셔야 합니다. Canvas 시계 - 바늘

Canvas 시계 – 바늘

2주전 작성

HTML Canvas 시계 바늘

HTML Canvas를 사용하여 시계 바늘을 그리는 방법을 알아본다. 이 튜토리얼에서는 시침, 분침, 초침을 그리고 실시간으로 움직이게 하는 방법을 설명한다.

시계 바늘 기본 원리

시계 바늘을 그리기 위해서는 다음과 같은 원리를 이해해야 한다.

  • 시침은 12시간을 기준으로 360도 회전한다 (1시간 = 30도)
  • 분침은 60분을 기준으로 360도 회전한다 (1분 = 6도)
  • 초침은 60초를 기준으로 360도 회전한다 (1초 = 6도)
  • 시침은 분과 초에 따라 연속적으로 움직인다

기본 시계 바늘 그리기

먼저 고정된 시간의 시계 바늘을 그려보자.

<canvas id="canvas1" width="400" height="400" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90;
drawClock();
function drawClock() {
drawFace(ctx, radius);
drawNumbers(ctx, radius);
drawTime(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius * 0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius * 0.15 + "px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
for (num = 1; num < 13; num++) { ang = num * Math.PI / 6; ctx.rotate(ang); ctx.translate(0, -radius * 0.85); ctx.rotate(-ang); ctx.fillText(num.toString(), 0, 0); ctx.rotate(ang); ctx.translate(0, radius * 0.85); ctx.rotate(-ang); } } function drawTime(ctx, radius) { var hour = 10; var minute = 10; var second = 30; hour = hour % 12; hour = (hour * Math.PI / 6) + (minute * Math.PI / (6 * 60)) + (second * Math.PI / (360 * 60)); drawHand(ctx, hour, radius * 0.5, radius * 0.07); minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60)); drawHand(ctx, minute, radius * 0.8, radius * 0.07); second = (second * Math.PI / 30); drawHand(ctx, second, radius * 0.9, radius * 0.02); } function drawHand(ctx, pos, length, width) { ctx.beginPath(); ctx.lineWidth = width; ctx.lineCap = "round"; ctx.moveTo(0, 0); ctx.rotate(pos); ctx.lineTo(0, -length); ctx.stroke(); ctx.rotate(-pos); } </script>[/code]

이 예제에서는 10시 10분 30초를 나타내는 고정된 시계 바늘을 그린다. drawTime() 함수에서 각 바늘의 각도를 계산하고, drawHand() 함수에서 실제 바늘을 그린다.

실시간 시계 바늘

현재 시간에 따라 움직이는 시계 바늘을 만들어보자.

<canvas id="canvas2" width="400" height="400" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var canvas = document.getElementById("canvas2");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90;
setInterval(drawClock, 1000);
function drawClock() {
ctx.clearRect(-radius, -radius, radius * 2, radius * 2);
drawFace(ctx, radius);
drawNumbers(ctx, radius);
drawTime(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius * 0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius * 0.15 + "px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
for (num = 1; num < 13; num++) { ang = num * Math.PI / 6; ctx.rotate(ang); ctx.translate(0, -radius * 0.85); ctx.rotate(-ang); ctx.fillText(num.toString(), 0, 0); ctx.rotate(ang); ctx.translate(0, radius * 0.85); ctx.rotate(-ang); } } function drawTime(ctx, radius) { var now = new Date(); var hour = now.getHours(); var minute = now.getMinutes(); var second = now.getSeconds(); hour = hour % 12; hour = (hour * Math.PI / 6) + (minute * Math.PI / (6 * 60)) + (second * Math.PI / (360 * 60)); drawHand(ctx, hour, radius * 0.5, radius * 0.07); minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60)); drawHand(ctx, minute, radius * 0.8, radius * 0.07); second = (second * Math.PI / 30); drawHand(ctx, second, radius * 0.9, radius * 0.02); } function drawHand(ctx, pos, length, width) { ctx.beginPath(); ctx.lineWidth = width; ctx.lineCap = "round"; ctx.moveTo(0, 0); ctx.rotate(pos); ctx.lineTo(0, -length); ctx.stroke(); ctx.rotate(-pos); } </script>[/code]

이 예제에서는 new Date()를 사용하여 현재 시간을 가져오고, setInterval()을 사용하여 1초마다 시계를 업데이트한다.

다양한 색상의 시계 바늘

각 바늘에 다른 색상을 적용해보자.

<canvas id="canvas3" width="400" height="400" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var canvas = document.getElementById("canvas3");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90;
setInterval(drawClock, 1000);
function drawClock() {
ctx.clearRect(-radius, -radius, radius * 2, radius * 2);
drawFace(ctx, radius);
drawNumbers(ctx, radius);
drawTime(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius * 0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius * 0.15 + "px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
for (num = 1; num < 13; num++) { ang = num * Math.PI / 6; ctx.rotate(ang); ctx.translate(0, -radius * 0.85); ctx.rotate(-ang); ctx.fillText(num.toString(), 0, 0); ctx.rotate(ang); ctx.translate(0, radius * 0.85); ctx.rotate(-ang); } } function drawTime(ctx, radius) { var now = new Date(); var hour = now.getHours(); var minute = now.getMinutes(); var second = now.getSeconds(); hour = hour % 12; hour = (hour * Math.PI / 6) + (minute * Math.PI / (6 * 60)) + (second * Math.PI / (360 * 60)); drawHand(ctx, hour, radius * 0.5, radius * 0.07, "#2c3e50"); minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60)); drawHand(ctx, minute, radius * 0.8, radius * 0.07, "#34495e"); second = (second * Math.PI / 30); drawHand(ctx, second, radius * 0.9, radius * 0.02, "#e74c3c"); } function drawHand(ctx, pos, length, width, color) { ctx.beginPath(); ctx.lineWidth = width; ctx.lineCap = "round"; ctx.strokeStyle = color; ctx.moveTo(0, 0); ctx.rotate(pos); ctx.lineTo(0, -length); ctx.stroke(); ctx.rotate(-pos); } </script>[/code]

이 예제에서는 시침을 진한 파란색, 분침을 회색, 초침을 빨간색으로 표시하여 각 바늘을 구분하기 쉽게 만들었다.

고급 스타일 시계 바늘

더 정교한 디자인의 시계 바늘을 만들어보자.

<canvas id="canvas4" width="400" height="400" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var canvas = document.getElementById("canvas4");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90;
setInterval(drawClock, 1000);
function drawClock() {
ctx.clearRect(-radius, -radius, radius * 2, radius * 2);
drawFace(ctx, radius);
drawNumbers(ctx, radius);
drawTime(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius * 0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius * 0.15 + "px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
for (num = 1; num < 13; num++) { ang = num * Math.PI / 6; ctx.rotate(ang); ctx.translate(0, -radius * 0.85); ctx.rotate(-ang); ctx.fillText(num.toString(), 0, 0); ctx.rotate(ang); ctx.translate(0, radius * 0.85); ctx.rotate(-ang); } } function drawTime(ctx, radius) { var now = new Date(); var hour = now.getHours(); var minute = now.getMinutes(); var second = now.getSeconds(); hour = hour % 12; hour = (hour * Math.PI / 6) + (minute * Math.PI / (6 * 60)) + (second * Math.PI / (360 * 60)); drawHourHand(ctx, hour, radius); minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60)); drawMinuteHand(ctx, minute, radius); second = (second * Math.PI / 30); drawSecondHand(ctx, second, radius); } function drawHourHand(ctx, pos, radius) { ctx.save(); ctx.rotate(pos); ctx.beginPath(); ctx.lineWidth = radius * 0.07; ctx.lineCap = "round"; ctx.strokeStyle = "#2c3e50"; ctx.moveTo(0, radius * 0.1); ctx.lineTo(0, -radius * 0.5); ctx.stroke(); ctx.restore(); } function drawMinuteHand(ctx, pos, radius) { ctx.save(); ctx.rotate(pos); ctx.beginPath(); ctx.lineWidth = radius * 0.05; ctx.lineCap = "round"; ctx.strokeStyle = "#34495e"; ctx.moveTo(0, radius * 0.1); ctx.lineTo(0, -radius * 0.8); ctx.stroke(); ctx.restore(); } function drawSecondHand(ctx, pos, radius) { ctx.save(); ctx.rotate(pos); ctx.beginPath(); ctx.lineWidth = radius * 0.02; ctx.lineCap = "round"; ctx.strokeStyle = "#e74c3c"; ctx.moveTo(0, radius * 0.15); ctx.lineTo(0, -radius * 0.9); ctx.stroke(); ctx.beginPath(); ctx.arc(0, -radius * 0.75, radius * 0.05, 0, 2 * Math.PI); ctx.fillStyle = "#e74c3c"; ctx.fill(); ctx.restore(); } </script>[/code]

이 예제에서는 각 바늘을 개별 함수로 분리하고, 초침에 작은 원을 추가하여 더 현실적인 시계 바늘을 만들었다. save()와 restore() 메서드를 사용하여 변환 상태를 관리한다.

그림자 효과가 있는 시계 바늘

시계 바늘에 그림자 효과를 추가해보자.

<canvas id="canvas5" width="400" height="400" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var canvas = document.getElementById("canvas5");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90;
setInterval(drawClock, 1000);
function drawClock() {
ctx.clearRect(-radius, -radius, radius * 2, radius * 2);
drawFace(ctx, radius);
drawNumbers(ctx, radius);
drawTime(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius * 0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius * 0.15 + "px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
for (num = 1; num < 13; num++) { ang = num * Math.PI / 6; ctx.rotate(ang); ctx.translate(0, -radius * 0.85); ctx.rotate(-ang); ctx.fillText(num.toString(), 0, 0); ctx.rotate(ang); ctx.translate(0, radius * 0.85); ctx.rotate(-ang); } } function drawTime(ctx, radius) { var now = new Date(); var hour = now.getHours(); var minute = now.getMinutes(); var second = now.getSeconds(); hour = hour % 12; hour = (hour * Math.PI / 6) + (minute * Math.PI / (6 * 60)) + (second * Math.PI / (360 * 60)); drawHand(ctx, hour, radius * 0.5, radius * 0.07, "#2c3e50"); minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60)); drawHand(ctx, minute, radius * 0.8, radius * 0.07, "#34495e"); second = (second * Math.PI / 30); drawHand(ctx, second, radius * 0.9, radius * 0.02, "#e74c3c"); } function drawHand(ctx, pos, length, width, color) { ctx.save(); ctx.shadowColor = "rgba(0,0,0,0.3)"; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.shadowBlur = 3; ctx.beginPath(); ctx.lineWidth = width; ctx.lineCap = "round"; ctx.strokeStyle = color; ctx.moveTo(0, 0); ctx.rotate(pos); ctx.lineTo(0, -length); ctx.stroke(); ctx.restore(); } </script>[/code]

이 예제에서는 그림자 효과를 추가하여 시계 바늘이 페이스에서 떠있는 것처럼 보이게 만들었다.

부드러운 초침 애니메이션

초침이 부드럽게 움직이는 애니메이션을 만들어보자.

<canvas id="canvas6" width="400" height="400" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var canvas = document.getElementById("canvas6");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90;
setInterval(drawClock, 50);
function drawClock() {
ctx.clearRect(-radius, -radius, radius * 2, radius * 2);
drawFace(ctx, radius);
drawNumbers(ctx, radius);
drawTime(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius * 0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius * 0.15 + "px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
for (num = 1; num < 13; num++) { ang = num * Math.PI / 6; ctx.rotate(ang); ctx.translate(0, -radius * 0.85); ctx.rotate(-ang); ctx.fillText(num.toString(), 0, 0); ctx.rotate(ang); ctx.translate(0, radius * 0.85); ctx.rotate(-ang); } } function drawTime(ctx, radius) { var now = new Date(); var hour = now.getHours(); var minute = now.getMinutes(); var second = now.getSeconds(); var millisecond = now.getMilliseconds(); hour = hour % 12; hour = (hour * Math.PI / 6) + (minute * Math.PI / (6 * 60)) + (second * Math.PI / (360 * 60)); drawHand(ctx, hour, radius * 0.5, radius * 0.07, "#2c3e50"); minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60)); drawHand(ctx, minute, radius * 0.8, radius * 0.07, "#34495e"); second = (second * Math.PI / 30) + (millisecond * Math.PI / (30 * 1000)); drawHand(ctx, second, radius * 0.9, radius * 0.02, "#e74c3c"); } function drawHand(ctx, pos, length, width, color) { ctx.beginPath(); ctx.lineWidth = width; ctx.lineCap = "round"; ctx.strokeStyle = color; ctx.moveTo(0, 0); ctx.rotate(pos); ctx.lineTo(0, -length); ctx.stroke(); ctx.rotate(-pos); } </script>[/code]

이 예제에서는 밀리초를 포함하여 초침이 부드럽게 움직이도록 만들었다. setInterval()의 간격을 50밀리초로 줄여서 더 부드러운 애니메이션을 구현했다.

💡 시계 바늘 제작 팁:
• 각도 계산 시 분과 초의 영향을 고려하여 연속적인 움직임을 만들어야 한다
• save()와 restore() 메서드를 사용하여 변환 상태를 관리하면 코드가 더 깔끔해진다
• 초침의 부드러운 움직임을 위해 밀리초를 포함한 계산을 사용할 수 있다
• 성능을 고려하여 적절한 업데이트 주기를 선택해야 한다

디지털 시간 표시와 함께

아날로그 시계 바늘과 디지털 시간을 함께 표시해보자.

<canvas id="canvas7" width="400" height="400" style="border:1px solid #d3d3d3;">
브라우저가 HTML5 Canvas를 지원하지 않습니다.
</canvas>
<script>
var canvas = document.getElementById("canvas7");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90;
setInterval(drawClock, 1000);
function drawClock() {
ctx.clearRect(-radius, -radius, radius * 2, radius * 2);
drawFace(ctx, radius);
drawNumbers(ctx, radius);
drawTime(ctx, radius);
drawDigitalTime(ctx, radius);
}
function drawFace(ctx, radius) {
var grad;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.fillStyle = 'white';
ctx.fill();
grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius * 0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius * 0.15 + "px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
for (num = 1; num < 13; num++) { ang = num * Math.PI / 6; ctx.rotate(ang); ctx.translate(0, -radius * 0.85); ctx.rotate(-ang); ctx.fillText(num.toString(), 0, 0); ctx.rotate(ang); ctx.translate(0, radius * 0.85); ctx.rotate(-ang); } } function drawTime(ctx, radius) { var now = new Date(); var hour = now.getHours(); var minute = now.getMinutes(); var second = now.getSeconds(); hour = hour % 12; hour = (hour * Math.PI / 6) + (minute * Math.PI / (6 * 60)) + (second * Math.PI / (360 * 60)); drawHand(ctx, hour, radius * 0.5, radius * 0.07, "#2c3e50"); minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60)); drawHand(ctx, minute, radius * 0.8, radius * 0.07, "#34495e"); second = (second * Math.PI / 30); drawHand(ctx, second, radius * 0.9, radius * 0.02, "#e74c3c"); } function drawHand(ctx, pos, length, width, color) { ctx.beginPath(); ctx.lineWidth = width; ctx.lineCap = "round"; ctx.strokeStyle = color; ctx.moveTo(0, 0); ctx.rotate(pos); ctx.lineTo(0, -length); ctx.stroke(); ctx.rotate(-pos); } function drawDigitalTime(ctx, radius) { var now = new Date(); var hour = now.getHours(); var minute = now.getMinutes(); var second = now.getSeconds(); var timeString = (hour < 10 ? "0" : "") + hour + ":" + (minute < 10 ? "0" : "") + minute + ":" + (second < 10 ? "0" : "") + second; ctx.font = radius * 0.1 + "px Arial"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillStyle = "#2c3e50"; ctx.fillRect(-radius * 0.35, radius * 0.55, radius * 0.7, radius * 0.15); ctx.fillStyle = "white"; ctx.fillText(timeString, 0, radius * 0.625); } </script>[/code]

이 마지막 예제에서는 아날로그 시계 바늘과 함께 디지털 시간 표시를 추가하여 두 가지 형태의 시간 표시를 동시에 제공한다.

Canvas를 사용한 시계 바늘 제작은 각도 계산, 삼각함수, 애니메이션의 실용적인 활용 예시이다. 이러한 기법들은 게이지, 다이얼, 회전 인터페이스 등 다양한 웹 애플리케이션에서 응용할 수 있다.

참고
Mingg`s Diary
밍구
공부 목적 블로그