대시보드 14일 추이 차트와 결제·충전 카드 버그 수정
목차
대시보드 14일 추이 차트 X축 라벨과 잔액 표기가 잘못 나오는 버그, 그리고 결제·충전 카드 UI 톤이 제각각이던 문제를 한 번에 정리했다. 변경된 파일은 뷰/스타일 2개, SQL 매퍼 1개. 숫자상으로는 작은 패치지만 금융 도메인 특성상 가볍게 넘길 수 없는 작업이었다.
뭐가 문제였나
14일 추이 차트는 기간별 잔액 변화를 시각적으로 보여주는 핵심 위젯이다. X축에 날짜 라벨이 찍히고, Y축에 잔액 추이가 그려지는 구조인데, 특정 조건에서 라벨이 밀리거나 잔액 합산 값이 틀리게 나왔다.
원인을 파고들면 SQL 매퍼 쪽에서 엣지 케이스가 빠져 있었다. 집계 쿼리가 날짜 범위를 고정 14개 행으로 보장하지 않아서, 중간에 데이터가 없는 날짜가 생기면 그 뒤 라벨 인덱스가 하나씩 밀려버리는 식이었다. 화면 렌더링 쪽에서는 이 빈 날짜를 보정하는 로직 없이 배열을 그대로 매핑하고 있었으니, SQL이 흔들리면 차트도 같이 흔들리는 구조였다.
결제·충전 카드는 기능 버그라기보다 톤 일관성 문제였다. 동일한 도메인 아래에 있는 카드인데 색상 weight나 텍스트 스타일이 제각각이어서 시각적으로 덜 정돈된 느낌을 줬다. 스타일 파일 하나 정리로 마무리됐지만, 방치하면 이후 컴포넌트 추가 때 또 분기가 생길 패턴이라 같이 끊어냈다.
수정 방향
SQL 매퍼는 날짜 시퀀스를 명시적으로 생성해서 LEFT JOIN으로 붙이는 방식으로 바꿨다. 데이터가 없는 날도 행이 반드시 존재하도록 보장하는 것이 핵심이다. 대략 이런 구조다.
-- 날짜 시퀀스를 먼저 만들고, 실제 집계 데이터를 LEFT JOIN
WITH date_series AS (
SELECT DATE(NOW() - INTERVAL n DAY) AS dt
FROM (
SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2
UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5
-- ... 13까지
) seq
)
SELECT
ds.dt,
COALESCE(SUM(t.amount), 0) AS daily_total
FROM date_series ds
LEFT JOIN transactions t
ON DATE(t.created_at) = ds.dt
AND t.status = 'completed'
GROUP BY ds.dt
ORDER BY ds.dt ASC;
이렇게 하면 거래가 한 건도 없는 날도 daily_total = 0 행이 생겨서 배열 길이가 항상 14로 고정된다. 프론트에서 인덱스 기반으로 라벨과 데이터를 매핑할 때 어긋날 여지가 없어진다.
화면 렌더링 수정은 SQL 보정에 맞춰 스크립트 매핑 로직을 단순화하는 방향이었다. 기존 코드에는 빈 날짜를 프론트에서 메꾸려는 시도가 뒤섞여 있어서 읽기도 어렵고 버그도 거기서 나왔다. 데이터 보정 책임을 DB 쪽으로 내리면 프론트는 그냥 받아서 그리기만 하면 되니 훨씬 깔끔해진다. 레이어 간 책임 분리가 실제로 유지보수 난이도를 낮춰주는 케이스였다.
버그 수정할 때 내가 따르는 흐름
증상만 고치면 반드시 다시 돌아온다는 걸 경험으로 배웠다. 특히 집계 쿼리 버그는 "이번엔 우연히 안 터진 것뿐"인 경우가 많다. 그래서 수정 전에 항상 같은 패턴이 다른 곳에도 있는지 먼저 훑는다.
이번에 체크한 항목들:
- 같은 날짜 시퀀스 패턴을 쓰는 다른 집계 쿼리가 있는지 (SQL 매퍼 전체 검색)
- 수정한 쿼리가 기존 정상 케이스, 즉 14일치 데이터가 모두 있을 때를 망가뜨리지 않는지
- 차트 위젯이 올라가 있는 모든 화면에서 실제 렌더링 확인
- 잔액 숫자를 다른 화면(거래 내역, 잔액 상세 등)과 cross-check
마지막 cross-check가 생각보다 중요하다. 집계 방식이 화면마다 미묘하게 다를 수 있어서, A 화면에서 고친 숫자가 B 화면 숫자와 맞지 않으면 둘 중 하나가 더 틀린 거다. 그 불일치를 발견하면 어느 쪽이 맞는 기준인지 먼저 정의하고, 모든 화면을 거기에 맞춰야 한다. 그냥 "각자 로직이 달라서 그래요" 하고 넘어가면 나중에 더 큰 혼란으로 돌아온다.
수정 후 검증은 버그를 직접 재현하는 방식으로 했다. "고쳤을 것 같다"는 느낌으로 넘어가지 않고, 실제로 데이터가 없는 날짜를 포함한 케이스를 만들어서 차트 라벨과 금액이 정확히 대응하는지 눈으로 확인했다.
금융·결제 도메인에서 숫자가 한 번 틀리면 사용자 신뢰가 무너진다는 건 머리로는 알면서도, 바쁠 때는 "대충 맞는 것 같다"로 넘어가고 싶은 유혹이 생긴다. 이번에도 차트 라벨 하나 밀리는 게 "그냥 시각 문제 아닌가" 싶었는데, 라벨과 데이터 인덱스가 어긋난다는 건 사용자가 보는 날짜와 실제 금액이 대응하지 않는다는 뜻이다. 가볍게 넘길 버그가 아니었다.
커밋 단위도 이번에 신경 썼다. SQL 매퍼 수정, 렌더링 로직 수정, 스타일 정리를 각각 독립 커밋으로 쪼갰다. 세 가지를 하나로 뭉치면 나중에 어느 변경이 어느 증상을 고쳤는지 추적하기 어렵고, 롤백이 필요할 때 범위도 커진다. 커밋 메시지는 "무엇을 바꿨다"보다 "왜 바꿨는지"를 담으려 했다. 6개월 뒤에 이 로그를 다시 봤을 때 컨텍스트를 복원할 수 있어야 의미가 있다.
사내 서비스는 기능 하나가 화면 버튼 하나로 끝나지 않는다는 걸 매번 다시 실감한다. SQL 집계, 상태 처리, 화면 렌더링, 스타일 정합성이 다 엮여 있어서 어느 하나만 빠뜨려도 숫자가 맞지 않거나 특정 조건에서 이상한 화면이 나온다. 엣지 케이스를 꼼꼼히 따지는 게 귀찮게 느껴지는 순간도 있는데, 같은 버그로 다시 돌아오는 시간 비용이 훨씬 크다는 걸 알기에 그냥 습관으로 굳혀두는 편이다.
댓글 0
첫 댓글 달아줘.