Cheondi
개발 · API

차트 기록을 JSON으로 옮기며 생긴 일

차트 히스토리 데이터를 JSON으로 읽고 화면 모델로 바꾸며 데이터 계약을 다듬은 기록입니다.

  • #json
  • #chart
  • #data-contract

차트 기록 데이터를 로컬 JSON으로 받아 표시하는 작업을 했다. 샘플 파일의 배열을 역직렬화해 점을 그리면 될 것 같았다. 작은 데이터는 바로 보였지만 실제 기록을 넣자 일부 구간이 비거나 선이 화면 밖으로 뻗었다. JSON 문법은 정상인데 값의 의미를 잘못 해석하고 있었다.

시간은 초 단위와 밀리초 단위가 섞였고 가격 자릿수도 상품마다 달랐다. 파일을 읽었다는 것과 올바른 차트를 만들었다는 건 다른 성공이었다.

외부 형식과 내부 형식을 나눴다

JSON 구조를 그대로 차트 컴포넌트에 넘기지 않고 입력 DTO와 내부 포인트를 분리했다.

[Serializable]
public class CandleDto
{
    public long timestamp;
    public string open;
    public string high;
    public string low;
    public string close;
}

public record Candle(DateTimeOffset Time, decimal Open,
    decimal High, decimal Low, decimal Close);

변환 단계에서 시간 단위와 숫자 파싱 규칙을 한 번 적용했다. UI는 정규화된 Candle만 사용했다.

정상 데이터의 조건을 검사했다

고가가 저가보다 낮거나 시간이 역순인 값은 그리기 전에 발견해야 했다. 값 하나가 잘못됐다고 전체 파일을 버릴지, 해당 행만 제외할지도 정했다.

bool IsValid(Candle c) =>
    c.Low <= c.Open && c.Open <= c.High &&
    c.Low <= c.Close && c.Close <= c.High;

제외한 행의 개수와 이유는 로그에 남겼고 원본 거래 데이터처럼 민감할 수 있는 값 전문은 출력하지 않았다.

큰 파일에서는 읽는 방식도 달랐다

전체 JSON을 한 번에 문자열로 만들고 다시 객체 배열로 만들면 같은 데이터가 메모리에 여러 형태로 존재했다. 초기에는 단순한 구현을 유지하되 파일 크기와 파싱 시간을 측정했다. 화면이 멈추는 수준이 되면 청크나 스트리밍 파서를 고려할 기준을 세웠다.

차트에는 필요한 기간만 넘기고 오래된 포인트는 보관 정책에 따라 잘랐다. 성능 문제를 막연히 예상하기보다 데이터 규모를 확인한 뒤 바꿨다.

JSON은 계약의 포장일 뿐이었다

처음에는 JSON이면 플랫폼 사이에서 쉽게 주고받을 수 있다고만 생각했다. 실제 호환성을 만드는 건 필드의 의미, 단위, 누락 가능성, 정렬 순서였다. 문법이 맞아도 계약이 다르면 결과는 틀렸다.

이후 JSON 작업에서는 샘플 하나만 보지 않고 빈 배열, 잘못된 행, 큰 값, 시간 경계를 함께 확인했다. 화면에 선 하나를 그리는 작업이 데이터 계약과 검증을 배우는 계기가 됐다.