사이트의 시스템 로그에는 계좌 궤적 차트가 하나 있다. 2022년 1월 50만원에서 시작해 2025년 3월 1억 4,300만원에서 꼭대기를 찍는 38개월, ×286. 실제 관측치는 일곱 개다. 화면에 서 있는 점은 8,647개다. 이 글은 그 차이 — 7과 8,647 사이 — 를 정직하게 처리하는 데 한 번 실패했다가 고친 기록이다. 수치는 전부 실제 값이다.
문제 — 돈의 기록을 어떻게 그리나
재료는 표 한 장이다. 증권사 앱과 본인 기록을 교차 검증한 관측 일곱 줄.
// 관측 7점 — 전부 실제 값 (life-timeline v79). yr는 십진 연도, v는 만원.
const KNOTS = [
{ yr: 2022.04, v: 50 }, // 2022.01 첫 실거래 — 위메이드, 50만
{ yr: 2022.12, v: 30 }, // 2022.02 첫 손절 −42% — 잔고 30만
{ yr: 2022.71, v: 1400 }, // 2022.09 자본 운영 궤도 진입
{ yr: 2023.79, v: 4600 }, // 2023.10
{ yr: 2024.54, v: 11400 }, // 2024.07 복무 중
{ yr: 2025.21, v: 14300 }, // 2025.03 PEAK — 복무 중
{ yr: 2025.55, v: 14300 }, // 2025.07.21 전역 · ACTIVE=OFF
];
쉬운 답은 선 차트다. 일곱 점을 잇고 끝. 그런데 이 사이트의 법은 이미지가 데이터로 만들어져야 한다는 것이고, 선 하나는 38개월의 질량을 못 든다. 그래서 산이다. 플롯 폭 878px을 1.25px 간격의 컬럼 약 700개로 자르고, 컬럼마다 그 시점의 잔고 높이까지 파티클을 쌓는다. 컬럼당 개수는 밀도 법칙 3 + 36·(v/VMAX)^0.85를 따르고, 깊이 분포 rnd^2.1이 질량을 능선 근처로 몰아준다. 능선 6% 안쪽의 점은 밝고(알파 0.55–1.0), 가끔 2px로 굵어진다. 목업 기준 총 8,647개.
색은 세 개뿐이고 전부 사건이다. 잉크색 산체, 첫 손절의 붉은 절벽(−42%는 0–60만 스케일의 줌 인셋으로 한 번 더 확대된다), 그리고 복무 밴드 위의 능선만 애시드(#e6ff9e) — 몸은 훈련장에 있고 시스템은 가동 중이던 18개월의 표시등이다.
무작위로 허용된 것은 점의 배치뿐이고, 그마저 시드가 20220121로 박힌 LCG다. 이 계좌의 1번 이벤트가 2022년 1월이다. 이 판에서는 난수조차 출처를 댄다. 같은 산이 매번 같은 모양으로 다시 선다.

정직이 렌더링 수학이 된다 — 오버슈트 금지
컬럼마다 높이가 필요하니 일곱 점 사이를 보간해야 한다. 부드러운 곡선의 기본값은 Catmull-Rom이다. 어디서나 쓰고, 예쁘고, 매듭 사이에서 위로 부푼다. 다른 차트라면 취향 문제다. 이 차트에서는 아니다. 매듭 사이에서 곡선이 4,600만 위로 부풀면, 그 컬럼에 쌓이는 파티클은 존재한 적 없는 잔고를 렌더한 것이다. 계좌에 찍힌 적 없는 돈이 산의 질량이 된다. 그래서 Catmull-Rom은 금지됐고, Fritsch–Carlson 단조 큐빅이 들어왔다.
FC의 전부는 접선 리미터다. 매듭은 정의상 정확히 통과하고(에르미트 끝점 조건, ===로 검사한다), 구간 양끝 접선이 기울기 대비 너무 가파르면 원 위로 끌어내린다.
// Fritsch–Carlson 단조 조건 — 구간 [i, i+1]의 접선 리미터
const a = m[i] / d[i], b = m[i + 1] / d[i];
const s = a * a + b * b;
if (s > 9) { // 반지름 3의 원 밖 = 오버슈트 가능 영역
const t = 3 / Math.sqrt(s);
m[i] = t * a * d[i]; // 접선을 원 위로 사영 — 곡선은 매듭 사이
m[i + 1] = t * b * d[i]; // 구간 밖으로 나갈 수 없게 된다
}
여기에 게이트를 하나 더 세웠다. DEV 빌드에서 매듭 7점 정확 통과와 구간당 64샘플 오버슈트 0을 검사하고, 하나라도 미달이면 throw — 판이 스스로 죽는다. 능선에 질감 노이즈를 얹던 초기의 rough() 함수도 같은 이유로 은퇴했다. 관측 사이를 지어내지 않는다. 첫 관측 이전과 전역 이후의 높이는 보간이 아니라 0이다. 계좌가 없던 시간에는 산도 없다.
밀도의 유혹과 재라벨 — N 사건
목업이 다 서고 나서, 헤더에 이렇게 썼다. N=8,647 PTS · 1PT=관측. 판 위에는 SCAN COMPLETE · 8,647 PTS, 캡션에는 “점 1개 = 관측 질량, 장식 아님”. 그리고 같은 프레임의 오른쪽 여백에 통계 블록이 있었다. N_OBS 7.
한 화면 안에서 두 문장이 서로를 반박하고 있었다. 진단 패널의 판정은 한 단어였다 — 위증. 8,647은 렌더링 예산이지 관측 횟수가 아니다. “1PT=관측”이라고 쓰는 순간, 파티클 밀도가 측정의 권위를 빌려 입는다. 정확해 보이는 것과 정확한 것 사이의 거리를, 내가 만든 판이 내 이름으로 좁혀서 팔고 있었다.
수정은 라벨을 예쁘게 다듬는 게 아니라 문법을 바꾸는 것이었다. 확정된 정직 문법은 관측 7 · 렌더 8,647PT — 사실의 수와 잉크의 수를 같은 줄에서 분리 신고한다. 렌더 카운트는 하드코딩이 아니라 실제로 찍힌 점의 실측이라, 파티클 예산이 바뀌면 라벨도 따라 움직인다(아래 스크린샷의 8,803PT가 그 증거다). 판 위에는 렌더 선언 한 줄을 못 박았다: PLOT 0.0 · X:2020.01→2025.07 · 높이=잔고 · SCALE=LIN · 만원 · FC-MONOTONE. 높이만 데이터고, 스케일은 로그가 아니라 선형이고, 보간 기법까지 판 위에 신고한다. “밀도∝잔고” 문구는 은퇴, 캡션은 이렇게 끝난다 — 능선은 관측 7점을 정확 통과, 장식 아님.


빠른 스크롤러의 거짓 0 — 대기 기호
빌드는 연대순이다. 애시드 스캔라인이 2020년에서 2025년으로 지나가며 파티클이 시간 순서로 쌓이고, 전선이 2025.03을 지나는 순간 PEAK 계기가 0에서 1억 4,300만까지 480ms 동안 12단계로 카운트한다. 문제는 계기의 초기 상태였다. 빌드 전 HUD가 PEAK (복무 중) 0만을 들고 있었다.
빠르게 스크롤해서 판을 스쳐 지나가는 사람은 카운트가 시작되기 전의 화면을 본다. 그 사람에게 이 판이 마지막으로 한 말은 “정점 0만”이다. 관측된 적 없는 잔고를 그리지 않으려고 보간기까지 갈아치운 판이, 관측된 적 없는 0원을 확정 수치의 표정으로 전시하고 있었다. 오버슈트와 같은 죄, 부호만 반대다.
수정: 미빌드 상태에 확정 수치 금지. 값이 존재하기 전의 계기는 대기 기호 — 하나로 선다. 렌더 카운트도 같다 — 관측 7 · 렌더 —. 계기는 관측이 실제로 도착한 순간에만 점등한다(.live, 애시드). 침묵이 문법이다. 아직 모르는 값은 아직 모른다고 서 있는 것.

결과 — 두 속도의 도착
마지막 문제는 타이밍이다. 판이 뷰포트에 들어오기 30vh 전에 빌드가 선행 발화하므로, 도착(35% 가시) 시점에 이미 얼마가 그려져 있는지가 체감을 정한다. 수용 게이트는 하나: 도착 시 잔여 진행률 ≥30% — 도착한 사람이 산이 자라는 것을 반드시 보게 하라. 이것을 두 속도로 검사했다.
시작 파라미터는 1.2초 스윕이었다. 빠른 스크롤(800px/s)은 통과, 느린 스크롤(200px/s)은 잔여 0 — 다 끝난 산을 만난다. 스윕을 2.8초로 늘려 동결한 실측치:
- fast 800px/s → 도착 시 경과 492ms → 잔여 86.8% ✓
- slow 200px/s → 도착 시 경과 2,192ms → 잔여 34.3% ✓
측정 기준점 자체를 스크립트 하나로 단일화한 뒤의 숫자다 — 같은 판을 놓고 “잔여 0%”와 “69%”가 동시에 보고된 적이 있는데, 충돌의 원인은 판이 아니라 기준점 부재였다. 이후 이 지오메트리를 만지는 커밋은 같은 커밋에서 게이트를 재실측한다.
나머지 경계 조건. prefers-reduced-motion이면 애니메이션 없이 정착판을 한 번 그리고 끝난다 — 정지 화면 한 장으로도 관측 7점과 선언이 전부 성립한다. 판이 화면 밖으로 나가면 채널은 0Hz로 정지하고, 돌아오면 쌓다 만 지점에서 이어 쌓는다. 정착 후에는 133ms 틱마다 26개 점이 반짝이는 상시 트윙클만 남는다 — 이것도 화면 안에 있을 때만.
산은 매번 같은 모양으로 선다. 시드가 박혀 있으니까. 관측이 일곱이라는 사실도 매번 같이 선다. 라벨에 박아 놨으니까. 이 차트가 증명하려는 것은 수익률이 아니다. 일곱 번의 관측을 일곱 번이라고 말하는 데 수정이 세 번 들었다는 것 — 그게 이 판의 실제 원가다.
출처·증거
- 데이터: 본인 계좌 관측 7점 (life-timeline v79, 전 구간 교차 검증 · 증거 B)
- 보간: Fritsch–Carlson monotone cubic (1980) — 매듭 정확 통과 + 오버슈트 0, DEV 게이트로 강제
- 컴포넌트:
AccountTerrain.tsx— 시드 20220121 LCG, 밀도 법칙, 대기 기호, 2속도 게이트 전부 이 파일 - 2속도 실측: fast 800px/s 잔여 86.8% · slow 200px/s 잔여 34.3% (기준점: 단일 측정 스크립트, 커밋 주석에 동결)
- 본문 수치 전부 위 소스와 m1-particle-terrain 목업 아티팩트에서 검증됨

