3주차 · 2026-01-26 ~ 2026-02-01
첫 프로토타입, 첫 번째 벽
첫 번째 작동하는 프로토타입을 Three.js 웹 앱으로 만들었다. 돌아가긴 했지만, 세 가지 축이 같은 주에 서로 다른 세 개의 벽에 부딪혔고, 세 벽 모두 같은 곳에서 왔다.
지난 주 나는 세 가지 축을 정의했고, 각각이 적어도 하나의 현실적인 구현 경로를 가진다는 것을 확인했다. 그 정도면 Week 2를 계획으로 닫기에 충분했다. 이번 주에는 그 계획이 현실을 마주해야 했다. 오디오 시각화, 가상 여행, 체화적 상호작용에 대해 말하는 것은 하나의 일이다. 세 가지를 같은 애플리케이션 안에서 동시에 돌리는 것은 또 다른 일이다.
나는 이미 알고 있는 스택으로 시작했다. 비주얼은 Three.js를 통한 WebGL, 애플리케이션 로직은 순수 JavaScript, 손 추적은 MediaPipe의 웹 버전이다. 이 조합에는 두 가지 이점이 있었다. 각 부분에 대한 경험이 어느 정도 있었고, 모든 것이 브라우저 안에서 돌기 때문에 초기 테스트 단계에서 배포나 설치 마찰이 없다. 이번 주에 필요한 것은 빠른 반복이었지, 최종 도구가 아니었다.
웹 프로토타입 만들기
첫 버전은 예상보다 빠르게 맞춰졌다. Three.js는 많은 장면 설정을 기본으로 처리해 준다. 카메라, 렌더러, 파티클 시스템이다. 며칠 만에 배경에서 재생되는 오디오 파일에 파티클이 반응하고, 웹캠이 MediaPipe로 내 손을 추적하는 브라우저 창 하나를 갖게 되었다. 세 가지 축이 처음으로 하나의 애플리케이션 안에서 기술적으로 함께 돌고 있었다.
표면적으로 보면 이건 성공이었다. 방문자가 페이지를 열고, 지역을 고르고, 3D 장면을 보고, 사운드스케이프를 듣고, 웹캠을 향해 손을 흔들어 화면 위에서 응답을 볼 수 있었다. 모든 축이 살아 있었다. 만약 여기서 멈추고 “컨셉이 작동한다”라고 보고서를 썼다면 설득력 있어 보였을 것이다.
문제는 사용하는 사람이 나였다는 점, 그래서 실제로 무슨 일이 벌어지고 있는지 알고 있었다는 것이다.
세 개의 벽
프로토타입을 더 밀어붙이려 했을 때, 세 가지 별개의 문제가 드러났다. 애플리케이션의 같은 영역에서 온 것은 아니었지만 며칠 간격으로 서로 나타났고, 각각이 같은 근본 원인을 가리키고 있었다. 하나씩 설명해 본다.
-
손 추적 지연시간
MediaPipe의 웹 버전은 실제 손의 움직임과 화면 위 반응 사이에 눈에 보이는 지연이 있다. 고장난 것은 아니다. 작동한다. 하지만 내 손이 앞으로 뻗는 것과 파티클이 반응하는 사이에 대략 0.5초의 간격이 있다. 많은 애플리케이션에서는 이 정도가 용인될 것이다. 이 프로젝트에서는 아니다.
이유는 체화적 상호작용이 세 가지 축 중 하나이기 때문이다. 세 번째 축의 핵심은 방문자가 자신의 몸이 공간 안에 있다고 느끼는 것이지, 밖에서 리모컨을 조작한다고 느끼는 것이 아니다. 손이 움직이고 화면이 0.5초 늦게 따라잡을 때, 비주얼 안쪽으로 다가가는 느낌은 죽는다. 명령과 응답의 상호작용이 되어 버린다. 바로 이것이 내가 원하지 않았던 것이다.
Bain은 오디오와 비주얼 사이의 간극에 대해 쓰고 있었지만, 같은 논리가 몸과 비주얼 사이의 간극에도 적용된다. 실시간 반응은 마지막에 덧붙이는 기능이 아니다. 경험이 작동하도록 만드는 전제 조건이다.
-
렌더링 성능
두 번째 벽은 파티클 수를 늘리려 시도하자마자 드러났다. 몇 천 개의 파티클은 브라우저에서 잘 돌아간다. 3만 개가 되면 프레임 레이트가 한 자리 수로 떨어진다. 내가 염두에 두었던 시각적 품질은 3만 개를 훨씬 넘는 수가 필요하다.
원인은 구조적이다. 브라우저는 페이지가 GPU와 얼마나 직접적으로 대화할 수 있는지를 제약하며, 그 결과 파티클 시뮬레이션의 많은 부분이 결국 CPU 위의 JavaScript에서 돌게 된다. JavaScript는 단일 스레드다. 큰 규모의 파티클 시뮬레이션이 매 프레임 단일 스레드에서 돌아가는 것은 어떤 코드 최적화로도 고칠 수 없는 병목이다.
일반적인 것들을 시도했다. 파티클당 작업을 줄였고, 할당을 풀링했고, 셰이더로 옮길 수 있는 것은 옮겼다. 개선은 미미했다. 천장은 환경이었지, 코드가 아니었다.
-
시각적 품질의 천장
세 번째 벽은 렌더링 환경 자체가 무엇을 할 수 있는가에 관한 것이었다. 대부분의 브라우저가 폭넓은 호환성을 위해 사용하는 WebGL 1.0은 컴퓨트 셰이더를 지원하지 않는다. 텍스처 포맷이 제한적이고 고급 후처리 옵션도 제한적이다. 내가 원했던 종류의 파티클 분위기, 즉 볼류메트릭 광채와 중첩된 투명성, 커스텀 컴퓨트 패스를 포함하는 것에 대해 읽었던 모든 것들은 더 강력한 렌더링 API를 전제로 하고 있었다.
얼마간은 우회해 볼 수도 있었다. 그런 기능에 의존하지 않는 스타일리시한 비주얼은 여전히 가능했을 것이다. 하지만 앞의 두 벽에서 브라우저가 이미 다른 방식으로 나를 제한하고 있다는 것을 알았기에, 세 번째 벽을 우회하는 것은 이미 닫히고 있는 문을 더 세게 미는 일처럼 느껴졌다.
결론
한 주가 끝날 무렵에는 웹 방향이 자기 역할을 다했다는 것이 분명했다. 세 가지 축이 하나의 애플리케이션 안에서 함께 돌 수 있다는 것을 증명했고, 그것이 Week 2의 질문이었다. 그리고 브라우저 기반 구현은 이 프로젝트가 필요로 하는 품질로 그 축들을 감당할 수 없다는 것도 증명했다.
실패는 생산적이었다. 이번 주를 시작할 때 나는 Python과 네이티브 툴링에 대한 선호는 있었지만 그것을 확정할 결정적인 근거는 없었다. 이번 주가 끝난 뒤 나는 구체적인 세 가지 근거를 가졌고, 각각이 예측이 아니라 실제 돌아가는 프로토타입에서 관찰 가능한 것이었다. Frayling의 “research through design” 프레임이 여기서 벌어진 일과 잘 맞는다. 플랫폼에 대한 지식은 도구에 관해 읽는 것에서 오지 않았다. 하나를 시도해 보고, 그것이 구체적이고 읽어낼 수 있는 방식으로 실패하는 것을 지켜보는 데서 왔다.
다음 주는 이주가 될 것이었다.
최종 결과 · 주차 마감 상태