Unity
"데자뷰, 느껴본적있어?"
김*균··수정됨 2026.07.19


5초 전의 나와 마주하는 미러 미션 체험
전시 화면 앞에 서서 화면 속 미션 동작을 따라 하면, 옆 화면에서 5초 전의 자신이 그 동작을 뒤따라 재생됩니다. 관람객은 실시간 화면과 지연 화면, 두 개의 자신을 동시에 마주하게 됩니다. 이번 포스팅에서는 해당 콘텐츠의 실시간 프레임 버퍼링 구현 과정을 공유합니다.
시스템 아키텍처 개요
본 콘텐츠는 크게 두 가지 요소로 구성됩니다.
웹캠 실시간 출력: 웹캠 영상을 첫 번째 디스플레이에 지연 없이 그대로 표시합니다.
5초 지연 버퍼링: 매 프레임을 큐(Queue)에 적재하고, 정확히 5초(150프레임)가 지난 프레임을 꺼내 두 번째 디스플레이에 출력합니다.
메인 플랫폼은 Unity 단일 씬이며, 하나의 웹캠 소스를 실시간/지연 두 개의 RawImage로 분기해 출력하는 구조입니다.

주요 기술적 구현
2.1 프레임 고정 기반 정밀 지연
'5초 지연'을 보장하려면 지연 시간을 프레임 수로 환산할 수 있어야 합니다. 이를 위해 Application.targetFrameRate = 30으로 프레임을 고정하고, delaySeconds * 30 = 150 프레임을 목표 버퍼 크기로 설정했습니다. 웹캠은 640x480, 30fps로 명시적으로 초기화해 장시간 전시 운영에서의 부하를 예측 가능한 수준으로 제한했습니다.

Update()에서는 webcamTexture.didUpdateThisFrame으로 실제 프레임 갱신이 있을 때만 GetPixels32()로 픽셀 데이터를 복사해 큐에 적재하고, 큐 길이가 150을 초과하는 순간부터 가장 오래된 프레임을 꺼내 지연 디스플레이에 표시합니다. 큐가 채워지는 최초 5초 이후로는 항상 '정확히 5초 전'의 프레임이 출력됩니다.
2.2 텍스처 풀링을 통한 무중단 운영
초기 구현의 가장 큰 과제는 메모리였습니다. 30fps 기준으로 매 프레임 new Texture2D()를 호출하면 초당 30개의 텍스처가 생성되고, 이를 Destroy()로 파괴하면 가비지 컬렉션(GC)이 빈번하게 발동해 화면이 순간적으로 끊기는 현상이 발생합니다. 개발 환경에서 수 분 정도는 문제가 드러나지 않지만, 하루 종일 무중단으로 구동되는 전시 환경에서는 치명적입니다.
이를 해결하기 위해 오브젝트 풀링(Object Pooling) 패턴을 적용했습니다. 지연 출력을 마친 텍스처는 파괴하지 않고 Stack<Texture2D> 풀에 반환하며, 새 프레임 적재 시 풀에서 꺼내 SetPixels32()로 데이터만 덮어씁니다. 해상도 변경에 대비해 풀에서 꺼낸 텍스처의 크기가 다를 경우 Reinitialize()로 재설정하도록 방어 로직을 두었습니다.

결과적으로 텍스처 신규 할당은 최초 5초 동안 버퍼가 채워질 때 150회만 발생하고, 이후에는 추가 할당과 GC 스파이크 없이 일정한 메모리 사용량으로 운영됩니다.
지연 시간: 5초 (150프레임)
프레임 레이트: 30fps 고정
웹캠 해상도: 640x480
텍스처 신규 할당: 최초 150회 이후 0회
사용자 경험(UX) 최적화
몸으로 이해하는 '시간차': 관람객이 미션 동작을 수행한 직후 옆 화면에서 과거의 자신이 같은 동작을 재현하므로, '기록과 재생'이라는 개념을 별도의 설명 없이 몸으로 직관하게 됩니다.
끊김 없는 지연 영상: 텍스처 풀링으로 GC 스파이크를 제거해, 지연 화면이 버벅이며 몰입이 깨지는 순간이 없도록 했습니다. '5초 전의 나'가 매끄럽게 움직여야 실시간 화면과의 대비가 온전히 전달됩니다.
무인 운영 최적화: 프레임 고정, 고정 해상도, 자동 디스플레이 구성을 통해 개관부터 폐관까지 운영자 개입 없이 안정적으로 구동되는 것을 목표로 설계했습니다.
마치며
데자뷰는 처음 겪는 순간인데 이미 겪은 것 같은 기묘한 감각입니다. 이 콘텐츠는 그 감각을 거꾸로 만들어냅니다. 분명 방금 내가 한 동작인데, 화면 속에서 다시 마주치면 낯설게 느껴지죠. 관람객이 5초 전의 자신에게 손을 흔들고, 따라 하고, 놀다 보면 어느새 시간의 흐름을 몸으로 체감하게 됩니다. 전시장에서 5초 전의 나와 마주쳐보세요.
읽기 도구
약 4분 읽기
이 글이 도움이 되었나요?