최근 챗지피티(ChatGPT)의 캔버스(Canvas) 기능이 많은 주목을 받고 있습니다. 이 기능은 2024년 10월 초에 베타 버전으로 처음 출시되어 현재는 무료 사용자도 사용할 수 있게 되었는데요, 글쓰기 작업뿐만 아니라 코딩 프로젝트에도 효율적으로 활용할 수 있어 많은 사용자들에게 인기를 끌고 있습니다.
캔버스는 문서나 코드 등 다양한 작업을 진행할 수 있는 공간으로, 작업 내용을 블록 단위로 구성하여 수정하거나 요청하기 쉽게 만들어주는 도구입니다. 특히 복잡한 요청도 프로젝트처럼 관리할 수 있도록 도와줍니다.
문서나 코드를 업로드하면 캔버스 내에서 내용을 분석하고 요청에 맞게 답변하거나 수정 작업을 이어갈 수 있습니다.
블로그 포스트를 작성할 때 캔버스를 활용하면 전체 흐름과 구조를 명확히 하며, 글의 완성도를 높일 수 있습니다. 하이라이트, 댓글, 편집 제안 등을 통해 쉽게 수정이 가능합니다.
캔버스 하단에 (편집 제안) 이모티콘에 커서를 갖다대면 다음과같은 부가 작업들이 나옵니다.
위와같이 어떤 부분에 어떤 개념을 더 추가하면 될지 알아서 하이라이트 표시해줍니다.
코딩 작업에도 매우 유용한데요, HTML, JavaScript, Python 등 다양한 언어의 코드 블록을 분석하고 수정 제안을 받을 수 있습니다. 테트리스 게임을 웹에서 실행할 수 있는 간단한 코드작업을 요청해보겠습니다.
캔버스 하단에 [코드 검토] 이모티콘에 커서를 갖다대면 아래와같은 부가 요소들을 추가해볼 수 있습니다.
캔버스는 단순한 편집 도구를 넘어서, 복잡한 글쓰기나 코딩 작업을 체계적이고 효율적으로 처리할 수 있게 도와주는 기능입니다. 특히 드래그&드롭과 버튼 클릭만으로 원하는 부분을 수정하거나 질문할 수 있어 초보자에게도 매우 친절한 환경을 제공합니다.
앞으로 캔버스 기능이 더욱 강화되면 팀 협업이나 실시간 코드 실행 등 다양한 기능으로 확장될 가능성이 크므로, 지금부터 익혀두면 큰 도움이 될 것입니다.
위에서 받은 캔버스 안의 코드파일입니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tetris Game</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: #111;
margin: 0;
}
canvas {
border: 2px solid #fff;
background: #000;
}
</style>
</head>
<body>
<canvas id="tetris" width="240" height="400"></canvas>
<script>
const canvas = document.getElementById('tetris');
const context = canvas.getContext('2d');
context.scale(20, 20);
function arenaSweep() {
outer: for (let y = arena.length - 1; y >= 0; --y) {
if (arena[y].every(cell => cell !== 0)) {
const row = arena.splice(y, 1)[0].fill(0);
arena.unshift(row);
++y;
}
}
}
function collide(arena, player) {
const m = player.matrix;
const o = player.pos;
for (let y = 0; y < m.length; ++y) {
for (let x = 0; x < m[y].length; ++x) {
if (m[y][x] !== 0 &&
(arena[y + o.y] && arena[y + o.y][x + o.x]) !== 0) {
return true;
}
}
}
return false;
}
function createMatrix(w, h) {
const matrix = [];
while (h--) {
matrix.push(new Array(w).fill(0));
}
return matrix;
}
function createPiece(type) {
switch (type) {
case 'T': return [[0, 0, 0], [1, 1, 1], [0, 1, 0]];
case 'O': return [[2, 2], [2, 2]];
case 'L': return [[0, 3, 0], [0, 3, 0], [0, 3, 3]];
case 'J': return [[0, 4, 0], [0, 4, 0], [4, 4, 0]];
case 'I': return [[0, 5, 0, 0], [0, 5, 0, 0], [0, 5, 0, 0], [0, 5, 0, 0]];
case 'S': return [[0, 6, 6], [6, 6, 0], [0, 0, 0]];
case 'Z': return [[7, 7, 0], [0, 7, 7], [0, 0, 0]];
}
}
function drawMatrix(matrix, offset) {
matrix.forEach((row, y) => {
row.forEach((value, x) => {
if (value !== 0) {
context.fillStyle = colors[value];
context.fillRect(x + offset.x, y + offset.y, 1, 1);
}
});
});
}
function draw() {
context.fillStyle = '#000';
context.fillRect(0, 0, canvas.width, canvas.height);
drawMatrix(arena, { x: 0, y: 0 });
drawMatrix(player.matrix, player.pos);
}
function merge(arena, player) {
player.matrix.forEach((row, y) => {
row.forEach((value, x) => {
if (value !== 0) {
if (arena[y + player.pos.y]) {
arena[y + player.pos.y][x + player.pos.x] = value;
}
}
});
});
}
function rotate(matrix, dir) {
for (let y = 0; y < matrix.length; ++y) {
for (let x = 0; x < y; ++x) {
[matrix[x][y], matrix[y][x]] = [matrix[y][x], matrix[x][y]];
}
}
if (dir > 0) {
matrix.forEach(row => row.reverse());
} else {
matrix.reverse();
}
}
function playerDrop() {
player.pos.y++;
if (collide(arena, player)) {
player.pos.y--;
merge(arena, player);
playerReset();
arenaSweep();
}
dropCounter = 0;
}
function playerMove(dir) {
player.pos.x += dir;
if (collide(arena, player)) {
player.pos.x -= dir;
}
}
function playerReset() {
const pieces = 'TJLOSZI';
player.matrix = createPiece(pieces[Math.floor(pieces.length * Math.random())]);
player.pos.y = 0;
player.pos.x = (arena[0].length / 2 | 0) - (player.matrix[0].length / 2 | 0);
if (collide(arena, player)) {
arena.forEach(row => row.fill(0));
}
}
function playerRotate(dir) {
const pos = player.pos.x;
let offset = 1;
rotate(player.matrix, dir);
while (collide(arena, player)) {
player.pos.x += offset;
offset = -(offset + (offset > 0 ? 1 : -1));
if (offset > player.matrix[0].length) {
rotate(player.matrix, -dir);
player.pos.x = pos;
return;
}
}
}
let dropCounter = 0;
let dropInterval = 1000;
let lastTime = 0;
function update(time = 0) {
const deltaTime = time - lastTime;
lastTime = time;
dropCounter += deltaTime;
if (dropCounter > dropInterval) {
playerDrop();
}
draw();
requestAnimationFrame(update);
}
document.addEventListener('keydown', event => {
switch (event.key) {
case 'ArrowLeft': playerMove(-1); break;
case 'ArrowRight': playerMove(1); break;
case 'ArrowDown': playerDrop(); break;
case 'q': playerRotate(-1); break;
case 'w': playerRotate(1); break;
}
});
const colors = [
null,
'#FF0D72',
'#0DC2FF',
'#0DFF72',
'#F538FF',
'#FF8E0D',
'#FFE138',
'#3877FF',
];
const arena = createMatrix(12, 20);
const player = {
pos: { x: 0, y: 0 },
matrix: null,
};
playerReset();
update();
</script>
</body>
</html>