📌 파이 (pi) - AI 광고 제작 스튜디오 게임형 인터랙티브 공식 웹사이트 구축
🔹 프로젝트 개요
🔹 프로젝트 목적
파이(pi)는 영상업계 8년차 PD들이 기획·연출·편집을 직접 담당하는 서울의 AI 광고 제작 스튜디오입니다. 본 프로젝트는 기존 WIX 템플릿을 걷어내고, 스튜디오가 직접 제작한 캐릭터 루프 영상을 화면 전체의 재료로 삼아 ‘페이지’가 아니라 ‘공간’으로 읽히는 게임형 인터랙티브 웹사이트를 만드는 것을 목표로 설계했습니다. 쇼킹핑크와 틸을 화이트 위에 올리고 픽셀 폰트·두꺼운 검정 테두리·픽셀 아트 커서·합성 효과음까지 오락실 캐비닛의 문법으로 정리했습니다. WebGL 3D 공간 연출은 계약 범위에서 제외되어 화면 전부를 2D 영상이 끌고 가는 구조였고, 그래서 영상과 영상 사이의 이음새와 그 영상을 실어 나르는 비용이 이 프로젝트의 실제 엔지니어링 과제가 됐습니다. 또한 스튜디오가 개발자 없이 작품·수상·클라이언트·회사소개서를 직접 운영할 수 있도록 전용 관리자 CMS를 함께 구축했습니다.
🔹 핵심 기술 및 구현 기능 (Key Technical Features)
Insert-to-Loop Seam Handoff (인서트→루프 이음새 처리):
섹션에 들어가면 전체화면 인서트 영상이 재생되고, 그 영상이 우측 칸의 루프 영상으로 넘어가야 합니다. 칸도 크롭도 프레임도 달라 그냥 바꾸면 그림이 튑니다. 전환을 intro → handoff → content 세 단계로 나눠, 인서트가 도는 동안 루프는 0초에 세워 두고, 오버레이를 루프 칸의 실제 화면 좌표(getBoundingClientRect)까지 0.62초에 걸쳐 좁히면서 그 안에서 같은 루프를 돌리고 인서트를 0.34초 디졸브로 걷어냅니다. 4K로 교체한 뒤 seek이 수백 ms 걸려 0초 프레임이 비쳤다 점프하던 문제는, handoff 시작과 동시에 본 루프도 같은 타임라인으로 함께 재생해 seek 자체를 없애 해결했습니다.
4K Dual-Format Video Pipeline (4K 듀얼 포맷 영상 파이프라인):
3840×2160 원본 16편을 h264 MP4와 VP9 WebM 두 벌로 인코딩하고, 브라우저가 canPlayType에 ‘probably’로 답할 때만 WebM을 건네도록 분기했습니다. 사이트의 모든 영상이 muted로 재생되므로 오디오 트랙은 제거했고, 원본이 66Mbps라 용량이 튀던 한 편은 CRF를 조여 SSIM 0.977 수준에서 절반으로 줄였습니다. 해상도는 4배 올리고 총 용량은 195MB → 107MB, 방문자 한 명이 실제로 받는 양은 약 55MB입니다.
Hover Prefetch & Orientation Branching (호버 프리페치·화면 방향 분기):
인서트 영상이 편당 10MB를 넘어, 클릭한 뒤에 받기 시작하면 첫 프레임까지 빈 화면이 남습니다. 메뉴 버튼에 포인터가 닿는 순간(클릭보다 몇백 ms 앞서) 숨은 video 엘리먼트로 버퍼링을 시작해 섹션이 캐시에서 바로 열리게 했습니다. 호버가 없는 터치 기기는 진입 후 한가할 때 차례로 데우되 데이터 절약 모드와 2G 회선에서는 건너뛰며, 데스크톱은 가로형·모바일은 세로형을 쓰고 인서트와 루프의 방향을 같게 묶어 이음새가 포맷을 넘나들지 않게 했습니다.
Content Tables with Seed Fallback (DB 원본 + 시드 폴백 구조):
작품 21편·수상 8건·클라이언트 로고 14곳·사이트 설정을 Postgres로 옮기고, 공개 페이지는 DB를 먼저 읽되 표가 비어 있거나 조회에 실패하면 번들에 함께 실린 시드로 그리도록 했습니다. 마이그레이션 중이거나 네트워크가 흔들려도 화면이 비지 않습니다. RLS는 익명 조회를 published 행으로 제한하고 쓰기는 로그인 세션에만 허용하며, 마이그레이션은 여러 번 실행해도 안전하도록 작성했습니다. 영문 칸이 비면 국문 값으로 폴백해 빈칸이 노출되지 않습니다.
Admin CMS for Non-developers (비개발자용 관리자 CMS):
문의 접수·포트폴리오·수상·클라이언트·설정 5개 탭. 유튜브 주소를 통째로 붙여넣으면 ID를 자동 추출하고, 썸네일은 Storage로 바로 업로드되며, 노출 순서는 숫자 입력이 아니라 ↑↓ 버튼으로 바꿉니다. 수상작 카드가 4:3으로 잘리는 문제는 CSS object-position을 ‘잘릴 위치 슬라이더’로 감싸고 미리보기를 실제 카드와 같은 비율로 보여줘 해결했습니다. 회사소개서 PDF를 올리면 사이트 좌하단 버튼이 즉시 생기고, 연결을 해제하면 버튼 자체가 사라져 깨진 링크가 남지 않습니다.
Pricing Behind the Login (견적 단가표 분리·관리자 보안):
고객 화면에 금액을 일절 노출하지 않기로 하여 단가표를 CONTACT 폼이 아닌 관리자 번들에만 두었습니다. 접수 건에는 선택값만 저장되고 금액 환산은 로그인 이후에 일어납니다. 관리자 화면은 지연 로딩으로 분리해 방문자 번들에 섞이지 않으며, 유휴 시간 자동 로그아웃과 접수 내역 CSV 내려받기를 갖췄습니다.
SPA SEO & Share Cards (SPA 검색·공유 카드 대응):
빌드 결과의 body가 #root 하나뿐이어서, 자바스크립트를 실행하지 않는 공유 크롤러에는 링크를 공유해도 아무것도 뜨지 않는 상태였습니다. OG 이미지를 새로 만들고 정적 메타·트위터 카드·canonical·hreflang·Organization JSON-LD를 넣은 뒤, 언어 토글이 새로고침 없이 경로만 바꾸는 점을 감안해 전환 시점에 lang·제목·og:url·canonical을 다시 쓰도록 했습니다. 관리자 경로는 robots.txt에 적으면 오히려 주소를 알리는 셈이라 noindex 메타로 처리했습니다.
Bilingual Routing without a Library (라이브러리 없는 국·영문 라우팅):
/kr·/en 경로를 언어의 단일 출처로 삼고, 토글은 pushState로 경로만 바꿔 새로고침 없이 전환합니다. 영문 사전에 없는 키는 국문으로 폴백해 번역이 덜 채워져도 화면이 깨지지 않으며, 국문 출력이 그대로 유지되도록 각 컴포넌트를 {ko, en} 구조로 옮겼습니다.
🔹 디자인 포인트