라이브 체험 프로젝트 소개
Foldscape Memories(저장소 안에서는 Nature Memories · Duo라고도 불린다)는 여행 사진을 3차원 기억으로 펼쳐 내는 인터랙티브 사이트로, React, Three.js, GSAP, Vite로 만들어졌다. 기기 표현은 저자가 이전에 브라우저로 재현한 폴더블 iPhone Duo(SkentSun / iPhone Duo Depth Lab) — 내부·커버 양면 화면, 일곱 가지 자세, 두 가지 마감이 모두 움직이는 완전한 목업 — 에서 출발했고, 이 프로젝트는 그 위에 「기억」이라는 층을 얹었다.
홈 화면은 닫힌 기기 한 대와 사진 한 장으로 시작한다. 스크롤하면 후보 사진들이 오른쪽에서 원통형 궤적을 따라 들어와 커버 화면 가장자리를 통해 녹아들고, Open memory를 누르면 기기가 5초 동안 펼쳐지며 카메라를 낮추는 사이 사진 속 장소가 화면에서 솟아오른다. 지금까지의 기억은 다섯 개 — Round Island Light 등대, 그린란드 빙해의 붉은 돛배, 아이슬란드 Kálfeyri의 해변 집, 산토리니, 오사카성. 드래그로 회전, 스크롤로 확대하고, Rewind는 같은 타임라인을 따라 사진을 다시 접는다. 오른쪽 위의 독립된 배경화면 스튜디오는 업로드한 이미지나 영상으로 내부·커버 화면을 갈아입히고 브라우저에서 깊이를 생성한다.
다섯 사례의 사진과 GLB 모델은 저장소에 함께 담겨 있어 감상에 API 키가 필요하지 않다. 선택 사항인 브라우저 내 깊이 생성은 필요할 때 추론 모델을 내려받는다. 사이트는 Vercel에 배포되어 있고(빌드 출력 dist/client) MIT 라이선스를 따르며, Apple 공식 모델과 배경화면 에셋은 THIRD_PARTY.md에 별도로 명시되어 해당 라이선스에서 제외된다.
체험 포인트
- 홈 화면은 원형 사진 갤러리다. 스크롤, 드래그 또는 방향키로 넘기면 각 사진이 원통형 궤적을 따라 기기 가장자리로 이동해 커버 화면 속으로 녹아들고, 반대로 스크롤하면 같은 경로를 되돌아가며 어느 지점에서든 멈출 수 있다.
- Open memory는 먼저 선택한 사진을 기기로 보내 해당 장면의 로딩을 기다린 뒤, 5초 동안 기기를 펼치고 카메라를 낮추고 줌을 조정한 다음 4°/s의 느린 자동 회전에 들어간다. 드래그로 회전, 스크롤로 확대하며, Rewind는 타임라인을 거꾸로 재생해 닫힌 사진으로 되돌린다.
- 다섯 개의 기억 — Round Island Light 등대, 그린란드 빙해의 붉은 돛배, 아이슬란드 Kálfeyri의 해변 집, 산토리니, 오사카성 — 각각 사진 한 장과 GLB 장면 하나로 이루어져 저장소에 함께 담겨 있으므로, 감상에는 API 키가 전혀 필요하지 않다.
- 배경화면 스튜디오(?view=wallpaper)는 업로드한 이미지나 영상으로 내부·커버 화면 배경을 바꾸고, 브라우저에서 빠른 깊이 맵을 계산한 뒤 소형 모델로 정제해 포인터를 따라 움직이는 시차와 심도를 만든다. 마감은 Star White와 Night Sky 두 가지. 소리는 기본적으로 꺼져 있으며, 켜면 절차적으로 생성된 해안 소음과 오리지널 앰비언트 코드가 흐른다. 동작 줄이기 설정에서는 장면 움직임, 자동 회전, 관성이 비활성화된다.
기술 분석
3D 에셋 · 다섯 개의 기억 장면 GLB와 Apple 모델을 개조한 폴더블 기기
다섯 개의 기억은 각각 사진 한 장과 GLB 장면 하나(lighthouse-memory-v2.glb는 약 25 MB)로, public/scenes 아래에 저장된다. 런타임에는 사진의 위쪽 절반만 커버로 사용하며, README에는 감상에 Tripo API 키가 필요 없다고 명시되어 있다 — 키는 에셋을 제작할 때만 필요하다.
폴더블 기기는 Apple 공식 iPhone Duo USDZ에서 왔다. scripts/prepare-model.mjs가 Playwright를 구동해 개발 페이지에서 USDZ를 불러오고, 움직이는 절반과 고정된 절반을 folding-half / stationary-half로 이름 붙이고, 내부·커버 화면 재질을 교체 가능한 흰 면으로 바꾼 뒤 GLTFExporter로 바이너리 GLB를 내보낸다(텍스처 상한 512). 다시 색을 입힐 수 있는 것은 금속 프레임만이며 화면·글라스·렌즈·힌지 디테일은 손대지 않는다. THIRD_PARTY.md는 Apple 에셋을 저장소의 MIT 라이선스 범위에서 제외한다고 선언한다.
사진의 여정 · 하나의 GSAP 진행도로 갤러리·실물 사진·커버 화면을 동시에 구동
원형 갤러리는 React Bits의 Circular Gallery를 OGL에서 Three.js로 포팅한 것이다. 100×50 분할 메시, 속도 기반 사인 정점 흔들림, 둥근 모서리 이미지 샘플링을 유지하면서 호를 깊이와 방향을 가진 원통형 경로로 확장하고, 기기와 하나의 PerspectiveCamera를 공유한다. GSAP Observer가 휠·포인터·터치 입력과 드래그 임계값을 담당하고, Timeline이 여정을 approach → receive-and-melt → settle로 안무한다. 새 입력은 진행 중인 애니메이션을 중단시키며 드래그로 역방향 샘플링도 가능하다.
사진 큐, 실물 사진 메시, 실제 커버 화면 이미지는 같은 진행도로 구동되고 화면 가장자리에서 텍스처 좌표가 일치한다. 바깥 메시는 화면에 들어가는 부분이 잘리고 화면이 해당 이미지를 채운다. 커버 전환은 Morph Slider의 Melt 분기(intensity 0.95 / scale 4.9 / aberration 0.35)를 사용하며, uTime을 벽시계가 아닌 여정 진행도로 구동하기 때문에 되감기와 정지 프레임이 가능하다.
화면 포털 · 보이는 범위는 실제로 움직이는 덮개만이 결정한다
장면은 완전히 펼쳐진 평면 위에 고정되어 제작되며 프레임마다 재구축하거나 재조정하지 않는다. 얼마나 보이는지는 움직이는 왼쪽 화면과 고정된 오른쪽 화면 사이의 각도가 결정한다 — 덮개를 열면 먼저 오른쪽 화면 위의 공간이 열리고, 덮개가 수직을 지나 평평해질수록 왼쪽 절반이 드러난다. 덮개를 멈추면 화면도 멈추고, 되감기는 같은 공간을 되짚어 간다. 덮개가 장면과 교차하는 곳의 임시 절단면은 실제 메시 교차선에서 공간 배제를 거쳐 삼각화하고, 변하지 않는 평면은 캐시해 GPU 버퍼를 재사용하며, 연한 얼음색이나 중립적인 석재색으로 채우고 완전히 닫힘·열림 양 끝에서는 숨긴다. 스텐실 방식은 전달된 메시에 열린 경계가 있어 채택하지 않았다. 왼쪽 수면 반사는 기울어진 이중 실루엣을 피하기 위해 평평함에 가까워질 때만 서서히 나타난다.
2026-09-16의 시작 최적화에서는 이 힌지 부위의 지오메트리 절단을 module worker로 옮겼다. 이전에는 다섯 장면 각각에 1–1.6초의 동기 준비가 필요했지만, 이제 메인 스레드는 transferable 버퍼를 복원하는 8–29ms만 쓴다. 새로 마운트된 장면은 렌더링 전에 현재 접힘 상태를 적용하고, 수면 반사 카메라는 기기와 갤러리가 아닌 자연 장면만 비추며, 배경화면 스튜디오의 프리셋과 AI 워커는 그 뷰에 실제로 들어갈 때만 로드된다.
배경화면 스튜디오 · 브라우저 내 깊이 추정과 접힘의 광학적 디테일
업로드한 이미지는 먼저 빠른 깊이 맵을 얻고, 이어서 소형 모델이 이를 정제한다(@huggingface/transformers가 depth.worker.js에서 실행되며, AI 워커는 실제로 생성 버튼을 눌렀을 때만 만들어진다). 전경과 배경은 깊이 차이에 따라 이동·블러 처리되어 포인터가 움직일 때 이미지에 실제 공간감이 생긴다. 다섯 개의 프리셋 배경화면은 512×288의 사전 생성 깊이 맵을 포함하고, 영상 프리셋은 포스터 프레임의 것을 사용한다. 내부·커버 화면 레이어는 JSON 레이아웃과 20개의 개별 SVG 아이콘으로 런타임에 투명 GPU 텍스처로 합성되므로, 아이콘 하나를 바꾸어도 화면 전체를 다시 그릴 필요가 없다.
접힘 자체는 매개변수 안에 있다. 블러 반경 계수는 내부 3.5, 커버 1.8로, 덮개가 닫힐 때 커버 화면이 먼저 흐려진다. 힌지는 96%에서 완전히 접히고 마지막 4%는 화면이 초점에 「안착」하도록 남겨 둔다. 밝기는 자세에 따라 사인 곡선을 따라 어두워지며 90° 부근이 가장 어둡다. 가로 시차는 샘플링 전에 화면 정점을 「완전히 펼쳐진 가상 평면」에 투영하기 때문에, 지오메트리는 접히더라도 배경화면은 눈앞의 평평한 유리판 위를 미끄러지듯 가로로 움직이고 사다리꼴로 왜곡되지 않는다.


