feat(showcase): 트웬티온스 사이트를 전면 개편한다
All checks were successful
ci / build (push) Successful in 33s

This commit is contained in:
Yun Chan 2026-08-25 03:50:28 +09:00
parent cb3c323c9f
commit 9529e3747c
29 changed files with 8906 additions and 1326 deletions

View file

@ -0,0 +1,229 @@
# 트웬티온스 전면 리디자인 — 1단계 레퍼런스 실측
> 상태: 인터뷰 선택 전에도 바뀌지 않는 구조·성능 근거를 먼저 확정한 기록.
> 색·명도·3D 주인공은 사용자 인터뷰 결과가 오면 2단계에서 최종 확정한다.
## 브리프
산업·교육 분야의 B2B 방문자가 트웬티온스의 네 현장과 실제 제품 관계를 공간적으로 이해하고 프로젝트 문의를 시작하게 한다. 느낌은 **정밀하고 몰입감 있게**.
### 0단계 기준선 감사
- 대상: `public/work/twentyoz-corp/index.html`과 쇼케이스 카드·캡처
- 현재 강점: 실제 고유명사와 기술 스택, 네 현장 라디오 전환, 의미 있는 HTML, 320/390/768/1440 오버플로·대비 통과
- 현재 약점: 첫 화면이 텍스트와 구분선만으로 구성돼 VR·산업 IoT·실시간 시뮬레이션을 시각적으로 증명하지 못함
- 모바일 약점: 390px에서 네 현장 선택기가 88px 높이로 네 줄 쌓이며, 선택 결과가 첫 화면 아래로 완전히 밀림
- 검증 공백: 기존 `tools/e2e.mjs`의 1,805개 단언은 `gaon-lms`와 `dure-enrollment`만 검사한다. 트웬티온스 전용 사용자 시나리오는 0개이므로 새 L6 스위트가 필요하다
## R1 · 구조 — Cognite
원본: https://www.cognite.com/en
- 업종: 산업 데이터·AI 플랫폼. 트웬티온스와 같은 산업 B2B 층위
- 가져올 축: **정보 위계, 그리드, 증거 배치**
- 섹션 흐름: 결과 중심 히어로 → 운영 성과 수치 → 고객 사례 → 역할별 효용 → 제품 체계 → 파트너 → 자료 → 데모 CTA
- 그리드: 1280px 뷰포트에서 지배 컨테이너 1233px, 주요 2열 589px / 565px. 본문 대표 폭 565px
- 타입: Space Grotesk + Manrope 2패밀리. 주요 h2 52/65px, 본문 18/32px. 최대/본문 2.9배
- 타입 단계 실측 상위: 12, 14, 16, 18, 20, 24, 28, 40, 44, 52px — 단계가 과다하므로 타입 체계는 가져오지 않는다
- 형태 실측: radius 2/4/6/8/12/9999px 등 6종 이상 — 형태 어휘도 가져오지 않는다
- 6축 밖의 관측: 기능 설명보다 운영 성과와 고객 증거가 먼저 온다. 데모·문의 CTA가 중간과 끝에서 반복된다
- 변형: 8단계 흐름을 `현장 → 제품 → 검증된 일 → 회사 → 문의` 5단계로 압축한다. 트웬티온스는 Cognite보다 제품·사례 수가 적고, 현재 8개 섹션이 이미 긴 페이지를 만든다
## R2 · 톤 — Polestar
원본: https://www.polestar.com/global/
- 업종: 전기차·자동차 커머스. R1과 다른 업종 ✓
- 가져올 축: **시각적 무게, 컬러 역할, 형태 절제, 타입 밀도**
- 첫 화면: 1280×720 중 제품 이미지의 실제 가시 면적 88.9%. 이미지 1265×648, y=72부터 시작
- 텍스트 위치: x=112, y=152. h1 30px / 400 / letter-spacing -1.2px. 제품이 크면 타이포가 물러난다
- CTA: 132×48px, radius 0. 제품 이미지 위에 있으나 단색·직사각형으로 조용하다
- 타입: Polestar Unica 한 패밀리. 지배 단계 16px / 30px, 장식적 굵기 대비 없이 400 중심
- 컬러: 검정 텍스트 82회, 60% 검정 보조 7회, 흰 텍스트 1회. 웹 UI의 강조색은 사실상 없고 제품 이미지가 색을 소유한다
- 형태: radius 사용 0건. 카드·필·글래스 패널로 고급감을 흉내내지 않는다
- 6축 밖의 관측: 제품 비주얼이 주인공이고 UI는 설명서처럼 물러난다
- 변형: 실제 자동차 사진 대신 네 현장 코어 3D가 첫 화면 가시 면적의 72~82%를 차지하게 한다. 국문 정보량 때문에 본문은 18px, h1은 최대 64px까지 올리되 2줄을 넘기지 않는다
## R3 · 디테일 — Shader.se 선택 렌더링과 장면 전환
원본: https://tympanus.net/codrops/2026/05/19/80s-business-tech-seamless-scene-transitions-inside-shader-ses-scroll-driven-webgpu-pipeline/
- 가져올 축: **3D 장면 전환과 렌더링 예산**
- 모션: 스크롤 진행도를 0..1로 정규화하고 현재 범위 밖 장면은 render pass 전체를 건너뛴다. 전환 직전 다음 장면만 미리 렌더해 텍스처를 현재 장면에 전달한다
- 전환 기법: 화면 좌표로 다음 장면 FBO를 샘플링하는 2D reveal, 또는 실제 3D 표면에 맞춰 카메라 frustum을 이동하는 물리적 전환
- 제약: 원본은 Three.js + React Three Fiber + TSL + WebGPU/WebGL + Lenis + canvas UI를 사용한다. 다중 FBO와 포스트프로세싱은 GPU 비용이 크며 canvas UI는 DOM 접근성을 잃는다
- 원본 스스로 지적한 한계: HTML을 캔버스 안에 다시 만들면 레이아웃·텍스트·입력·접근성을 브라우저 수준으로 재현하기 어렵다
- 변형: 기존 Astro + vanilla Three.js를 유지한다. 현재 장면과 다음 장면만, half-resolution FBO 최대 2장만 사용한다. UI와 카피는 DOM이 소유하고 WebGL은 조형물·상태 uniform만 소유한다. Lenis·R3F·uikit·WebGPU 전용 경로는 추가하지 않는다
## 합성
- 구조와 증거 순서: R1 Cognite
- 첫 화면의 시각적 무게·무장식 형태·타입 절제: R2 Polestar
- 네 현장 전환의 렌더링 문법: R3 Shader.se 선택 렌더링
- 고유 결과: 자동차 사진도 산업 SaaS 카드도 아닌, **네 현장이 하나의 코어에서 다른 작동 상태로 바뀌는 실시간 산업 조형물**
## 회색조 위계
색을 전부 제거했을 때 가장 강한 덩어리는 **네 현장 3D 코어**, 두 번째는 **한 문장 가치 제안**, 세 번째는 **현재 현장 선택과 프로젝트 문의**다.
비즈니스 우선순위 `[1 기술을 체감 / 2 어느 현장에 쓰이는지 이해 / 3 문의]`와 일치한다.
## 안 할 것
- 보라·파랑 AI 그라디언트와 빛나는 유리 카드로 기술을 표현하지 않는다
- 네 제품을 같은 크기 카드 네 장으로 반복하지 않는다
- 장식용 입자·마퀴·스크롤 가로막기·커스텀 스크롤을 넣지 않는다
- 제품 UI와 카피를 캔버스 안에 다시 만들지 않는다
- 실제 출처를 다시 검증하지 않은 수치·수상·파트너 로고를 추가하지 않는다
- 3D가 꺼졌을 때 빈 검정 사각형이 남지 않게 정적 렌더와 완성된 DOM 레이아웃을 함께 만든다
## 1단계 통과 판정
- R1/R2/R3 원본 URL: 있음
- R2 다른 업종: 확인
- 각 슬롯의 축과 변형: 기록
- 그리드·타입·면적·진행도 수치: 실제 브라우저 computed style/DOM rect로 측정
- R3 지원 범위·비용·접근성 제약: 기록
- 회색조 위계와 비즈니스 우선순위: 일치
## 2단계 · 콘셉트와 프리셋
### 한 문장 콘셉트
**정밀한 공간 계기 — 네 산업 현장이 하나의 코어 안에서 다른 물리 상태로 전환된다.**
### 커스텀 프리셋 `precision-spatial`
- 기반 문법: `swiss-minimal`의 단일 그로테스크, 중립색 90%, 엄격한 정렬, 평면 DOM UI
- 추가 문법: 첫 화면 한 곳에만 실시간 3D 코어를 두고, 나머지 섹션은 선·여백·타이포로 조용하게 유지
- 금지: 글래스 패널, 같은 크기 카드 반복, 둥근 알약형 버튼, 장식용 그라디언트, 무한 마퀴, 스크롤 가로막기
- 형태: DOM은 직각, 3D 조형물만 원형·곡면을 소유한다
- 의도적 위험: 3D 조형물이 히어로 가시 면적의 72~82%를 차지한다. 위험은 한 곳에 집중하고 카피·CTA는 네이티브 DOM으로 고정한다
### 선택한 시각안
- 기본 테마: 따뜻한 백색 스튜디오, 세라믹·티타늄 재질, 단일 적색 신호
- 어두운 시스템 테마: 흑연·건메탈 재질, 동일한 신호 역할의 호박색 대응값
- 정적 렌더: AI 이미지 생성 결과를 WebGL 불가·감소 모션·초기 로딩 폴백으로만 사용
- 실시간 장면: 네 현장 선택이 코어의 회전축, 층 간격, 신호 주기, 표면 거칠기를 바꾼다
- UI 역할: 선택·텍스트·링크·표는 HTML이 소유하고 캔버스는 의미 없는 장식으로 선언한다
### 정보 구조
1. 현장 — 가치 제안, 네 현장 선택, 대응 제품, 문의 CTA
2. 제품 — XD Hub / XD Works / XD Builder / XD Play의 역할과 기술
3. 검증된 일 — 기존 12개 프로젝트 기록
4. 회사 — 기존 수치·파트너·수상·채용 기록
5. 문의 — 이메일 CTA와 회사 정보
## 2단계 통과 판정
- 한 문장 콘셉트: 있음
- 프리셋: `precision-spatial`로 명명하고 차용·변형·금지 규칙 기록
- 와우 포인트: 첫 화면 3D 코어 한 곳
- 의도적 위험: 범위와 폴백까지 기록
- 기존 기능·정보: 네 현장 상태와 모든 공개 기록을 유지
## 3단계 · 토큰과 성능 예산
### 색 역할
| 역할 | 밝은 테마 | 어두운 테마 |
|---|---:|---:|
| page | `#E9E7E2` | `#0D0F0F` |
| surface | `#F6F4EF` | `#171A1A` |
| ink | `#151616` | `#F1F0EB` |
| muted | `#5A5954` | `#A8AAA7` |
| line | `#B8B5AE` | `#3B3E3D` |
| signal | `#B9362B` | `#D99A38` |
| signal ink | `#FFF8F0` | `#15120C` |
- 강조색은 테마별 한 역할 `signal`만 사용한다
- 링크·포커스·선택 상태는 색만이 아니라 밑줄, 선 두께, 텍스트 상태를 함께 바꾼다
### 타입
- 한 패밀리: `Pretendard Variable` + 시스템 폴백
- 본문: 17~18px, line-height 1.7, letter-spacing 0
- 소형 레이블: 12~13px, line-height 1.4, 숫자는 tabular-nums
- h1: `clamp(3rem, 1.9rem + 3.2vw, 4.5rem)`, line-height 1.04, letter-spacing `-0.018em`, 최대 2줄
- h2: `clamp(2rem, 1.75rem + 0.8vw, 2.5rem)`, line-height 1.15, letter-spacing `-0.012em`
- 한글 본문: `word-break: keep-all`, `overflow-wrap: break-word`, 25~40자 폭
### 공간·형태·모션
- 공간 기본 단위: 4px
- 주요 단계: 8 / 12 / 20 / 32 / 56 / 96 / 160px
- DOM radius: 0px. 원형은 3D 조형물과 상태 점에만 허용
- 컨트롤 최소 높이: 44px
- 지속시간: 120 / 220 / 420 / 760ms
- 이징: `cubic-bezier(.22, .75, .16, 1)`
- `prefers-reduced-motion`에서는 자동 회전·보간·스크롤 등장 효과를 중지하고 정적 렌더를 유지
### 성능 예산
- 히어로 자체 JS + 셰이더: gzip 35KB 이하
- WebGL 관련 추가 전송: gzip 200KB 이하
- 첫 화면 전체 전송: 1MB 이하
- 정적 폴백 이미지: 테마별 350KB 이하, 명시적 크기로 CLS 방지
- 첫 상호작용 가능: 3초 이하
- LCP: 2.5초 이하, CLS: 0.1 이하
- DPR: 데스크톱 최대 1.75, 모바일 최대 1.35
- 렌더 루프: 문서 비가시·히어로 화면 밖·감소 모션에서 중지
## 3단계 통과 판정
- 색·타입·공간·형태·모션 역할 토큰 정의
- 단일 서체와 단일 신호색으로 시각 문법 제한
- 3D·이미지·사용자 체감 성능 예산을 수치로 고정
- 감소 모션·WebGL 실패·모바일 DPR 폴백을 구현 전 요구사항으로 승격
## 4단계 · 구현과 콘텐츠 대응
### 공식 사이트 대응
- 회사 공개 수치: 159 projects, 42 clients, 40 crew, 4 patents
- 제품 체계: VIVEN, EduBill, XD Hub, XD Works
- 공개 작업: 49건 중 현재 홈페이지가 노출하는 12건을 이름·연도·기술 축으로 유지
- 운영 원칙: Hybrid, Continuum, Precision, Empowerment를 한국어 공식 문체로 재구성
- 최근 기록: `https://twentyoz.kr/news/111`의 2026-02-25 K기술대상 산업대상을 최상단에 추가
- 상세 페이지: 제품별 핵심 기능 4개, 기술 스택, 운영 사양, 4단계 운용 흐름, 도입 문의를 별도 실제 경로에 구현
### 3D 모델 조사와 최적화
- 선택 모델: `Scifi Drone 1.1` by Javier Martín Hidalgo
- 원본: `https://sketchfab.com/3d-models/scifi-drone-11-dd21953e81a24bd385d16eaf0c6a8ae7`
- 라이선스: CC BY 4.0. 화면 푸터와 `assets/twentyoz-field-core-LICENSE.txt`에 귀속을 남김
- 원본 ZIP 8.37MB를 glTF Transform으로 양자화·WebP 텍스처 최적화하여 최종 GLB 697,076B로 축소
- 원본 유휴 애니메이션은 코어가 화면을 배회해 정보 위계를 무너뜨리므로 재생하지 않고, 카메라 안에서 제한된 절차적 회전만 적용
### 셰이더·후처리·형태 보강
- RoomEnvironment 기반 PBR 조명, EffectComposer, 제한적 UnrealBloom, OutputPass 구성
- 마지막 합성 패스에서 미세 색수차·비네트·그레인을 적용하되 카피 대비에 영향을 주지 않음
- 절단된 오픈 링의 단면에는 cylinder end-cap 메시를 추가해 빈 내부가 보이지 않게 함
- 모델을 전면으로 이동하고 호박색 신호 링을 뒤로 분리함
- 청록색의 더 크고 얇은 스펙트럼 링을 한 겹 더 추가해 `data-glow-rings="2"`로 런타임 검증
## 5단계 · 브라우저 검증
- 전용 E2E: 122/122 assertions GREEN
- 반응형: 320 / 390 / 768 / 1440, 가로 오버플로 0
- 실제 WebGL: 모델 준비, postprocess, shader stack, 두 개 glow ring, 상태 전환 확인
- 접근성: 메인·제품 상세 라이트/다크 axe 위반 0
- 폴백: WebGL 비활성, 감소 모션, 모듈 실패에서 정적 렌더와 DOM 유지
- 성능: 코어 번들 646,152B raw / 166,057B gzip, 200KB 예산 통과
- 제품 상세: 320 / 1440 반응형·링크·스펙·axe 검증
## 6단계 · 셀프 감사와 게이트
- `integrity.mjs`: 114/114 통과
- `showcase-audit.mjs twentyoz-corp`: 320/390/768/1440 4/4 통과
- 메인 design gate: 메타, 죽은 선택자, 토큰 위생, 오버플로, h1, 수축, 리듬, 대비, 글꼴 확대, 터치, 인셋 통과
- 제품 design gate: 동일 실렌더 항목 통과. 공통 `main.css`의 죽은 선택자는 메인 게이트가 소유해 페이지 단독 오탐을 피함
- 전체 Astro build 통과
- 전체 `verify`에 트웬티온스 3D 자산, 제품 HTML, 메인·제품 design gate, 전용 L6 E2E를 편입
## 최종 판정
공식 카피와 실제 제품 구조, 라이선스가 명시된 최적화 3D, 이중 깊이 링, 셰이더·후처리, 상세 제품 경로, 폴백·접근성·성능·E2E 게이트가 하나의 배포 기준으로 연결되었다.