
Node.js์ npm์ด ์ค์น๋ ์ํ์์ ์งํํฉ๋๋ค.
node -v
npm -v
ํฐ๋ฏธ๋์์ ์ ๋ช
๋ น์ผ๋ก ๋ฒ์ ์ ํ์ธํ๊ณ ํ์ํ๋ฉด ์ต์ ๋ฒ์ ์ผ๋ก ์
๋ฐ์ดํธํฉ๋๋ค.
๊ฐ๋ฐ ํด๋๋ฅผ ์ ํฉ๋๋ค.
React๋ Vue๊ฐ ์๋, ์์ Vanilla JavaScript ํ ํ๋ฆฟ์ ์ฌ์ฉํด ํ๋ก์ ํธ๋ฅผ ์์ฑํฉ๋๋ค.
ํฐ๋ฏธ๋์์ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํ์ธ์.
npm create vite@latest my-p5-art -- --template vanilla
npm create: npm์ ์ฌ์ฉํด ์ ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ ๋ช
๋ นvite@latest: vite์ ์ต์ ๋ฒ์ ์ ์ฌ์ฉmy-p5-art: ์์ฑํ ํ๋ก์ ํธ ํด๋ ์ด๋ฆ (ํ์์ ๋ง๊ฒ ๋ณ๊ฒฝ)--: ์ดํ์ ์ต์
๋ค์ vite ๋ช
๋ น์ด์ ์ ๋ฌํ๋ค๋ ์๋ฏธ. npm๊ณผ vite ๋ช
๋ น์ด์ ์ต์
์ ๊ตฌ๋ถํ๋ ๊ตฌ๋ถ์--teamplate vanilla: vite์ ํ
ํ๋ฆฟ ์ต์
. react, react-ts, vue ๋ฑ ์ฌ์ฉ ์์ฑ๋ ํด๋๋ก ์ด๋ํ ํ, ํ์ํ ํจํค์ง๋ฅผ ์ค์นํฉ๋๋ค.
cd my-p5-art
npm install
p5.js๋ฅผ npm์ผ๋ก ์ค์นํฉ๋๋ค. ๋ชจ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ ์ ์๋๋ก ํฉ๋๋ค.
npm install p5
package.json์ ๋ฒ์ ์ด ๋ช
์๋๋ฏ๋ก ํ๋ก์ ํธ๋ฅผ ๊ณต์ ํ๊ฑฐ๋ ๋ฐฐํฌํ ๋ ํญ์ ๋์ผํ ๋ฒ์ ์ p5.js๊ฐ ๋ณด์ฅ๋ฉ๋๋ค CDN ๋งํฌ๋ฅผ ์ฌ์ฉํ ๋ ๋ฐ์ํ๋ ์ธํฐ๋ท ์ฐ๊ฒฐ ๋ฌธ์ ๋ ์๊ธฐ์น ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์
๋ฐ์ดํธ๋ก ์ธํ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
๋ํ CDN ๋ฐฉ์์ ๋ชจ๋ ํจ์๋ฅผ ์ ์ญ(global) ๋ฒ์๋ก ์ค์ผ์ํค๋ ๋ฐ๋ฉด์, npm ํจํค์ง๋ก ์ค์นํ๋ฉด import ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ํ์ํ ๋ชจ๋๋ง ๊ฐ์ ธ์ ๊น๋ํ๊ฒ ์์ฑํ ์ ์์ต๋๋ค. ์ค์น ํ, main.js๋ ๋ณ๋์ sketch ํ์ผ์์ p5๋ฅผ importํด ์ฌ์ฉํ ์ ์์ต๋๋ค.
(์ํฌํธ ์์: import p5 from 'p5'; ๋๋ import 'p5';)
React, Vue, Svelte ๊ฐ์ modern frontend framework๋ Vite, Webpack ๊ฐ์ Bundler๋ฅผ ์ฌ์ฉํ ๋ p5๋ฅผ ์ผ๋ฐ ์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋์ฒ๋ผ ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค. ๋ฒ๋ค๋ฌ๋ฅผ ํตํด ์ฝ๋๋ฅผ ์์ถํ๊ณ ์ต์ ํํ์ฌ ์น ๋ก๋ฉ ์๋๋ฅผ ํฅ์์ํต๋๋ค.
๋ค๋ฅธ ์ธ๋ถ ์๋ฐ์คํฌ๋ฆฝํธ ํจํค์ง๋ฅผ ํจ๊ป ์ค์นํ๊ณ ๊ฒฐํฉํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฌ๊ธฐ๊น์ง ์ค์น๊ฐ ๋๋๋ฉด package.json ํ์ผ์ ๋ด์ฉ์ ํ์ธํฉ๋๋ค.
์๋์ ํญ๋ชฉ์ ํ์์ด๋ฉฐ ์ด ํญ๋ชฉ ์ด์ธ์ ๊ฒ๋ค์ ์ง์๋ ๋ฌด๋ฐฉํฉ๋๋ค. (keywords, author, license ๋ฑ)
{
"name": "p5js-vite-01",
"version": "1.0.0",
"type": "commonjs",
"scripts": {
"dev": "vite --host",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"p5": "^2.3.0"
},
"devDependencies": {
"vite": "^8.1.0"
}
}
"name", "version": package.json ์์ฒด์ ๊ธฐ๋ณธ ๊ท๊ฒฉ์
๋๋ค."type": "commonjs": Node.js ํ๊ฒฝ์์ ๋ชจ๋ ์์คํ
์ ํด์ํ๋ ๊ธฐ์ค์ด ๋๋ฏ๋ก ๋จ๊ฒจ๋๋ ๊ฒ์ด ์ข์ต๋๋ค."scripts": npm run dev ๋ฑ์ ๋ช
๋ น์ด๋ฅผ ์คํํ๊ธฐ ์ํ ํ์ ์ค์ ์
๋๋ค."dependencies"์ p5: p5.js๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ํต์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค."devDependencies"์ vite: ๊ฐ๋ฐ ์๋ฒ ์คํ ๋ฐ ํ๋ก์ ํธ ๋น๋๋ฅผ ๋ด๋นํ๋ ํ์ ๋ฒ๋ค๋ฌ์
๋๋ค.์ด์ ๊ผญ ํ์ํ ํ์ผ๋ค์ ์์ฑํ๊ณ ๊ฐ๊ฐ ์ฝ๋๋ฅผ ๋ฃ์ต๋๋ค.
index.html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>p5.js + Vite</title>
</head>
<body>
<div id="p5-container"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
src/main.js์ธ์คํด์ค ๋ชจ๋๋ก ์์ฑ
import p5 from "p5";
import "./style.css";
const sketch = (p) => {
let t = 0; // ์๊ฐ ๋ณ์
p.setup = () => {
p.createCanvas(400, 400).parent("p5-container");
p.noStroke();
};
p.draw = () => {
p.background(0);
p.fill(255);
// ์ฌ์ธํจ์๋ฅผ ์ด์ฉํด ๋ฐ์ง๋ฆ ๊ณ์ฐ
const baseRadius = 80; // ๊ธฐ๋ณธ ํฌ๊ธฐ
const amplitude = 40; // ํฌ๊ธฐ ๋ณํ ํญ
const speed = 0.05; // ์๋ (๊ฐ์ด ํด์๋ก ๋น ๋ฆ)
const radius = baseRadius + amplitude * p.sin(t);
// ํ๋ฉด ์ค์์ ์ ๊ทธ๋ฆฌ๊ธฐ
p.circle(p.width / 2, p.height / 2, radius * 2);
// ์๊ฐ ์ฆ๊ฐ
t += speed;
};
};
new p5(sketch);
๋ ๋ค๋ฅธ ์ธ์คํด์ค ๋ชจ๋์ ์์ ์ฝ๋
import p5 from 'p5';
import "./style.css";
const sketch = (p) => {
let angle = 0;
p.setup = () => {
p.createCanvas(800, 600); // ์บ๋ฒ์ค ํฌ๊ธฐ
p.background(0); // ์ด๊ธฐ ๋ฐฐ๊ฒฝ
p.smooth(); // ๋ถ๋๋ฌ์ด ๋ ๋๋ง
};
p.draw = () => {
// ๋ฐํฌ๋ช
๋ฐฐ๊ฒฝ์ผ๋ก ํธ๋ ์ผ ํจ๊ณผ
p.fill(0, 20);
p.rect(0, 0, p.width, p.height);
// ์ค์ฌ ์ด๋
p.translate(p.width/2, p.height/2);
// ํ์ ํ๋ ์ฌ๋ฌ ๋ํ ์์
for (let i = 0; i < 8; i++) {
p.push();
p.rotate(angle + i * p.PI / 4);
// ์์ ๋ณํ
let hue = (p.frameCount + i * 30) % 360;
p.fill(hue, 80, 100);
p.noStroke();
// ์ฌ๊ฐํ + ์ ์กฐํฉ
p.rect(-40, -40, 80, 80);
p.circle(60, 0, 30);
p.pop();
}
angle += 0.02; // ํ์ ์๋
};
// ๋ง์ฐ์ค ํด๋ฆญ ์ ์์/ํจํด ๋ฆฌ์
์์
p.mousePressed = () => {
p.background(0);
};
};
new p5(sketch);
style.css* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
background: #000000;
}
#p5-container {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
canvas {
display: block;
}
์ง๊ธ๊น์ง ์งํํ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ํํ์ ํ๋ก์ ํธ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
my-vanilla-p5-app/ โโโ index.html <-- ํ๋ก์ ํธ ๋๋ฌธ ์ญํ โโโ package.json <-- ๊ฐ๋ฐ์ ์ํ ์ธํ โโโ package-lock.json โโโ node_modules/ <-- npm install๋ก ์ค์นํ ๋ชจ๋ โโโ src/ โโโ main.js <-- p5.js ์ฝ๋๊ฐ ๋ค์ด๊ฐ ๋ฉ์ธ javascriptํ์ผ โโโ style.css <-- css ํ์ผ
ํฐ๋ฏธ๋์์ ์๋์ ๋ช ๋ น์ผ๋ก ๊ฐ๋ฐ ์๋ฒ๋ฅผ ์คํํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํฉ๋๋ค.
npm run dev
ํฐ๋ฏธ๋์ Local: http://localhost:5173/ ๊ณผ ๊ฐ์ ์ฃผ์๊ฐ ๋ํ๋ฉ๋๋ค. ์ด๊ฑธ Cmd+ํด๋ฆญ ํด์ ์น ๋ธ๋ผ์ฐ์ ๋ก ์ฝ๋๋ค. ๋ธ๋ผ์ฐ์ ์ ๋ณด์ด๋ ๊ฒ์ ํ์ธํ๋ฉด์ ์ฝ๋๋ฅผ ์์ฑํด๋๊ฐ๋ฉด ๋ฉ๋๋ค.
https://github.com/processing/p5.js/wiki/Global-and-instance-mode
// v1.x: UMD ๋ฐฉ์ (์ ์ญ์ ์๋ ๋ฑ๋ก)
<script src="p5.js"></script>
// setup(), draw() ํจ์๊ฐ ์๋์ผ๋ก ์ ์ญ์์ ์ธ์๋จ
// v2.x: ES Modules ๋ฐฉ์
import p5 from 'p5';
// setup(), draw()์ด ์ ์ญ์ ์๋ ๋ฑ๋ก๋์ง ์์
Vite/Webpack ๋ฑ์ ๋ชจ๋ ์์คํ ์์๋ ๊ฐ ํ์ผ์ด ๋ ๋ฆฝ๋ ์ค์ฝํ๋ฅผ ๊ฐ์ง โ ์ ์ญ ํจ์๊ฐ ์๋์ผ๋ก ๋ฑ๋ก๋์ง ์์
v1.x: ์ฌ์ด ์์์ ์ํ ๊ธ๋ก๋ฒ ํด๋ฆฌ์v2.x: ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ชจ๋ ์์คํ
์ค์p. ์ ๋์ฌ๊ฐ ํ์ํ๊ฐ?// ๋ชจ๋ ํ๊ฒฝ์์๋ ์ด๊ฒ ์๋๋ ์ด์ :
function setup() { // โ ์ด ํจ์๋ p5 ์ธ์คํด์ค์ ์ฐ๊ฒฐ๋์ง ์์
createCanvas(400, 400); // โ createCanvas๊ฐ ์ด๋ค p5 ์ธ์คํด์ค์ธ์ง ๋ชจ๋ฆ
}
// ๋์ ์ด๋ ๊ฒ ํด์ผํจ:
new p5((p) => { // โ
p5 ์ธ์คํด์ค ์์ฑ
p.setup = () => { // โ
์ด setup์ p ์ธ์คํด์ค์ ์ฐ๊ฒฐ๋จ
p.createCanvas(400, 400); // โ
p ์ธ์คํด์ค์ createCanvas ์ฌ์ฉ
};
});