달성률, 전환율, 마진율처럼 보고서에는 비율이 정말 많이 나옵니다. 비율은 나눗셈이고, 나눗셈에는 늘 같은 문제가 따라옵니다. 분모가 0이거나 비어 있으면 어떻게 하느냐는 것입니다. 앞선 글들에서 비율을 구할 때마다 슬쩍 사용했던 DIVIDE가 바로 이 문제를 다루는 함수입니다. 이 글에서는 DIVIDE의 문법과 동작, 나누기 연산자(/)와 무엇이 다른지, 그리고 실무에서 자주 만나는 세 가지 상황(달성률, 전환율, 합계 줄의 비율)을 같은 데이터로 정리합니다.
문법
DIVIDE( <분자>, <분모> [, <대체값>] )
Microsoft 문서의 설명대로 DIVIDE는 나눗셈을 하고, 0으로 나누는 경우에는 대체값이나 빈 값(BLANK)을 돌려줍니다. 세 번째 인수인 대체값은 생략할 수 있고, 생략하면 기본값이 BLANK입니다. 반환값은 소수 형태의 숫자입니다. 문서가 드는 예는 세 가지입니다. DIVIDE(5, 2)는 2.5, DIVIDE(5, 0)은 빈 값, DIVIDE(5, 0, 1)은 1입니다.
한 가지 제약이 있습니다. 대체값은 상수여야 합니다. 다른 측정값이나 계산식을 대체값 자리에 넣을 수 없다고 Microsoft 문서가 명시합니다.
Power BI Desktop에서 측정값으로 만들기
메뉴 이름은 Power BI 버전과 언어 설정에 따라 조금 다를 수 있다는 점을 먼저 말씀드립니다. 일반적인 순서는 이렇습니다.
- 보고서 보기에서 오른쪽 필드 창의 테이블(예: 지역성과)을 선택합니다.
- 상단 리본에서 “새 측정값”(영문판은 New measure)을 누릅니다.
- 수식 입력줄에
달성률 = DIVIDE( [총매출], [총목표] )처럼 이름과 식을 적고 Enter를 누릅니다. - 만든 측정값을 표 시각화에 올리고, 서식을 백분율로 바꿔 줄마다 값이 어떻게 나오는지 확인합니다.
예제 데이터
설명하려고 만든 가상 데이터입니다. 대구는 방문자가 0명이고, 광주는 목표가 비어 있습니다. 결과는 Power BI에서 돌린 화면이 아니라 직접 구한 값이니, 같은 식을 본인 데이터에 적용해서 확인해 보세요.
| 지역 | 매출 | 목표 | 방문자 | 구매자 |
|---|---|---|---|---|
| 서울 | 300 | 250 | 100 | 20 |
| 부산 | 120 | 200 | 80 | 8 |
| 대구 | 0 | 100 | 0 | 0 |
| 광주 | 50 | (빈 값) | 40 | 4 |
총매출 = SUM( 지역성과[매출] )
총목표 = SUM( 지역성과[목표] )
총방문자 = SUM( 지역성과[방문자] )
총구매자 = SUM( 지역성과[구매자] )
실무 시나리오 1: 목표 달성률
달성률 = DIVIDE( [총매출], [총목표] )
| 지역 | 총매출 | 총목표 | 달성률 |
|---|---|---|---|
| 서울 | 300 | 250 | 120% |
| 부산 | 120 | 200 | 60% |
| 대구 | 0 | 100 | 0% |
| 광주 | 50 | (빈 값) | (빈 값) |
서울은 300 ÷ 250 = 120%, 부산은 120 ÷ 200 = 60%입니다. 대구는 매출이 0이고 목표가 100이니 0 ÷ 100 = 0%로 계산됩니다. 분자가 0인 것은 문제가 아니고, 분모가 0일 때만 DIVIDE의 특별한 처리가 필요합니다. 광주는 목표가 비어 있어서, 분모가 빈 값이라 결과도 빈 값입니다. SQLBI는 대체값을 주지 않았을 때 분모가 0이거나 빈 값이면 DIVIDE가 빈 값을 돌려준다고 설명합니다. “목표가 없는 지역의 달성률”은 숫자로 표현할 수 없으니 빈 값으로 두는 것이 대개는 자연스럽습니다.
실무 시나리오 2: 전환율과 0/0
전환율 = DIVIDE( [총구매자], [총방문자] )
| 지역 | 총방문자 | 총구매자 | 전환율 |
|---|---|---|---|
| 서울 | 100 | 20 | 20% |
| 부산 | 80 | 8 | 10% |
| 대구 | 0 | 0 | (빈 값) |
| 광주 | 40 | 4 | 10% |
대구는 방문자도 0명이고 구매자도 0명이라 0 ÷ 0이 됩니다. 나누기 연산자(/)로 이 식을 쓰면 문제가 생깁니다. DAX Guide와 SQLBI는 연산자가 0으로 나누면 오류가 아니라 분자의 부호에 따라 양의 무한대나 음의 무한대를, 0 ÷ 0은 NaN(숫자가 아님)을 돌려준다고 설명합니다. 보고서에 “Infinity”, “NaN” 같은 글자가 그대로 나타나는 일이 생기는 것이죠. DIVIDE를 쓰면 그 자리가 깔끔하게 빈 값이 됩니다.
빈 값 대신 0%로 보여주고 싶다면 세 번째 인수를 씁니다.
전환율_0표시 = DIVIDE( [총구매자], [총방문자], 0 )
이렇게 하면 대구가 0%로 나옵니다. 다만 “방문자가 아예 없는 지역”을 0%로 보여주는 것이 맞는지는 생각해 봐야 합니다. 방문자가 없어서 전환율을 구할 수 없는 것과 방문자가 있었는데 아무도 사지 않아 0%인 것은 다른 상황이기 때문입니다. SQLBI는 빈 값 대신 0을 보여줄 때 데이터가 없는 항목까지 줄이 늘어나는 부작용이 있다고 설명하기도 합니다. 질문의 성격에 따라 정하세요.
실무 시나리오 3: 합계 줄의 비율
합계 줄은 각 줄의 값을 평균한 것이 아니라, 필터 없이 분자와 분모를 각각 합한 뒤 나눈 값입니다. 앞선 AVERAGE 함수 글에서 본 “합계 줄은 필터 없이 새로 계산한 값”이라는 원리와 같습니다. 이 예제에서 합계를 확인해 보겠습니다.
| 구분 | 총매출 | 총목표 | 달성률 | 총방문자 | 총구매자 | 전환율 |
|---|---|---|---|---|---|---|
| 합계 | 470 | 550 | 85.5% | 220 | 32 | 14.5% |
총매출은 300 + 120 + 0 + 50 = 470이고, 총목표는 250 + 200 + 100 = 550입니다(광주의 빈 값은 합계에서 건너뜁니다). 달성률은 470 ÷ 550 = 약 85.5%입니다. 그런데 여기에는 함정이 있습니다. 광주는 목표가 없는데 매출 50은 분자에 들어 있습니다. 목표가 있는 지역끼리만 비교하면 (300 + 120 + 0) ÷ 550 = 약 76.4%입니다. 합계 줄의 85.5%는 광주의 매출이 달성률을 부풀린 값입니다. 분자와 분모가 같은 대상을 가리키는지 확인하는 것은 DIVIDE가 해 주지 않습니다.
전환율의 합계는 구매자 32 ÷ 방문자 220 = 약 14.5%입니다. 줄별 전환율(20%, 10%, 빈 값, 10%)을 평균한 값(약 13.3%)과 다릅니다. 방문자가 많은 서울의 비중이 더 크게 반영되기 때문이고, 보통은 합계 줄 값이 실제 전체 전환율에 해당합니다.
DIVIDE와 나누기 연산자(/), 무엇을 쓸까
| 상황 | 쓸 방법 |
|---|---|
| 분모가 측정값이나 열이라 0이나 빈 값이 나올 수 있다 | DIVIDE |
| 분모가 상수다 (예: 천 단위로 변환하려고 1000으로 나눔) | 연산자 / |
| 0일 때 빈 값 대신 특정 값이 필요하다 | DIVIDE( …, …, 상수 ) |
| 분모가 절대 0이 될 수 없다는 것을 알고 있다 | 연산자 /도 가능 |
SQLBI는 분모가 0이나 빈 값이 될 수 있는 식에는 DIVIDE를 쓰고, 분모가 상수라면 연산자를 쓰라고 권합니다. 성능 면에서는 두 가지가 함께 언급됩니다. DIVIDE는 분모가 0인지 IF로 검사하는 것보다 빠르게 최적화되어 있지만, 항상 수식 엔진(formula engine)에서 실행되기 때문에 단순한 나누기 연산자보다는 느릴 수 있다고 DAX Guide가 설명합니다. 그러니 “무조건 DIVIDE”가 아니라 “0이 나올 수 있는 분모에만 DIVIDE”로 기억해 두면 됩니다. Microsoft 문서도 DIVIDE와 연산자의 선택 기준을 따로 다룬 모범 사례 문서를 안내합니다.
IF로 직접 검사하면 이렇게 길어집니다
DIVIDE가 없던 시절의 방식이자 지금도 종종 보이는 식은 분모를 직접 검사하는 것입니다.
전환율_IF =
IF(
[총방문자] = 0 || ISBLANK( [총방문자] ),
BLANK(),
[총구매자] / [총방문자]
)
결과는 DIVIDE( [총구매자], [총방문자] )와 같지만 식이 길고 분모 측정값을 두세 번 계산하게 됩니다. 앞서 소개한 것처럼 DAX Guide와 SQLBI는 DIVIDE가 이런 IF 검사보다 빠르게 최적화되어 있다고 설명하니, 특별한 이유가 없다면 DIVIDE로 바꾸는 편이 읽기에도 낫습니다.
쓰지 말아야 할 때
- 분모가 상수일 때: 불필요하게 수식 엔진을 거치게 하지 말고 연산자를 쓰세요.
- 대체값 자리에 측정값이나 식을 넣고 싶을 때: 상수만 가능합니다. 필요하면 IF 같은 다른 방식으로 풀어야 합니다.
- 정수 나눗셈의 몫이 필요할 때: 몫만 구하는 함수(QUOTIENT)가 따로 있습니다.
알아둘 점
- 대체값은 상수여야 합니다. 생략하면 BLANK입니다.
- 분모가 빈 값일 때도 대체값을 주지 않으면 빈 값이 반환됩니다.
- DAX Guide는 DIVIDE가 DirectQuery의 측정값과 계산 열에서 지원된다고 안내합니다.
- 결과는 소수라서 보고서에서는 백분율 서식을 따로 적용해야 합니다.
- 지역 설정에 따라 인수 구분자가 쉼표 대신 세미콜론일 수 있습니다. 식을 붙여 넣었는데 오류가 난다면 먼저 확인해 보세요.
자주 하는 실수
- 분모가 빈 값이거나 0일 때 오류를 막으려고 IF로 감쌈: DIVIDE가 더 간결하고 빠르게 최적화되어 있습니다.
- 0일 때 0을 보여주려고 무조건 세 번째 인수에 0을 넣음: “계산할 수 없음”과 “실제로 0″이 섞입니다.
- 합계 줄의 비율을 줄별 비율의 평균으로 이해: 합계 줄은 분자와 분모를 각각 합한 뒤 나눈 값입니다.
- 분자와 분모의 기준이 다름: 광주 예시처럼 한쪽에만 값이 있으면 비율이 왜곡됩니다.
비슷한 함수
- QUOTIENT: 나눗셈의 정수 몫을 돌려줍니다.
- IFERROR: 오류가 나면 지정한 값을 돌려줍니다. DIVIDE와 달리 모든 종류의 오류를 가립니다.
- IF: 분모를 직접 검사하는 방식. DIVIDE보다 길고 느릴 수 있습니다.
정리
DIVIDE는 “나누되, 분모가 0이거나 비어 있으면 안전하게 처리한다”는 한 문장으로 요약됩니다. 분모가 0이나 빈 값이 될 수 있다면 DIVIDE를, 상수로 나눈다면 연산자를 쓰고, 합계 줄의 비율은 분자와 분모를 각각 합한 뒤 나눈 값이라는 점, 그리고 분자와 분모가 같은 대상을 가리키는지는 스스로 확인해야 한다는 점을 기억해 두세요. 예제는 가상 데이터이니 본인 모델의 열 이름으로 바꿔 직접 확인해 보시고, 동작은 버전에 따라 다를 수 있어 공식 문서도 함께 보시길 권합니다.
참고한 자료
- Microsoft Learn, DIVIDE function (DAX): https://learn.microsoft.com/en-us/dax/divide-function-dax
- Microsoft Learn, DIVIDE function vs. divide operator (/) in DAX: https://learn.microsoft.com/en-us/dax/best-practices/dax-divide-function-operator
- DAX Guide, DIVIDE: https://dax.guide/divide/
- SQLBI, DIVIDE vs division operator in DAX: https://www.sqlbi.com/blog/marco/2014/07/24/divide-vs-division-operator-in-dax/
- SQLBI, DIVIDE Performance: https://www.sqlbi.com/articles/divide-performance/