[DATA-012][실무] 원본 표를 대시보드로 바꾸는 흐름 만들기 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[DATA-012][실무] 원본 표를 대시보드로 바꾸는 흐름 만들기

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 50회 작성일 26-09-06 17:36

본문

[이번 수업]

CSV 원천 데이터를 검사하고 채널별로 집계해 HTML 대시보드를 만듭니다. 외부 서비스 없이 검증→변환→표시→재검증 흐름을 완성합니다.

[선수지식]

DATA-002의 CSV, DATA-003의 결측치, DATA-004의 집계, DATA-007의 시각화, DATA-011의 품질을 알면 좋습니다.

[학습목표]

1. 원천 데이터의 스키마와 품질 규칙을 정한다.
2. 같은 입력에서 같은 집계 결과를 재현한다.
3. 지표 정의·출처·갱신 시각을 대시보드와 함께 관리한다.

[핵심개념]

원천 데이터는 가공 전 기록입니다. 스키마는 열 이름·자료형·허용 범위의 약속입니다. 표시 전에 필수 열과 0 이상인 주문·매출을 검사해야 잘못된 숫자의 확산을 막습니다.

파이프라인은 데이터를 단계별로 전달하는 흐름입니다. ETL은 추출·변환·적재이며 여기서는 읽기, 검증·집계, HTML 저장을 수행합니다. 같은 입력은 같은 결과를 내야 합니다. 데이터 계보는 결과와 원본·처리 규칙을 잇는 기록입니다.

지표는 계산식까지 정의합니다. 총 주문은 orders의 합, 총 매출은 revenue의 합입니다. 실제로는 취소 포함 여부·통화·시간대도 적습니다. 표에는 제목과 머리글을 넣고 색만으로 구분하지 않습니다.

[따라하기]

sales.csv를 UTF-8로 저장하세요. 개인정보가 없는 가짜 데이터입니다.
```csv
date,channel,orders,revenue
2026-09-01,web,3,36000
2026-09-01,app,2,28000
2026-09-02,web,4,46000
2026-09-02,app,1,12000
```

같은 폴더에 build_dashboard.py를 저장합니다.
```python
from collections import defaultdict
from html import escape
from pathlib import Path
import csv

with open("sales.csv", newline="", encoding="utf-8-sig") as f:
    reader = csv.DictReader(f)
    if reader.fieldnames != ["date", "channel", "orders", "revenue"]:
        raise ValueError("열 이름이 다릅니다")
    rows = list(reader)

totals = defaultdict(lambda: [0, 0])
for line, row in enumerate(rows, 2):
    orders, revenue = int(row["orders"]), int(row["revenue"])
    if min(orders, revenue) < 0 or not row["channel"].strip():
        raise ValueError(f"{line}행 오류")
    totals[row["channel"]][0] += orders
    totals[row["channel"]][1] += revenue

body = "".join(f"<tr><th>{escape(k)}</th><td>{v[0]}</td><td>{v[1]:,}</td></tr>" for k, v in sorted(totals.items()))
orders = sum(v[0] for v in totals.values())
revenue = sum(v[1] for v in totals.values())
page = f"""<!doctype html><html lang='ko'><meta charset='utf-8'><title>판매 현황</title>
<h1>판매 현황</h1><p>총 주문 {orders}건 · 총 매출 {revenue:,}원</p>
<table><caption>채널별 집계</caption><tr><th>채널</th><th>주문</th><th>매출(원)</th></tr>{body}</table></html>"""
Path("dashboard.html").write_text(page, encoding="utf-8")
print(f"완료: {len(rows)}행, 주문 {orders}건, 매출 {revenue:,}원")
```

macOS·Linux는 `python3 build_dashboard.py`, Windows는 `py build_dashboard.py`를 실행합니다. 예상 결과는 `완료: 4행, 주문 10건, 매출 122,000원`입니다. dashboard.html에는 총계와 app 3건·40,000원, web 7건·82,000원이 표시됩니다.

원본 파일명·행 수·처리 시각·규칙 버전·합계를 기록하고 원본은 덮어쓰지 않습니다. 자동화에서는 검사가 통과한 뒤에만 기존 결과를 교체합니다.

[흔한 실수]

빈 값을 0으로 바꾸거나 실패 행을 조용히 버리지 마세요. 정의와 시간대가 다른 자료를 합치지 말고 합계뿐 아니라 행 수와 채널별 값도 검증합니다.

[보안 주의]

실제 이름·연락처는 넣지 않습니다. 필요한 열만 수집하고 접근권한과 보관 기간을 정하세요. HTML 문자열은 이스케이프하며 본인 소유 로컬 파일만 씁니다.

[직접 해볼 과제]

store 채널 2행과 기대 합계를 추가하세요. revenue가 -1인 시험 파일이 실패하는지 확인한 뒤 날짜별 집계와 마지막 데이터 날짜도 표시합니다.

[확인문제]

1. 화면을 만들기 전에 스키마와 값 범위를 검사해야 하는 이유는 무엇인가요?
2. 지표 이름뿐 아니라 계산식과 포함 범위를 기록해야 하는 이유는 무엇인가요?
3. 같은 원본으로 파이프라인을 다시 실행했을 때 결과가 같아야 하는 이유는 무엇인가요?

[다음 학습]

SWE-012에서 테스트가 부족한 기존 프로그램을 안전하게 개선하는 종합 프로젝트를 진행합니다.

[공식 참고 자료]

https://www.w3.org/TR/tabular-data-model/
https://www.w3.org/TR/dwbp/
https://www.w3.org/TR/WCAG22/
https://docs.python.org/3/library/csv.html

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
4,554
어제
6,862
최대
16,772
전체
770,505
Copyright © 소유하신 도메인. All rights reserved.