TECH 으로 돌아가기
TECH HACKER NEWS 2026.11.05 03:42 9분 읽기 27 READS

mrdoob의 Jelly Sheet로 보는 웹 소프트바디 시뮬레이션 입문

three.js를 만든 리카르도 카벨로(mrdoob)가 Jelly Sheet라는 작은 웹 데모를 공개했어요. 주소를 보면 Codevember 2026 시리즈의 첫 번째 작품이에요. 이름만 들어도 손으로 꾹 누르면 출렁일 것 같은 느낌이 오죠?

먼저 솔직하게 말씀드릴게요. 이 글은 데모의 제목과 주소까지만 확인하고 쓴 글이에요. 코드를 직접 뜯어본 건 아니라서 '이 작품은 이렇게 구현됐다'고 단정할 수는 없어요. 그래서 데모 해설 대신, 브라우저에서 젤리 같은 판을 만들려면 어떤 기술이 필요한지를 차근차근 풀어볼게요. 실제 동작은 링크에서 직접 만져보시는 게 제일 정확해요.

Codevember가 뭐냐면

Codevember는 11월 한 달 동안 매일 작은 코드 작품을 만들어 올리는 크리에이티브 코딩 챌린지예요. 그림 그리는 사람들의 Inktober를 코드 버전으로 옮긴 거라고 보면 쉬워요. 완성도 높은 서비스를 만드는 게 아니라, 아이디어 하나를 짧은 시간에 눈에 보이게 만드는 연습이에요. 그래서 이런 작품은 코드도 짧고 핵심이 또렷한 경우가 많아서 공부 재료로 아주 좋거든요.

말랑함의 정체는 점과 스프링이에요

컴퓨터 안에 진짜 젤리는 없어요. 말랑해 보이는 물체는 대부분 점 여러 개를 스프링으로 이어놓은 그물이에요. 이걸 질량-스프링 모델이라고 불러요. 바둑판처럼 점을 깔고 이웃한 점끼리 고무줄로 묶었다고 상상해 보세요. 한 점을 잡아당기면 고무줄이 늘어나고, 늘어난 고무줄이 옆 점을 끌어당기고, 그 옆 점이 또 다음 점을 끌어당겨요. 이렇게 힘이 번져나가는 모습이 우리 눈에는 '출렁임'으로 보이는 거예요.

판 모양이라면 보통 스프링을 세 종류로 나눠요. 바로 옆 점을 잇는 구조 스프링은 판이 찢어지지 않게 잡아주고, 대각선을 잇는 전단 스프링은 판이 마름모로 찌그러지는 걸 막아요. 한 칸 건너뛰어 잇는 굽힘 스프링은 판이 너무 쉽게 접히지 않게 해주고요. 이 셋의 세기를 조절하면 천처럼 흐물거리게도, 젤리처럼 탱글하게도 만들 수 있어요.

코드로 보면 생각보다 짧아요

입문용으로 가장 많이 쓰는 방법이 베를레 적분(Verlet integration)이에요. 이게 뭐냐면, 속도를 따로 저장하지 않고 '지금 위치와 직전 위치의 차이'를 속도로 치는 방식이에요. 여기에 스프링 길이를 원래대로 되돌리는 보정을 몇 번 반복하면 끝이에요.

// 1단계: 관성과 중력으로 점을 움직여요
for (const p of points) {
const vx = (p.x - p.px) * 0.99;
const vy = (p.y - p.py) * 0.99;
p.px = p.x;
p.py = p.y;
p.x += vx;
p.y += vy + gravity dt dt;
}

// 2단계: 스프링 길이를 원래대로 되돌려요
for (let i = 0; i < 8; i++) {
for (const s of springs) {
const dx = s.b.x - s.a.x;
const dy = s.b.y - s.a.y;
const dist = Math.hypot(dx, dy);
const diff = (dist - s.length) / dist 0.5 s.stiffness;
s.a.x += dx * diff;
s.a.y += dy * diff;
s.b.x -= dx * diff;
s.b.y -= dy * diff;
}
}

코드의 0.5는 두 점이 절반씩 움직인다는 뜻이고, 반복 횟수를 늘릴수록 판이 단단해져요. 여기에 포인터로 잡은 점을 마우스 위치에 고정하는 코드만 더하면 손으로 당겨보는 데모가 돼요.

왜 자꾸 터질까요

직접 만들어보면 스프링을 세게 했을 때 점들이 화면 밖으로 튀어나가는 일이 생겨요. 힘을 계산해서 속도에 더하는 단순한 방식은 스프링이 강하거나 시간 간격이 길면 오차가 눈덩이처럼 불어나거든요. 그래서 실시간 시뮬레이션에서는 힘 대신 위치를 직접 고치는 PBD(Position Based Dynamics)와 이를 개선한 XPBD를 많이 써요. 위 코드의 2단계가 바로 이 발상이에요. 물리적으로 아주 정확하진 않아도 잘 터지지 않아서 게임과 인터랙션에 잘 맞아요. 한 프레임을 작은 시간 단위로 쪼개 여러 번 계산하는 서브스텝을 같이 쓰면 더 안정적이고요.

점이 많아지면 GPU로

점 몇천 개까지는 자바스크립트로도 버티지만, 판을 곱게 만들려고 점을 늘리면 CPU가 먼저 지쳐요. 점 하나하나의 계산은 서로 비슷해서 GPU에 나눠 맡기기 좋은 일이에요. 예전 WebGL에서는 위치를 텍스처에 담고 두 장을 번갈아 쓰는 식으로 우회했는데, WebGPU는 컴퓨트 셰이더를 쓸 수 있어서 훨씬 자연스러워요. three.js도 WebGPURenderer와 셰이더 언어 TSL을 키워가고 있어서 이쪽을 공부해두면 쓸모가 많아요. 다만 이웃한 점들이 동시에 같은 점을 고치려고 부딪힐 수 있어서 계산 순서를 나누는 고민이 따라와요. 표면을 예쁘게 보이려면 변형된 모양에 맞춰 법선(빛이 어느 방향으로 반사될지 정하는 값)도 다시 계산해야 하고요.

다른 선택지와 비교하면

직접 짜지 않고 라이브러리를 쓸 수도 있어요. Rapier나 cannon-es는 딱딱한 물체 위주라 이런 말랑한 표현에는 맞지 않아요. Bullet을 웹으로 옮긴 Ammo.js는 소프트바디를 지원하지만 덩치가 큰 편이에요. 2D라면 Matter.js에 소프트바디를 만드는 도우미가 있고요. 판 하나를 출렁이게 하는 정도라면 위 코드처럼 직접 짜는 쪽이 오히려 가볍고 손맛도 조절하기 쉬워요. 반대로 여러 물체가 부딪히는 복잡한 장면이라면 라이브러리가 안전해요.

한국 개발자에게는요

실무에서 쓸 곳도 꽤 있어요. 랜딩 페이지 첫 화면의 인터랙션이나 포트폴리오, 브랜드 캠페인 페이지가 대표적이에요. 다만 몇 가지는 챙겨주세요. 저사양 모바일에서는 점 개수를 줄이고, 화면 밖으로 나가면 계산을 멈추고, 움직임을 줄여달라는 사용자 설정(prefers-reduced-motion)도 존중해야 해요.

프론트엔드 개발자가 그래픽을 처음 공부한다면 이 주제를 추천해요. 벡터, 시간 간격, 수치 안정성 같은 개념을 화면으로 바로 확인할 수 있거든요. 주말에 캔버스 2D로 점 20×20개짜리 판부터 만들어 보세요.

마무리

한 줄로 정리하면, 말랑함은 특별한 마법이 아니라 점과 스프링을 반복 계산한 결과예요. 여러분이라면 이런 말랑한 인터랙션을 실제 서비스 어디에 넣어보고 싶으세요? 아니면 예쁘기만 하고 쓸모는 없다고 보시나요?


🔗 출처: Hacker News

SOURCE · HACKER NEWS
원문 전체 보기 → https://mrdoob.github.io/codevember-2026/01/
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기 →
처리 중...