본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 28. 06:09

Orange Pi Zero에서 구현한 Brainrot 아트 설치물 엔지니어링

요약

저사양 Orange Pi Zero를 사용하여 무한 스크롤 비디오를 재생하는 인터랙티브 아트 설치물 'BrainRot TV'의 구현 과정을 다룹니다. Google Cloud Run과 Docker를 활용한 아키텍처 설계 및 임베디드 환경에서의 성능 최적화 방법을 설명합니다.

핵심 포인트

  • Orange Pi Zero와 같은 저사양 SBC에서의 웹 미디어 최적화
  • Google Cloud Run 및 Docker를 활용한 경량 컨테이너 배포
  • Fisher-Yates 알고리즘을 이용한 동적 비디오 플레이리스트 구현
  • 물리적 하드웨어와 웹 애플리케이션 간의 매핑 및 인터랙션

TIAT "Slop Epistemologies" 전시를 위해 게임화된 무한 스크롤 비디오 설치물을 어떻게 구축했는지, 그리고 15달러짜리 싱글 보드 컴퓨터(Single-board computer)에서 무거운 웹 미디어가 부드럽게 실행되도록 어떻게 최적화했는지에 대하여.

David Foster Wallace의 _Infinite Jest_에서 "The Entertainment"는 너무나 치명적으로 매혹적인 영화 카트리지여서, 이를 보는 사람은 다른 무엇을 하고자 하는 욕구를 모두 잃고 결국 화면에 갇힌 채 굶어 죽게 됩니다.

샌프란시스코에서 열린 TIAT (The Intersection of Art & Technology) "Slop Epistemologies" 전시를 위해, 저는 현대의 알고리즘 콘텐츠 소비라는 관점을 통해 이 개념을 탐구하고 싶었습니다. 우리는 비판적 사고를 우회하고 우리의 주의 집중력을 영구적으로 "망가뜨리도록(cooked)" 설계된 초최적화된 피드, 즉 무한한 숏폼(Short-form) 비디오 슬롭(Slop)의 시대에 살고 있습니다.

그 결과물이 바로 BrainRot TV — The Entertainment입니다. 이는 갤러리 방문객이 모니터 앞으로 다가와 물리적인 USB 슬라이드 어드밴서(USB slide advancer)를 잡고, 큐레이션된 비디오 슬롭의 끝없고 악화되는 스트림에 자발적으로 "몰입(LOCK IN)"하게 되는 인터랙티브한 물리적 아트 설치물입니다.

개념적 전제는 예술적이지만, 이를 실제로 구현하기 위해서는 매혹적인 풀스택(Full-stack) 및 임베디드 시스템(Embedded systems) 엔지니어링 과제들을 해결해야 했습니다. 저는 끝없는 비디오 피드를 재생하고, 절차적 오디오(Procedural audio)를 생성하며, 게임화된 심리적 쇠퇴를 추적할 수 있는 반응형의 몰입형 웹 애플리케이션을 구축해야 했으며, 이 모든 것이 640×480 CRT 스타일 디스플레이에 연결된 저사양 Orange Pi Zero에서 결함 없이 실행되어야 했습니다.

이 글은 이것을 가능하게 만든 아키텍처(Architecture), 물리적 하드웨어 매핑(Physical hardware mapping), 그리고 공격적인 성능 최적화(Performance optimizations)에 대한 심층적인 분석입니다. 준비되셨나요! 😄

1. 핵심 경험 및 아키텍처

BrainRot TV의 핵심은 Google Cloud Run에 배포된 커스텀 경량 Docker화된 Nginx 컨테이너를 통해 서비스되는 순수(vanilla) HTML5, CSS3, JavaScript 애플리케이션입니다.

"slop" 큐레이션

실제 알고리즘 피드(algorithmic feed)를 시뮬레이션하기 위해, Google Cloud Storage에 호스팅된 120개 이상의 직접적인 MP4 비디오 URL로 구성된 플레이리스트를 구축했습니다. 방문자가 "LOCK IN"을 누르면 플레이리스트는 Fisher-Yates 셔플 알고리즘을 통해 동적으로 섞이며, 클립 사이의 TikTok 스타일 수직 스와이프 전환(vertical swipe transition)이 시작됩니다.

// 다크 테마 감지 var iframe = document.getElementById('tweet-2070630195028250804-599'); if (document.body.className.includes('dark-theme')) { iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2070630195028250804&theme=dark" }

생성형 오디오 (Web Audio API)

정적인 오디오 파일을 루프(looping)시키는 대신, 이 설치물은 Web Audio API를 사용하여 실시간으로 진화하는 절차적 드론 분위기(procedural drone atmosphere)를 생성합니다.

  • 두 개의 디튜닝된 사인 오실레이터(detuned sine oscillators)가 A1 (55 Hz)과 E2 (82.41 Hz) 주변을 표류하며 으스스한 완전 5도(open fifth) 화음을 만들어냅니다.
  • 느린 LFO가 피치 드리프트(pitch drift)를 변조하여 유기적이고 불안한 따스함을 제공하며, 필터링된 핑크 노이즈 베드(filtered pink-noise bed)가 미세한 아날로그 정적 질감을 더합니다.

오디오 엔진은 loadeddata 휴리스틱(heuristics)을 사용하여 활성화된 비디오 스트림을 감지합니다. 현재 재생 중인 비디오에 활성 오디오 트랙(Veo 3 또는 Omni로 생성됨)이 포함되어 있으면, 절차적 앰비언트 드론(procedural ambient drone)의 볼륨이 자동으로 35%에서 6%로 낮아지는 더킹(ducking)이 발생하며, 무음 클립 동안에는 다시 상승하여 시각적 및 청각적 긴장감을 유지합니다.

// 비디오 오디오 감지에 따른 앰비언트 음악 더킹(Ducking)
function checkVideoAudio() {
  const player = dom.videoPlayer;
...

"Cooked" 미터 및 멜트다운(Meltdown) 메커니즘

방문자들이 시청함에 따라 심리적 쇠퇴 미터(psychological decay meter)가 시간이 지남에 따라 가속화됩니다. 이 미터는 FRESHSLIGHTLY GLAZED부터 NO THOUGHTS HEAD EMPTY, 그리고 마지막으로 THE ENTERTAINMENT에 이르기까지 9개의 뚜렷한 단계(tiers)를 통해 확장됩니다.

그 과정에서 UI는 단일 프레임의 잠재의식적 명령(CONSUME, OBEY, DO NOT LOOK AWAY)과 주기적인 Sick, Sad World 타이틀 카드를 깜빡이며 보여줍니다. 시청자가 100%의 rot(뇌 부패) 상태에 도달하면, 치명적인 멜트다운(meltdown) 시퀀스가 시작됩니다. 격렬한 CSS 화면 흔들림이 화면을 장악하고, "TOUCH GRASS" 종료 버튼은 강제로 비활성화됩니다. 시스템이 블루스크린(BSOD) 커널 패닉(kernel panic) 상태로 붕괴될 때까지 사용자는 떠날 수 없습니다.

2. 물리적 세계와의 연결

이 프로젝트는 물리적인 갤러리 설치물(installation)이기 때문에, 사용자가 키보드나 마우스를 직접 만지는 것을 원치 않았습니다. 대신, 방문객들은 Orange Pi에 연결된 표준 무선 **USB 프레젠테이션 클릭커 (슬라이드 어드밴서, slide advancer)**를 사용하여 작품과 상호작용합니다.

대부분의 상용 USB 슬라이드 어드밴서는 표준 USB HID 키보드 이벤트를 에뮬레이션(emulate)하며, 일반적으로 "다음" 버튼에는 PageDown 또는 ArrowRight를, "이전" 버튼에는 PageUp 또는 ArrowLeft를 송출합니다. 우리는 이러한 단순한 물리적 입력을 복잡한 상태 전이(state transitions)로 매핑하기 위해 문맥 민감형 이벤트 디스패처(context-sensitive event dispatcher)를 구축했습니다.

클릭커 버튼HID 키 코드랜딩 화면시청 화면BSOD 충돌 화면
Forward ▶PageDown, ArrowRight, Enter🔒 LOCK IN (시작)Skip Video🔒 REBOOT BRAIN
Back ◀PageUp, ArrowLeft, Escape(동작 없음)🌱 TOUCH GRASS (종료)(동작 없음)
const FORWARD_KEYS = new Set(['PageDown', 'ArrowRight', 'ArrowDown', 'Enter', ' ']);
const BACK_KEYS = new Set(['PageUp', 'ArrowLeft', 'ArrowUp', 'Escape', 'Backspace']);

...

3. Orange Pi Zero를 위한 최적화

최신 MacBook M-series 칩에서 무거운 비디오 스트림과 동적 CSS 필터(CSS filters)를 실행하는 것은 사소한 일입니다. 하지만 저주파 Allwinner ARM 프로세서, 512MB RAM, 그리고 최소한의 GPU 가속만을 갖춘 초소형 싱글 보드 컴퓨터(Single-board computer)인 Orange Pi Zero에서 이를 실행하는 것은 즉각적인 성능 병목 현상을 야기했습니다.

Orange Pi에서 설치물을 처음 테스트했을 때, 비디오는 심하게 끊겼고, 프레임 레이트(Frame rates)는 한 자릿수로 떨어졌으며, 텍스트는 640×480 디스플레이 상에서 읽을 수 없는 흐릿한 얼룩처럼 렌더링되었습니다. 이를 해결하기 위해서는 특화된 **저전력 아키텍처 (Low-power architecture)**를 설계해야 했습니다.

온보드 하드웨어 자동 감지

두 개의 별도 코드베이스를 유지하는 대신, 애플리케이션은 실행 시 브라우저의 동시성(Concurrency)과 하드웨어 메모리 성능을 검사하여, 임베디드 엣지 하드웨어(Embedded edge hardware)에서 실행될 때 저전력 최적화를 자동으로 활성화합니다:

const LOW_POWER = new URLSearchParams(window.location.search).get('lowpower') === '1' ||
  (navigator.deviceMemory && navigator.deviceMemory <= 2) ||
  (navigator.hardwareConcurrency && navigator.hardwareConcurrency <= 2);

심층 비디오 프리페칭 (Deep Video Prefetching)

Wi-Fi 신호가 약하거나 CPU 스레드(Threads)가 제한적인 환경에서는, 다음 MP4를 가져오기 전에 사용자가 "Skip"을 클릭할 때까지 기다리는 것이 불쾌한 검은색 일시 정지 화면을 유발합니다. 저전력 모드에서는 프리페치 파이프라인(Prefetch pipeline)을 비디오 1개에서 4개의 숨겨진 <video> 버퍼 요소로 구성된 비동기 큐(Asynchronous queue)로 확장했습니다. preload="auto"를 설정하고 이를 DOM 외부에서 음소거 상태로 유지함으로써, 브라우저는 미디어 캐시(Media cache)를 미리 조용히 채워 넣어 비디오 전환 시 지연 없는 즉각적인 컷을 보장합니다.

GPU를 과부하시키는 CSS 필터 제거

원래는 방문자의 브레인롯(Brain rot)이 진행됨에 따라 .screen--viewing 컨테이너 전체에 hue-rotate(), saturate(), blur()와 같은 강렬한 CSS 왜곡(Distortions)이 적용되었습니다.

전용 GPU 합성(Compositing) 스레드가 없는 ARM Linux에서는 CSS blur()가 소프트웨어 렌더링(Software rendering)을 강제하여 CPU에 엄청난 부하를 줍니다. 저전력 모드에서는 모든 CSS 필터와 전체 화면 DOM 오버레이(CSS 스캔라인(Scanlines) 및 글리치(Glitch) 오버레이 등)를 동적으로 제거하고, 순수하게 가벼운 불투명도(Opacity) 변화와 단색 대비(Solid color contrast)에만 의존합니다.

절차적 캔버스 노이즈(Procedural canvas noise) 스로틀링(Throttling)

애플리케이션은 아날로그 TV 화이트 노이즈(White noise)를 렌더링하는 실시간 2D <canvas> 기능을 포함하고 있습니다. 60fps로 실행되는 단순한 requestAnimationFrame 루프는 Math.random() 픽셀 데이터를 계산하는 데만 Orange Pi CPU 사이클의 40% 이상을 소모했습니다.

이를 해결하기 위해 프레임레이트 스로틀링(Framerate throttling)과 해상도 스케일링(Resolution scaling)을 도입했습니다. 저전력 하드웨어에서는 캔버스의 내부 해상도를 8로 나누고(CSS를 통해 부드럽게 확대), 초당 단 8프레임으로 렌더링되도록 스로틀링하거나, 필요한 경우 아예 건너뛰도록 설정했습니다:

const STATIC_FRAME_INTERVAL = LOW_POWER ? 125 : 0; // 125ms = ~8 FPS
const STATIC_RESOLUTION_DIVISOR = LOW_POWER ? 8 : 4;

4. 640×480 CRT 타이포그래피(Typography)

마지막 장애물은 시각적 타이포그래피(Typography)였습니다. 640×480 해상도에서 커스텀 웹 폰트(Press Start 2P 또는 스타일화된 디스플레이 폰트 등)는 Linux ARM 브라우저에서 매우 형편없이 렌더링되었습니다. 고해상도(High-DPI) 화면이나 OS 수준의 서브픽셀 안티앨리어싱(Subpixel anti-aliasing)이 없었기 때문에, 글자들이 뭉쳐서 읽을 수 없는 픽셀 덩어리처럼 보였습니다. 게다가 표준 텍스트 그림자(0 0 10px neon-green)는 탁한 후광(Halos)처럼 번졌습니다.

어두운 갤러리에서 3피트 거리에서도 선명한 가독성을 보장하기 위해, 우리는 임베디드 타이포그래피의 완전한 개편을 실행했습니다:

  1. 시스템 폰트 (System Fonts): 임베디드 장치에서는 Google Fonts를 완전히 배제하고, DOM 요소를 오버라이드하여 네이티브 OS 폰트 스택(-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif)을 사용하도록 했습니다. 네이티브 폰트는 저해상도 픽셀 그리드에 완벽하게 정렬되는 내장 힌팅 (hinting) 규칙을 가지고 있습니다.
  2. 크기 두 배 확대 (Scale Doubling): 전반적으로 폰트 크기를 두 배로 키웠습니다. 헤더는 72px–110px, 컨트롤 버튼은 36px, 텔레메트리 (telemetry) 배지는 24px로 확대했습니다.
  3. 제로 섀도우 (Zero-Shadow): 모든 빛나는 텍스트 그림자(glowing text shadows)를 제거했으며, backdrop-filter: blur()를 사용한 글래스모피즘 (glassmorphism)을 100% 불투명한 칠흑색 대비 배경(#000 !important)으로 교체했습니다. 텍스트가 움직이는 비디오 픽셀 위에 합성되지 않도록 했습니다.
  4. 이모지 (Emojis): 경량 ARM Linux OS 빌드는 포괄적인 유니코드 (Unicode) 이모지 폰트 테이블이 부족한 경우가 많아, 이모지가 빈 사각형 박스()로 렌더링되곤 합니다. 우리는 UI 이모지를 <span class="emoji"> 태그로 감싸고 저전력 모드에서는 display: none !important를 적용하여, 이를 ///와 같은 깔끔한 사이버고딕 (cybergothic) ASCII 인디케이터로 대체했습니다.

슬롭(Slop)은 보는 이의 눈에 달려 있다

TIAT의 "Slop Epistemologies" 전시를 위해 BrainRot TV를 제작하는 과정은 매우 즐거웠으며, 하드웨어의 제약이 종종 가장 영향력 있는 엔지니어링 및 미학적 결정을 이끌어낼 수 있다는 점을 상기시켜 주는 좋은 경험이었습니다.

무거운 GPU 추상화 계층을 제거하고 15달러짜리 Orange Pi Zero에 특화된 미디어 파이프라인 (media pipelines)을 맞춤 제작함으로써, 이제 BrainRot은 끊김이 없고, 조기 충돌이 발생하지 않으며, 현대의 디지털 소비에 대한 강렬하고 매혹적이며 벗어날 수 없는 비판을 전달하는 매우 견고한 60fps 비디오 재생 루프를 갖추게 되었습니다.

샌프란시스코에서 열리는 전시회에 참석하신다면, 터미널 앞으로 다가와 클릭커를 잡고 LOCK IN을 누르세요! 다만 시스템이 당신을 집어삼키기 전에 미리 '풀밭을 만지며 휴식(Touch Grass)'하는 것을 잊지 마세요. 😅

BrainRot TV의 전체 코드베이스는 Docker로 컨테이너화되어 Google Cloud Run에 배포됩니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0