
코드와 예술의 경계, 그리고 14,000개의 DOM 요소를 다루는 법
8년차 개발자 김테크가 라바 랩스와 협업하며 14,000개의 요소를 처리하는 생성형 예술 작품 'Quine'을 구현한 기술적 도전과 해결 과정을 공유합니다.
김테크
8년차 개발자

안녕하세요. 풀링포레스트에서 백엔드와 인프라를 거쳐, 이제는 풀스택의 영역을 넘나들고 있는 8년차 개발자 김테크입니다.
개발자라면 누구나 한 번쯤 "재귀(Recursion)"라는 개념에 매료된 적이 있을 겁니다. 거울 속에 비친 거울처럼 끝없이 이어지는 그 논리적 구조 말이죠. 오늘은 제가 최근에 겪었던 아주 흥미로운 프로젝트 경험을 공유하려 합니다. 바로 '크립토펑크(CryptoPunks)'로 유명한 라바 랩스(Larva Labs)와 협업하며 'Quine(콰인)'이라는 독특한 생성형 예술 작품을 애니메이션으로 구현했던 이야기입니다. 단순히 예쁜 그림을 그리는 것이 아니라, 수만 개의 데이터를 브라우저에서 어떻게 효율적으로 렌더링할 것인가에 대한 치열한 기술적 고민이 담겨 있습니다.
이야기는 우연한 만남에서 시작되었습니다. 퇴근길에 우연히 오랜 친구이자 라바 랩스의 공동 창립자인 존(John Watkinson)을 만났습니다. 그들은 당시 'Quine'이라는 새로운 프로젝트를 준비 중이었는데, 이걸 시각적으로 구현해 줄 엔지니어를 찾고 있었죠. 타이밍이 기가 막혔습니다.
'Quine'의 개념은 개발자인 저에게도 신선한 충격이었습니다. 코드가 예술을 생성하고, 그 예술 안에 다시 코드가 숨겨져 있는 구조입니다. 심지어 그 숨겨진 코드를 추출해 실행하면 다음 세대의 변형된 예술 작품이 생성됩니다. 3세대마다 루프가 도는 '3-Quine', 영원히 루프하지 않는 'Pseudo-Quine' 등 수학적 특성까지 가지고 있었죠. 제 임무는 이 복잡한 생성 과정을 시각적인 애니메이션으로 표현하는 것이었습니다.
하지만 기술 명세서를 받아든 순간, 솔직히 좀 막막했습니다.
각 Quine은 1440x2560 픽셀 해상도에, 내부적으로 14x14 픽셀 크기의 사각형(Square)들로 구성되어 있었습니다. 이를 SVG(Scalable Vector Graphics)로 구현한다면, 하나의 작품당 최대 14,400개의 <rect> 요소가 필요했습니다. 여기에 코드를 표현하는 텍스트 요소(<tspan>)까지 합치면 요소 개수는 2만 개에 육박합니다.
백엔드 개발자로 비유하자면, 단일 요청에 2만 번의 DB 쿼리를 날리는 것과 비슷했습니다. 브라우저의 DOM(Document Object Model)에 수만 개의 노드를 때려 박고 애니메이션을 돌린다면? 브라우저는 비명조차 지르지 못하고 뻗어버릴 게 뻔했습니다. SVG는 벡터 기반이라 확대해도 깨지지 않지만, 요소가 많아질수록 성능은 기하급수적으로 떨어지니까요.
저는 망설임 없이 SVG를 포기하고 <canvas>를 선택했습니다. 캔버스는 비트맵 방식이지만 하드웨어 가속을 활용해 수천, 수만 개의 오브젝트를 고속으로 그려내는 데 최적화되어 있습니다. 마치 대용량 트래픽을 처리하기 위해 REST API 대신 gRPC 스트리밍을 선택하는 것과 같은 이치였죠.
물론 바로 코드를 짜진 않았습니다. 엔지니어의 기본은 '검증'이니까요. 저는 가장 극단적인 케이스부터 성능 테스트를 진행했습니다.
모든 도형을 개별적으로 애니메이션화해보기 (최악의 시나리오)
텍스트의 위치 대신 스케일(Scale)만 변형해보기
요소들을 그룹으로 묶어 레이어 단위로 렌더링하기
놀랍게도 캔버스의 성능은 기대 이상이었습니다. 개별 애니메이션도 꽤 버텨주더군요. 하지만 시각적인 완성도와 더 나은 퍼포먼스를 위해, 저는 '프린터'의 메타포를 차용하기로 했습니다. 잉크젯 프린터가 한 줄씩 이미지를 찍어내듯, 혹은 실크스크린 인쇄처럼 색상별 레이어가 입혀지듯 애니메이션을 구성했습니다. 기계적이고 선형적인 움직임이 오히려 코드가 생성되는 과정을 더 극적으로 보여줄 거라 판단했습니다.
여기서 한 가지 난관이 더 있었습니다. Quine의 핵심은 "그림 안에 코드가 있다"는 것입니다. 하지만 그림(사각형)과 코드를 동시에 보여주니, 시각적 정보량이 너무 많아 코드가 묻혀버렸습니다.
저는 '반전(Inversion)' 기법을 도입했습니다. 먼저 코드 레이어만 인쇄하여 "이것은 코드입니다"라고 명확히 보여준 뒤, 그 위로 사각형 레이어가 덮일 때 색상을 반전시켜 코드가 그림 속에 자연스럽게 녹아들게 만들었습니다. 백엔드 로직으로 치면, 데이터 전처리를 통해 핵심 정보를 먼저 필터링하고 나중에 메타데이터를 입히는 방식과 비슷하겠네요.
마지막 화룡점정은 '스캐닝' 효과였습니다. 이 코드가 단순히 무작위 텍스트가 아니라 실행 가능한 진짜 코드라는 걸 보여주고 싶었습니다. 그래서 개발자들에게 친숙한 IDE(통합 개발 환경) 스타일의 UI를 입히고, 스캐너가 지나가면 코드가 하이라이팅되는 연출을 더했습니다. 커서가 깜빡이고 텍스트가 스트리밍되는 그 익숙한 느낌 말이죠.
결과적으로 프린팅 애니메이션과 스캐닝 효과가 병렬로 작동하면서, 코드가 예술이 되고 예술이 다시 코드가 되는 Quine의 순환 구조를 완벽하게 시각화할 수 있었습니다.
이번 프로젝트를 통해 뼈저리게 느낀 점이 있습니다. 기술적 제약(DOM 퍼포먼스)을 창의적인 우회로(Canvas, 프린터 메타포)로 극복했을 때, 비로소 엔지니어링은 예술의 경지에 다다른다는 것입니다. 무조건 최신 기술이나 편한 도구(SVG)를 고집하기보다, 데이터의 규모와 특성에 맞는 도구(Canvas)를 선택하는 것이야말로 8년차 개발자가 갖춰야 할 진짜 실력이 아닐까 싶습니다.
여러분도 혹시 화면에 렌더링해야 할 데이터가 너무 많아 고민하고 계신가요? 때로는 과감하게 익숙한 도구를 버리고, 로우 레벨(Low-level)로 내려가 보는 건 어떨까요. 그곳에 의외의 해답이 기다리고 있을지도 모릅니다.