StudyDad Loop 제품을 만들며 배운 운영과 설계를 기록합니다.

FamBlend를 중심으로 실제 구현, 운영 메모, GitHub 포트폴리오를 연결해 쌓아가는 StudyDad의 작업 기록입니다.

성장과 기술/시스템 설계

운영 콘솔의 리포트 기능은 왜 생각보다 어려운가

박세식 2026. 5. 31. 12:00
반응형

데이터와 리포트 설계 시리즈 1/8

운영 콘솔에서 리포트 기능은 단순해 보인다.

사용자는 조건을 선택하고 버튼을 누른다. 잠시 뒤 엑셀 파일을 내려받는다.

겉으로 보면 "조회해서 파일로 만들면 되는 기능"처럼 보인다.

하지만 실제로 만들어보면 리포트 기능은 단순 조회 API와 다르다. 데이터 조회, 집계, 파일 생성, 작업 상태, 저장, 다운로드, 실패 처리까지 함께 설계해야 한다.

버튼 하나 뒤에 있는 일들

사용자는 하나의 버튼을 본다.

[리포트 다운로드]

하지만 시스템 내부에서는 여러 단계가 이어진다.

요청 파라미터 검증
-> 작업 생성
-> 데이터 조회
-> 집계 또는 가공
-> 엑셀 파일 생성
-> 파일 저장
-> 작업 상태 갱신
-> 다운로드 URL 제공

이 중 하나라도 실패하면 사용자는 파일을 받지 못한다.

그래서 리포트 기능은 API 하나가 아니라 작은 처리 파이프라인으로 봐야 한다.

단순 조회 API와 다른 점

일반 조회 API는 보통 빠르게 응답한다.

예를 들어 대시보드 카드나 목록 조회는 수백 ms에서 수 초 안에 끝나야 한다.

리포트 생성은 다르다.

  • 조회 범위가 넓다.
  • 여러 테이블을 조합할 수 있다.
  • 집계나 포맷팅이 필요하다.
  • 엑셀 파일 생성이 CPU와 메모리를 쓴다.
  • 결과 파일을 저장해야 한다.
  • 사용자가 기다리는 시간이 길다.

따라서 리포트 생성은 일반 조회와 같은 실행 모델에 두면 문제가 생길 수 있다.

오래 걸리는 작업은 실패 가능성도 높다

작업 시간이 길수록 실패 지점도 늘어난다.

  • DB 쿼리가 timeout 될 수 있다.
  • 메모리가 부족할 수 있다.
  • Lambda나 API Gateway timeout에 걸릴 수 있다.
  • 파일 생성 중 예외가 날 수 있다.
  • object storage 업로드가 실패할 수 있다.
  • 사용자가 중간에 브라우저를 닫을 수 있다.

짧은 API는 실패해도 다시 호출하면 된다.

하지만 오래 걸리는 리포트는 다시 호출할 때 중복 작업이나 중복 파일이 생길 수 있다.

그래서 작업 단위로 추적해야 한다.

운영자는 결과뿐 아니라 상태도 필요하다

사용자에게 중요한 것은 최종 파일이다.

하지만 운영자에게는 상태도 중요하다.

  • 요청이 접수되었는가
  • 지금 처리 중인가
  • 실패했는가
  • 왜 실패했는가
  • 언제 완료되었는가
  • 파일은 어디에 저장되었는가
  • 다시 생성할 수 있는가

이 정보가 없으면 장애 대응이 어렵다.

예를 들어 사용자가 "다운로드가 안 된다"고 말했을 때, 시스템에 작업 상태가 남아 있지 않으면 어디서 멈췄는지 알 수 없다.

리포트 기능은 데이터 품질 문제도 드러낸다

리포트는 운영 데이터의 문제를 잘 드러낸다.

화면에서는 일부 데이터만 보이지만, 리포트는 넓은 범위를 한 번에 처리한다.

그래서 다음 문제가 나타날 수 있다.

  • 누락된 값
  • 예상과 다른 상태값
  • 날짜 형식 불일치
  • 중복 데이터
  • 참조 무결성 문제
  • 과거 데이터의 예외 케이스

리포트 기능을 만들 때는 데이터가 항상 깨끗하다고 가정하면 안 된다.

파일 생성 로직에는 예외 처리와 기본값 정책이 필요하다.

리포트는 재현 가능해야 한다

리포트는 종종 업무 판단의 근거가 된다.

따라서 "언제 어떤 기준으로 생성된 파일인가"가 중요하다.

같은 조건으로 다시 생성했을 때 결과가 달라질 수 있다면 그 이유를 설명할 수 있어야 한다.

예를 들어 원천 데이터가 바뀌었기 때문인지, 쿼리 조건이 바뀌었기 때문인지, 생성 로직이 수정되었기 때문인지 구분해야 한다.

가능하면 작업 기록에 다음을 남긴다.

  • 요청자
  • 요청 조건
  • 요청 시각
  • 처리 시작/종료 시각
  • 상태
  • 실패 사유
  • 결과 파일 위치

이 정보는 감사 추적과 장애 대응에 모두 도움이 된다.

파일 저장 위치도 설계 대상이다

생성된 파일을 서버 로컬 디스크에 두면 문제가 생긴다.

  • 서버가 바뀌면 파일을 잃을 수 있다.
  • Lambda는 로컬 디스크를 영구 저장소로 쓸 수 없다.
  • 여러 인스턴스에서 접근하기 어렵다.
  • 다운로드 URL을 안정적으로 제공하기 어렵다.

그래서 결과 파일은 object storage에 두는 편이 좋다.

예를 들어:

report-downloads-bucket/
└── reports/YYYY-MM/DD/report-job-id.xlsx

파일 저장 위치는 단순 구현이 아니라 운영 설계다.

리포트 기능을 기능이 아니라 시스템으로 보기

리포트 다운로드를 하나의 버튼 기능으로 보면 동기 API로 만들고 싶어진다.

하지만 처리 흐름으로 보면 job, worker, storage, polling이 필요하다는 것이 보인다.

이 구조는 처음에는 조금 복잡해 보인다.

하지만 운영 중에는 훨씬 안정적이다.

정리

운영 콘솔의 리포트 기능은 단순 다운로드 버튼이 아니다.

시스템 입장에서는 다음을 모두 다뤄야 한다.

  • 긴 데이터 조회
  • 집계와 가공
  • 파일 생성
  • 작업 상태
  • 실패 처리
  • 결과 파일 저장
  • 다운로드 URL
  • 재시도와 감사 추적

그래서 리포트 기능은 조회 API가 아니라 비동기 작업 시스템으로 보는 편이 좋다.

사용자는 파일을 원하지만, 시스템은 작업을 관리해야 한다.

함께 볼 GitHub 저장소

반응형
Next Step 이 글은 StudyDad 작업 루프의 한 조각입니다.

글에서 정리한 생각은 GitHub의 코드와 포트폴리오로 이어지고, 일부는 FamBlend 같은 제품 실험으로 확장됩니다.