설계·구현 (개인 작업)진행중
포트폴리오 3D 데이터 흐름 장면
남한 지도 위 5개 공장의 데이터 흐름을 Three.js 장면으로 구현 — 스크롤하면 수집·검증·예측 단계를 차례로 비추고, 저사양·모션 축소 환경에서는 정적 이미지로 대체
- 남한 지도 위 다섯 사업장의 전력·연료·용수 데이터가 지도 위 통합 화면(원형 패널 링)으로 모이는 장면을 첫 화면 무대로 두고, 스크롤하면 카메라가 사업장 → 검증 게이트 → 예측 패널(실측과 P05~P95 구간)을 차례로 비추며 단계 글을 읽는 동안에는 멈춤
- 모션 축소 설정, WebGL2 미지원, 저메모리, 좁은 화면, 청크 로드 실패의 다섯 경우에 같은 구도의 정적 이미지로 대체
- 장면의 색은 CSS 토큰에서, 공장 이름은 사실 원장에서 읽어 다크 모드와 사실 변경이 장면에 그대로 반영되고, 이름과 좌표가 어긋나면 테스트가 잡음
- 삼각형 1,467개 · draw call 31회 · 3D 청크 237 KB는 지연 로드라 초기 로드에 들어가지 않고, 화면 밖에서는 렌더 루프를 멈춤
수치와 근거
- 삼각형 1,467개
- 3D 장면 한 프레임의 삼각형 수
- 지도·아이콘·패널을 캔버스 텍스처로 그려 지오메트리가 적음 · 포스터와 같은 구도 · 예산 20,000개
- 빌드 산출물 계측 2026-10-01 (스크롤 단계 무대 · 검증 게이트 · 빛기둥 · 바닥 격자)
- draw call 31회
- 3D 장면 한 프레임의 draw call 수
- 지도 전체가 텍스처 한 장(1회), 데이터 펄스 30개는 Points 하나(1회), 사업장 빛기둥 5개는 인스턴스 하나, 패널 6장 · 양면 반투명 면은 앞뒤 두 번 그림
- 빌드 산출물 계측 2026-10-01 (스크롤 단계 무대 · 검증 게이트 · 빛기둥 · 바닥 격자)
- 237 KB
- 3D 청크 크기 (gzip)
- 해안선 좌표 포함 · 초기 로드에 포함되지 않는 지연 청크 · 예산 250KB
- 빌드 산출물 계측 2026-10-01 (스크롤 단계 무대 · 검증 게이트 · 빛기둥 · 바닥 격자)
배경
2026 하반기 지원서에 "입사 후 Three.js를 학습해 설비 상태와 배치를 함께 보는 3D 원격 모니터링을 만들고 싶다"고 적었습니다. 포부만 적고 근거가 없으면 면접에서 확인할 방법이 없습니다. 그래서 같은 기술로 먼저 만들어 두기로 했습니다.
수행
무엇을 그릴지 — 장식이 아니라 업무를 보여 주는 그림이어야 했습니다. 그래서 사내 BEMS가 다루는 것, 즉 다섯 사업장의 전력·연료·용수 데이터와 실측·예측 구간(P05~P95)을 남한 지도 위에 홀로그램처럼 도식화했습니다. 사업장은 실제 위치(시 단위)에 두고, 데이터는 지도 위에 떠 있는 하나의 통합 화면(원형 패널 링) 가운데로 모입니다. 앞 패널은 실측과 예측 구간, 옆 패널은 원장에서 받은 예측 오차이고 나머지 패널은 수치 없는 장식입니다. BEMS 화면을 그대로 옮긴 것이 아니라, 무엇이 어디서 모이는지를 한 그림으로 보여 주는 도식입니다.
어떻게 그릴지
- React Three Fiber로 지오메트리를 코드에서 만듭니다. glTF 같은 외부 자산을 두지 않아 저장소가 무거워지지 않고 경로 문제도 생기지 않습니다
- 지도·공장 아이콘·이름표·패널은 캔버스 2D에 네온으로 그려 텍스처로 씁니다. 지오메트리로는 글로우를 낼 수 없어서입니다. 해안선은 Natural Earth 1:10m 공개 데이터를 0.03° 허용오차로 단순화한 좌표 배열이고, 지도 전체가 draw call 한 번입니다
- 데이터 펄스 30개(사업장 5 × 전력·연료·용수 3 × 알갱이 2)는 Points 하나로 그립니다
- 패널에 적는 수치는 원장에서 props로 받습니다. 장면 안에 수치를 적어 두지 않습니다
- 예측 구간은 앞 패널의 캔버스를 세 프레임마다 다시 그려 흐르게 해, 값 하나가 아니라 범위를 내놓는 모델이라는 점이 그림에서 읽히게 했습니다
- 색은 CSS 토큰에서 읽습니다. 다크 모드로 바뀌면 장면도 함께 바뀝니다
- 공장 이름은 사실 원장의 수치에서 읽고 위치는 좌표표에서 찾습니다. 원장을 고치면 장면도 따라오고, 원장의 이름에 좌표가 없으면 테스트가 실패합니다
스크롤 단계 (2026-10) — 장면을 첫 화면 전체 무대로 넓히고, 첫 화면 제목의 세 동사를 카메라 단계로 옮겼습니다.
- 모으고: 지도 가까이에서 다섯 사업장과 솟아오르는 원천 데이터(주황)를 비춥니다
- 자동화하고: 링 아래 검증 게이트를 내려다봅니다. 알갱이는 게이트를 지나며 표준 데이터(하늘색)로 바뀝니다. 색은 정점 색이라 draw call이 늘지 않습니다
- 예측합니다: 앞 패널의 실측선과 예측 구간을 정면에서 비춥니다
- 단계 글이 화면 가운데 있는 동안에는 카메라를 세워 두고, 단계 사이에서만 감쇠를 거쳐 옮겨 갑니다. 읽는 동안 화면이 움직이지 않게 하기 위해서입니다
- 카메라 단계는 화면 높이를 세지 않고 단계 글의 실제 위치로 정합니다. 첫 화면이 화면보다 긴 노트북·태블릿에서도 글과 장면이 어긋나지 않습니다
- 글이 놓이는 왼쪽을 비우는 일은 대상을 비껴 겨누지 않고 렌즈 이동(filmOffset)으로 합니다. 비껴 겨누면 원근이 틀어집니다
켜지 않는 조건 — 3D는 부가물이므로 다음 경우에는 아예 불러오지 않고 같은 구도로 미리 렌더한 정적 이미지를 둡니다.
| 조건 | 이유 |
|---|---|
| 모션 축소 설정 | 움직임이 불편한 사용자 |
| WebGL2 미지원 | 그릴 수 없음 |
| 기기 메모리 4GB 미만 | 끊기며 도는 것보다 안 도는 편이 낫습니다 |
| 화면 너비 720px 미만 | 배터리와 데이터를 쓸 만한 화면이 아닙니다 |
| 청크 로드 실패 | 조용히 포스터로 남습니다 |
언제 불러올지 — 본문이 먼저 그려진 뒤 유휴 시간에 불러오고, 화면 밖으로 나가면 렌더 루프를 멈춥니다.
성과
| 항목 | 값 | 예산 |
|---|---|---|
| 한 프레임 삼각형 | 삼각형 1,467개 | 20,000개 |
| 한 프레임 draw call | draw call 31회 | — |
| 3D 청크 (gzip) | 237 KB | 250 KB |
| 초기 로드에 포함 | 아니오 | — |
포스터는 밝은 화면용과 어두운 화면용을 각각 만들어, 3D를 켜지 않는 환경에서도 페이지의 색과 따로 놀지 않게 했습니다.
배운 점과 다음 개선
기능을 넣는 것보다 넣지 않을 조건을 먼저 정하는 것이 어려웠습니다. 3D는 잘못 넣으면 읽는 속도를 떨어뜨리고 내용을 가립니다. 그래서 대체 경로를 먼저 만들고 장면을 나중에 붙였습니다.
스크롤 단계를 넣을 때도 같았습니다. 이전에는 "읽는 동안 화면이 움직이면 방해가 된다"는 이유로 스크롤 카메라를 넣지 않았는데, 단계 글이 화면 가운데 있는 동안 카메라를 세워 두는 조건을 걸어 그 이유를 지킨 채 넣었습니다.
처음에는 공장 다섯 채를 호(弧) 위에 늘어놓고 가운데 원반으로 모았는데, 블록의 높이가 아무 뜻이 없는데도 뜻이 있어 보였고 알갱이가 어디로 가는지 읽히지 않았습니다. 지도 위 제자리에 세우고 길을 옅은 선으로 깔자 그림만으로 읽히게 되었습니다.
다음에는 공장을 눌렀을 때 그 공장의 실적과 예측을 옆에 띄우는 것까지 해 보려고 합니다. 실제 설비를 3D로 모니터링하는 시스템을 운영한 적은 없고, 여기까지는 포트폴리오 사이트의 시각 자료입니다.