불만이 180건에서 210건으로 늘었어요. 그런데 주문당 불만 비율은 18%에서 14%로 줄었어요. 보고서에 ‘불만 악화’라고 써야 할까요, ‘품질 개선’이라고 써야 할까요? 먼저 이 그래프로 결정할 질문이 상담 인력의 업무량인지, 주문 경험의 변화인지 정해야 해요. 업무량은 건수로, 주문 경험은 같은 기준의 주문 수를 분모로 한 비율로 살펴봐야 해요.
첨부 링크는 이 글의 예제 ZIP으로 연결돼요. 압축을 푼 뒤 링크에 표시된 파일을 열면 입력·코드·완성 자료를 함께 사용할 수 있어요.
이번 글에서는 온라인 주문 업무를 보고하는 담당자의 상황을 가정하고, 원자료를 확인할 수 있는 도표와 범위가 명확한 캡션을 만들어요. 아래 주문·불만 건수는 모두 합성 자료예요. 한 주문에 불만이 접수됐는지를 한 번만 세며, 한 주문의 반복 연락을 여러 건으로 세지 않는다고 정의했어요. 따라서 분자는 ‘불만 연락 수’가 아니라 ‘불만이 한 번 이상 접수된 주문 수’예요.

건수와 비율이 답하는 질문을 나눠요
원자료 CSV (ZIP: input.csv)를 먼저 보면 숫자가 함께 움직이는 이유를 알 수 있어요.
| 기간 | 불만 주문 | 전체 주문 | 불만 주문 비율 |
|---|---|---|---|
| 1월 전체 | 180 | 1,000 | 18% |
| 2월 전체 | 210 | 1,500 | 14% |
| 3월 전체 | 120 | 800 | 15% |
| 4월 1~15일 | 90 | 450 | 20% |
| 3월 1~15일 | 64 | 400 | 16% |
1월에서 2월의 불만 주문 수는 (210−180)/180×100=16.7% 늘었어요. 상담해야 할 주문의 수라는 관점에서는 증가가 맞아요. 같은 기간 주문 수는 50% 늘어서 주문당 비율은 210/1,500=14%로 내려갔어요.
18%에서 14%의 차이는 **−4퍼센트포인트(%p)**예요. 상대 변화율은 (14−18)/18×100=−22.2%이고요. ‘4% 감소’라고만 쓰면 두 뜻이 섞여요. 비율의 차이를 말할 때는 %p, 기존 값 대비 얼마나 바뀌었는지 말할 때는 %를 써요.
이 숫자만으로 서비스 품질이 좋아졌다고 확정할 수는 없어요. 상품 구성이나 불만 접수 경로가 달라졌을 수 있기 때문이에요. 여기서 안전하게 말할 수 있는 것은 정의된 주문 기준에서 불만 비율이 낮아졌고, 불만 주문의 절대 건수는 늘었다는 관측이에요.
막대의 길이에 들어간 150을 찾아봐요
잘못 읽기 쉬운 도표를 만들기 위해 건수 막대의 시작점을 0 대신 150으로 잡아 봤어요. 그러면 180건 막대의 길이는 30, 210건 막대의 길이는 60에 비례해요. 길이는 두 배인데 실제 건수는 210/180=1.167배예요. 축 숫자를 자세히 보지 않으면 변화가 훨씬 커 보일 수 있어요.

막대는 길이로 양을 비교하므로 수치 축을 0에서 시작하게 해요. 0 기준에서 작은 차이가 잘 보이지 않으면 값 표기나 점 그래프를 고려해요. 선 그래프는 시간에 따른 변화 패턴을 보여주므로 목적에 따라 0이 아닌 범위를 쓸 수 있지만, 축 범위가 읽히고 중요한 기준선을 숨기지 않아야 해요. 모든 그래프의 축을 기계적으로 같게 만드는 규칙은 아니에요. 이 구분은 Government Analysis Function의 차트 안내를 참고했어요.
15일 자료를 한 달 자료 끝에 연결하지 않아요
4월 90건과 3월 120건만 보면 25% 줄었다고 계산할 수 있어요. 하지만 4월은 절반만 관측했고 3월은 31일 전체예요. 이 계산을 월간 개선으로 표현하면 비교 기간이 빠져요. 이번에는 월 전체 자료는 1~3월 선 그래프로, 4월 자료는 전월의 같은 날짜 구간과 별도로 비교해요.
3월 1~15일은 64/400=16%, 4월 1~15일은 90/450=20%예요. 같은 15일 비교에서는 +4%p예요. 전체 월의 3월 15%와 4월 전반부 20%의 +5%p도 산술적으로는 맞지만, 같은 기간을 비교한 값으로 사용하지 않아요.


최종 캡션은 아래처럼 쓸 수 있어요.
합성 주문 자료의 월 전체 불만 주문 비율은 1월 18%, 2월 14%, 3월 15%예요. 4월은 1~15일만 확보되어 별도로 표시했어요. 4월 전반부는 90/450=20%로, 3월 같은 날짜 구간의 64/400=16%보다 4%p 높아요. 분자는 기간 내 불만이 한 번 이상 접수된 주문, 분모는 해당 기간 주문이에요.
여기서 ‘같은 15일’도 완전한 통제 조건은 아니에요. 요일 구성·휴일·상품 종류가 다를 수 있고, 주문 후 불만을 제기하기까지 시간이 걸리면 최근 주문은 관측 기간이 짧아요. 실제 자료라면 주문일 기준인지 불만 접수일 기준인지, 주문 이후 며칠까지 불만을 기다릴지 추가 정의해야 해요. 그 정의가 바뀌면 예전 숫자도 같은 기준으로 다시 계산해야 해요.
전체 비율은 낮아졌는데 두 집단 모두 나빠질 수도 있어요
분모를 확인한 다음에는 구성도 확인해요. 같은 1월 180/1,000, 2월 210/1,500을 유지하면서 집단별 합성 자료 (ZIP: subgroups.csv)를 아래처럼 나눠 봤어요. 원자료에서 추가로 발견한 고객 특성이 아니라, 전체 합계만으로는 알 수 없는 경우를 계산하려고 만든 조건이에요.
| 집단 | 1월 불만/주문 | 2월 불만/주문 | 집단 안의 변화 |
|---|---|---|---|
| 고불만군 | 160/400 = 40% | 90/200 = 45% | +5%p |
| 저불만군 | 20/600 = 3.33% | 120/1,300 = 9.23% | +5.90%p |
| 전체 | 180/1,000 = 18% | 210/1,500 = 14% | −4%p |
전체 비율은 내려갔지만 두 집단의 비율은 모두 올라갔어요. 불만 비율이 낮은 집단의 주문 비중이 60%에서 86.67%로 커졌기 때문이에요. 전체 그래프의 ‘개선’이라는 제목 하나로 집단 안의 변화를 전달할 수 없어요.
비교 질문을 ‘1월과 같은 주문 구성이었다면’으로 바꾸면, 1월 구성비 40:60을 두 달에 똑같이 적용할 수 있어요. 2월은 0.4×45 + 0.6×(120/1,300×100)=23.54%가 되고 1월 18%보다 5.54%p 높아요. 14%는 실제로 설정한 2월 합계의 비율, 23.54%는 고정된 가중치로 계산한 비교값이에요. 두 수치를 같은 관측치처럼 섞어 쓰지 않아요. 가중치를 2월로 잡거나 다른 집단을 나누면 값도 달라지므로 선택한 기준을 캡션에 적어요. 이 계산도 상품 이외의 차이를 통제한 인과효과는 아니에요.
따라서 업무량 보고에는 0에서 시작하는 건수 막대와 180·210이라는 값을, 품질 비교에는 집단별 비율의 점 그래프나 위 표를 선택할 수 있어요. 전체 추세를 한눈에 전달해야 한다면 18→14%를 유지하되 ‘구성 변화 포함’이라고 표시하고 집단별 비교를 붙여요. 두 달의 정확한 값 네 개를 대조하는 목적이면 표로 충분해요. 잘린 막대의 길이 두 배라는 인상을 점 그래프로 바꿔도 분모와 구성 문제까지 해결되지는 않아요.
조건 계산 코드 (ZIP: condition-sensitivity.py)를 실행하면 합계가 기존 CSV와 같은지, 두 집단의 비율이 모두 상승하는지, 고정 가중치 결과가 18→23.54%인지 대조한 결과 JSON (ZIP: condition-results.json)이 나와요. 그림 1·2는 원래 합계와 기간 비교를 보여주고, 이 절은 그 합계만으로 결론을 내릴 때 빠지는 조건을 보여줘요.
원자료에서 캡션까지 되짚어 확인해요
검증 코드 (ZIP: verify.py)는 Python 3.12.3 표준 라이브러리만 사용해요. 원고 폴더에서 python3 assets/verify.py와 python3 assets/condition-sensitivity.py를 차례로 실행하면 비율 결과 CSV (ZIP: results.csv)와 검증 JSON (ZIP: results.json)을 다시 만들 수 있어요. 확인 순서는 분자·분모를 읽기, 비율 재계산, %p 계산, 기간 표기 대조예요. 최종 그림에서도 1~3월만 월 전체 선에 연결돼 있는지 확인해요.
자기 자료에 적용할 때는 처음에 보고할 질문을 한 문장으로 써보세요. ‘상담 인력이 처리할 물량은 늘었나’라면 불만 주문 수뿐 아니라 연락 횟수와 건당 처리시간도 필요할 수 있어요. ‘주문 경험은 나아졌나’라면 같은 관측 창과 같은 대상의 비율이 필요하고요. 분모가 0인 기간은 비율을 0%로 만들지 말고 계산 불가로 표시해요.
자료의 품질·정의·기간 제한은 각주에만 숨기기보다 핵심 숫자 가까이에 두는 편이 좋아요. 품질과 불확실성 전달 지침에서도 비교에 영향을 주는 정의 변경 등을 표에서 명확히 밝히도록 안내해요. 부서별로 같은 비율 이름을 다르게 계산한다면 KPI 정의서부터 맞춰보세요. 원자료·계산·도표 코드는 2026년 10월 13일 Codex가 작성했고 실제 서비스의 성과를 분석한 자료는 아니에요.
예제 파일을 한 번에 받아 다시 확인해요
이 글의 입력·코드·완성 자료 ZIP을 새 폴더에 풀면 R12/README.txt, replay.py, assets 폴더가 함께 생겨요. 개별 코드 파일만 저장하면 보조 모듈이나 입력이 빠질 수 있으므로 처음에는 이 묶음을 사용하세요. R12 폴더에서 다음 명령을 실행하면 본문에 사용한 검사를 순서대로 수행해요.
python3 replay.py
확인할 결과는 **불만 비율18→14%, 구성 고정23.538…%**예요. 명령이 성공해도 이 값과 본문의 적용 범위를 함께 대조하세요. 실행 안내 (ZIP: README.txt)에 필요한 파일과 개별 명령을 적었어요. 실행 코드는 verify.py (ZIP: verify.py) · condition-sensitivity.py (ZIP: condition-sensitivity.py)에서 직접 볼 수 있어요. Python3.12의 표준 라이브러리를 사용하며, 명령이 실패하면 ZIP의 폴더 구조와 오류에 나온 파일부터 확인해요. 실제 앱 실행에 필요한 프로그램은 원래 설명을 따르세요.
설명 삽화 2장은 GPT로 생성한 개념 설명이에요. 실제 예제의 작업 화면과 실행 결과는 기존 그림·첨부 자료에서 따로 확인할 수 있어요.