결제수단별 수익 분석 대시보드 신규 추가
목차
revenue-analysis 영역에 새 기능을 추가했다. 결제수단별 수익을 집계해서 대시보드에 렌더링하는 기능인데, 변경 범위는 내부 클래스 1개, SQL 매퍼 1개, 뷰/스타일 1개다. 파일 수만 보면 크지 않은 작업처럼 보이지만, 쿼리 설계부터 화면 렌더링까지 레이어를 전부 건드린 작업이었음.
왜 쿼리 레벨부터 다시 설계했나
기존 화면이나 API에는 결제수단 기준으로 수익을 쪼개는 집계가 없었다. 처음엔 뷰 단에서 필터링하면 되겠다 싶었는데, 보면 볼수록 아니었음. 결제수단 분류는 집계 키가 되어야 하고, 집계 키가 달라지면 쿼리 구조 자체를 바꿔야 한다.
금융/결제 도메인에서 뷰 단 필터링으로 집계 수치를 뽑는 건 위험하다. 이미 집계된 값을 클라이언트에서 다시 더하면 소수점 처리 방식이 달라지거나, 데이터 로딩 타이밍에 따라 중간 상태가 화면에 노출될 수 있음. 정확한 수치는 DB 집계 레벨에서 한 번에 내려와야 한다. 그래서 SQL 매퍼에 새 쿼리를 작성하고, 내부 클래스에 메서드를 추가하는 방식으로 진행했다.
집계 쿼리의 핵심 구조는 이렇다:
SELECT
payment_method,
COALESCE(SUM(amount), 0) AS total_revenue,
COUNT(*) AS transaction_count
FROM orders
WHERE status = 'COMPLETED'
AND created_at BETWEEN :startDate AND :endDate
GROUP BY payment_method
ORDER BY total_revenue DESC
GROUP BY payment_method가 핵심이다. 이걸 애플리케이션 레이어에서 처리하면 페이지네이션이나 정렬 기준이 바뀔 때마다 전체를 다시 불러와야 하고, 결제수단이 늘어날수록 코드가 조건 분기로 늘어난다. DB에서 잘라서 주는 쪽이 훨씬 깔끔하고 안전함.
설계에서 실제로 고민한 것들
쿼리 작성보다 결정이 필요한 부분이 더 많았다.
실시간 갱신 여부. 결제 데이터는 실시간에 가까울수록 좋지만, 폴링을 붙이면 DB 부하가 생긴다. 이 기능은 분석용 대시보드라 수 분 단위 지연이 허용된다고 판단해서 웹소켓이나 폴링 없이 페이지 진입 시 1회 조회로 결정했음. 분석 목적 화면과 운영 모니터링 화면은 요구사항이 다르다. 혼동하면 불필요한 복잡도만 생긴다.
NULL 처리. GROUP BY 결과에서 특정 결제수단 데이터가 없으면 NULL이 반환될 수 있다. 뷰에서 그냥 렌더링하면 "NaN" 또는 공백이 나오는데, 금액 화면에서 이게 노출되면 신뢰가 깨진다. 매퍼에서 COALESCE로 처리하고, 뷰에서도 방어 로직을 추가했음. 두 레이어 모두 막는 게 맞다고 봤다. 어느 하나만 믿으면 나중에 반드시 구멍이 난다.
쿼리 실행 계획 확인. 작성 후 실행 계획을 봤다. payment_method 컬럼이 인덱스 없이 풀 스캔을 타면 데이터 증가에 따라 응답이 느려진다. 분석 대시보드는 조회 빈도가 낮더라도 실행 시간이 길면 UX에 바로 영향이 간다. 기존 인덱스로 커버 가능한지 확인하는 과정이 필요했음.
| 고려 항목 | 결정 내용 | 판단 근거 |
|---|---|---|
| 갱신 방식 | 진입 시 1회 조회 | 분석 목적, 실시간 불필요 |
| NULL 처리 | DB + 뷰 이중 방어 | 금액 화면에서 NaN 노출 방지 |
| 인덱스 | 기존 인덱스 재확인 | 신규 인덱스 없이 커버 가능 여부 판단 |
| 권한 체크 | 기존 미들웨어 재사용 | 신규 권한 로직 없이 기존 레이어 활용 |
구현 후 직접 화면에서 동작을 확인했다. 중요한 건 숫자 cross-check였다. 새 대시보드에 표시되는 합계가 기존 화면에서 보이는 전체 수익과 일치해야 함. 결제수단별로 쪼개서 더한 값 = 기존 전체 합계. 이게 맞지 않으면 집계 조건이 서로 다른 것이다.
실제로 이 cross-check가 처음에 안 맞았다. 쿼리를 다시 봤더니 기존 화면과 날짜 범위 필터 조건이 미묘하게 달랐음. BETWEEN을 쓸 때 경계값 처리 방식이 기존 쿼리와 달랐고, 거기서 오차가 발생하고 있었다. 사소해 보이지만 금액에서는 이게 직접 수치 오차로 연결된다. 발견하지 못하고 배포했으면 숫자가 조금 다른 화면 두 개가 공존했을 것임.
사내 도구를 만들다 보면 기능 하나가 화면에 버튼 하나 추가하는 것으로 끝나지 않는다는 걸 계속 체감한다. SQL 집계, 예외 처리, 화면 렌더링, 권한 체크, NULL 방어가 모두 엮여 있어서 어느 하나만 빠뜨려도 숫자가 틀리거나 특정 케이스에서 이상한 화면이 나온다. 파일 3개 수정이지만 신경 써야 할 지점은 그 몇 배다.
금융/결제 도메인에서 숫자 하나가 틀리면 신뢰가 무너질 수 있다. "대충 맞는 것 같다"로 넘어가면 반드시 나중에 다시 돌아온다. 이 도메인에서는 꼼꼼함이 기본값이어야 한다는 걸, 작업할 때마다 다시 확인하게 된다.
작업 전에 현재 동작이나 수치를 메모해두고, 수정 후에 같은 케이스로 확인하는 습관을 유지 중이다. 관련 화면이 있으면 숫자 cross-check를 빠뜨리지 않음. 커밋도 논리적으로 독립된 단위로 쪼개서 넣는 편인데, 나중에 어느 변경에서 이슈가 생겼는지 찾을 때 훨씬 수월하다. 하나의 큰 커밋보다 작은 커밋 여러 개가 디버깅 비용을 줄여준다. 메시지는 "무엇을 바꿨다"보다 "왜 바꿨는지"를 담으려고 노력한다. 나중에 git log를 볼 때 그 커밋이 왜 생겼는지 알 수 있어야 의미가 있기 때문이다.
댓글 0
첫 댓글 달아줘.