계산식을 코드가 아니라 JSON에 둔 이유

2026-07-27

지수를 만드는 코드에는 숫자가 많이 들어갑니다. 이 지표는 몇 점부터 100점인지, 저 층의 비중은 얼마인지, 어떤 값이 없을 때 무엇으로 채우는지 같은 것들입니다. 처음에는 이 숫자들이 전부 파이썬 코드 안에 있었습니다. 지금은 전부 JSON 사양 파일 안에 있고, 코드는 그 파일을 읽어서 실행만 합니다.

왜 옮겼는지, 그리고 옮겨서 무엇을 잃었는지를 적어 둡니다.

옮기기 전에 무슨 일이 있었나

문제는 계산이 두 군데에서 일어난다는 데서 시작했습니다. 서버는 매일 배치로 점수를 계산해서 저장하고, 화면의 시뮬레이터는 사용자가 슬라이더를 움직일 때마다 브라우저에서 다시 계산합니다. 둘이 같은 식을 써야 하는데, 식이 코드 안에 흩어져 있으면 한쪽만 고치는 사고가 반드시 납니다.

실제로 났습니다. 경계값 하나를 서버에서만 바꾸고 화면 쪽을 안 고쳐서, 같은 날 같은 지표가 두 화면에서 다른 점수로 보인 적이 있습니다. 버그 자체는 5분이면 고칩니다. 무서운 건 아무도 그게 틀렸다는 걸 몰랐던 기간입니다.

얻은 것 셋

하나, 계산의 원본이 한 벌이 됩니다. 사양 파일은 서버도 읽고 화면도 읽습니다. 경계값을 고치면 양쪽이 같이 바뀝니다. 한쪽만 고치는 사고가 구조적으로 불가능해집니다. 이게 옮긴 가장 큰 이유입니다.

둘, 테스트가 값 자체를 지킬 수 있게 됩니다. 코드 안에 숫자가 박혀 있으면 테스트는 함수의 동작만 검사합니다. 사양이 파일이면 테스트가 파일을 읽어서 "비중의 합이 1인가", "모든 지표에 경계값 두 개가 다 있는가", "층 이름이 정해진 셋 중 하나인가" 같은 것을 직접 검사할 수 있습니다. 이 검사들은 계산 로직과 무관하게 사양 자체의 무결성을 지킵니다.

셋, 개정 이력이 남습니다. 사양 파일은 버전 관리 아래 있으니 "이 지표 경계가 언제 왜 바뀌었나"를 되짚을 수 있습니다. 지수의 값이 과거와 달라졌을 때 그게 데이터가 바뀐 탓인지 식이 바뀐 탓인지를 구분할 수 있어야 하는데, 코드 커밋 사이에 섞여 있으면 그 구분이 안 됩니다. 사양 파일 하나만 따라가면 됩니다.

대가 셋

여기서부터가 이 글을 쓴 이유입니다. 이 방식은 공짜가 아닙니다.

하나, JSON은 변경 내역을 읽기 어렵습니다. 사양 파일 하나가 커지면 한 줄을 고쳐도 들여쓰기나 항목 순서 때문에 열 줄이 바뀐 것처럼 보입니다. 코드였다면 함수 이름과 주석이 문맥을 주는데, JSON에는 문맥이 없습니다. 그래서 사양 파일에 별도의 설명 항목을 두고, 값을 바꿀 때 그 이유를 같은 파일 안에 적도록 했습니다. 파일이 커지는 대신 나중에 자기가 왜 그랬는지 몰라서 헤매는 시간이 줄어듭니다.

둘, 스키마 검증기가 없습니다. 정식으로 하려면 JSON Schema 같은 걸 두고 사양을 기계적으로 검증해야 합니다. 지금은 테스트가 몇 가지를 직접 확인하는 수준이라 촘촘하지 않습니다. 사양에 오타로 항목 이름을 잘못 쓰면 그 지표가 조용히 빠진 채로 계산이 돌 수 있습니다. 이건 아직 남아 있는 약점입니다.

셋, 그리고 가장 중요한 것 — 사양은 "값이 무엇인가"를 정의하지 못합니다. 사양 파일은 "이 지표가 몇 점부터 100점인가"를 정할 수 있지만, "이 지표에 들어오는 값이 무엇을 세는 숫자인가"는 정하지 못합니다. 그건 수집 코드의 몫입니다. 그래서 사양이 완벽해도 들어오는 값이 틀리면 아무 소용이 없습니다.

실제로 났던 사고

세 번째 대가가 그냥 이론이 아니라는 걸 보여 주는 사례가 있습니다.

빅테크 4사의 설비투자 가이던스를 전년 대비 증가율로 환산하는 지표가 있습니다. 어느 시점에 이 값이 141.2% 로 잡혔습니다. 사양에 적힌 경계 기준으로는 당연히 만점이었고, 사양 검증도 전부 통과했습니다. 비중 합은 1이고 경계값도 다 있었으니까요.

문제는 분자와 분모가 서로 다른 것을 세고 있었다는 점이었습니다. 한쪽은 분기 가이던스를, 다른 쪽은 연간 실적을 잡고 있어서 애초에 비교 대상이 아니었습니다. 고친 뒤 값은 75.3% 가 됐습니다. 여전히 높은 수치지만 141%와 75%는 전혀 다른 이야기입니다.

이 하나 때문에 상위 숫자들이 같이 움직였습니다.

항목고치기 전고친 뒤
빅테크 capex 증가율141.2%75.3%
Thesis 코어81.075.2
종합 지수79.076.4

사양을 파일로 뺀 덕분에 이 오류가 어디서 났는지는 5분 만에 찾았습니다. 사양은 멀쩡했고 수집 코드가 틀렸다는 게 바로 보였으니까요. 하지만 사양을 파일로 뺀 것이 이 오류를 막아 주지는 않았습니다. 사양이 지킬 수 있는 것과 없는 것의 경계가 정확히 여기입니다.

그래서 남은 숙제

값이 무엇을 세는 숫자인지를 지키려면 결국 수집 단계에 검사를 걸어야 합니다. 지금은 값의 범위가 터무니없이 벗어나면 잡아내는 정도만 있습니다. 분자와 분모의 기간이 맞는지 같은 의미론적 검사는 아직 없습니다. 다음에 손볼 곳입니다.

기록해 둘 만한 건, 이 사고 이후 종합 지수의 과거 곡선이 통째로 다시 그려졌다는 점입니다. 계산식이 바뀌면 과거도 다시 계산됩니다. 그래서 어제 본 곡선과 오늘 본 곡선이 다를 수 있고, 그럴 때마다 무엇이 왜 바뀌었는지를 적어 두려고 합니다. 조용히 다시 그리는 게 제일 나쁩니다.

지수의 층 구조와 비중 이야기는 메모리 반도체 업황을 매일 0~100점으로 재는 방법에 있습니다.

#아키텍처 #설계 #사양
이전 글메모리 반도체 업황을 매일 0~100점으로 재는 방법다음 글베타와 결정계수로 메모리 종목 네 개의 흔들림을 비교해 봤습니다목록글 전체 보기
이 글의 숫자는 공개 API 실측값이거나 회사가 직접 낸 발표문에서 가져온 것입니다. 지수와 점수는 제가 만든 계산의 결과이지 사실이 아니며, 계산식은 검증 페이지에 전부 공개돼 있습니다. 투자 자문이 아니고 매매 권유도 아닙니다.