건강 관련 화면이나 사내 복지 페이지 같은 걸 만들다 보면 BMI 계산기를 넣어 달라는 요청이 의외로 자주 들어옵니다. 계산 자체는 한 줄인데, 단위(cm와 m)를 헷갈리거나 키와 몸무게 자리를 바꿔 넣는 실수가 잦아서 식부터 정확히 적어 둡니다.

BMI = 체중(kg) / (키(m) × 키(m))
    = 체중 / ((키(cm) / 100)^2)

키를 cm로 입력받는 화면이 대부분이라 100으로 나눠 m로 바꾼 다음 제곱합니다. 예를 들어 키 170cm, 몸무게 65kg이면 1.7 × 1.7 = 2.89이고, 65 ÷ 2.89 ≈ 22.49가 나옵니다.

광고

판정 구간은 어떻게 나누나

아래 소스에서 쓰는 기준은 이렇습니다. 국내 의료기관 사이트에서 흔히 보는 구간이고, 해외 기준(WHO 일반 기준)은 과체중·비만 경계가 더 높게 잡혀 있어서 어느 기준을 쓸지는 화면 용도에 맞춰 정해야 합니다.

BMI 값 판정
18.5 미만 저체중
18.5 이상 23 미만 정상
23 이상 25 미만 과체중
25 이상 비만

BMI는 근육량이나 체형 차이를 반영하지 못한다는 한계가 있습니다. 그래도 키와 몸무게 두 값만으로 바로 나오기 때문에 검진이나 통계에서 여전히 가장 많이 씁니다. 화면에 결과를 보여 줄 때 "참고용 지표"라는 문구를 한 줄 붙여 두면 괜히 민원 받을 일이 줄어요.

서울의료원 건강정보 페이지의 계산기 소스

아래는 서울의료원 건강정보 사이트의 BMI 팝업 페이지 소스를 발췌한 것입니다. 입력 폼, 결과 표시 영역, 구간 막대, 식생활 안내 문구, 그리고 jQuery로 짠 계산 스크립트로 구성되어 있습니다. CSS 파일과 jQuery 라이브러리 참조는 원래 페이지 쪽에 있으므로 그대로 붙여 넣으면 스타일은 빠진 채로 보입니다.

<body>
    <div id="pop-wrap" class="green">
        <div class="pop-header">
            <h1>나의 체질량지수(BMI)</h1>
            <a href="#" id="btnClose" title="닫기">닫기</a>
        </div>
        <div class="pop-body">
            <div class="message-box">
                <span>체질량지수는 자신의 몸무게(kg)를 키의 제곱(m)으로 나눈 값입니다.<br />
                    체질량지수는 근육량, 유전적 원인, 다른 개인적 차이를 반영하지 못하는 단점이 있음에도 불구하고<br />
                    조사자들이나 의료인들이 가장 많이 쓰는 방법 중 하나입니다.</span>
            </div>
            <div class="form">
                <form id="bmiCheckForm" name="bmiCheckForm">
                    <label for="">신장</label>
                    <input type="text" id="length" name="length" /><span>cm</span>
                    <span class="dash">/</span>
                    <label for="">체중</label>
                    <input type="text" id="weight" name="weight" /><span>kg</span>
                    <span class="compute">
                        <input type="button" id="btnCalc" value="계산" />
                        <input type="reset" value="초기화" />
                    </span>
                </form>
                <dl class="clearfix">
                    <dt>비만도 결과</dt>
                    <dd id="resultText"></dd>
                    <dt>BMI 지수</dt>
                    <dd id="bmiNumber"></dd>
                </dl>
                <ul>
                    <li>
                        <label>BMI</label><label class="dv1">18.5</label><label class="dv2">23</label><label>25.00</label>
                        <ul class="clearfix">
                            <li class="low-weight">저체중</li>
                            <li class="regular">정상</li>
                            <li class="overweight">과체중</li>
                            <li class="obesity">비만</li>
                        </ul>
                        <label>체중</label>
                    </li>
                </ul>
            </div>
            <h3>올바른 식생활 지침</h3>
            <h4>제때에</h4>
            <p>신체리듬에 맞춰 규칙적으로 식사하는 것은 아주 중요합니다. 특히 아침을 거르지 맙시다.</p>
            <h4>골고루</h4>
            <p>다양한 식품을 선택해 부족한 영양소가 없도록 해야 합니다.</p>
            <h4>알맞게</h4>
            <p>표준 체중을 유지하기 위해 하루에 필요한 적정열량을 섭취하는 것은 비만과 성인병을 예방하는 기본 노력입니다.</p>
            <h4>싱겁게</h4>
            <p>소금의 과잉 섭취는 고혈압을 비롯한 순환기계질환의 중요 요인이 됩니다. 건강을 위해 소금 섭취를 하루에 5g이하로 줄입시다.</p>
            <h4>즐겁게</h4>
            <p class="last">식사는 가능한 여럿이 함께 하는 것이 좋습니다. 가족끼리 즐겁게 하는 식사는 그 자체가 즐거움이고, 성인병 관리입니다.</p>
        </div>
    </div>
    <script type="text/javascript">
        $().ready(function() {
            this.title = $(".pop-header h1").text();

            $("#btnClose").click(function() {
                window.close();
            });

            $("#btnCalc").click(function() {
                if ($("#length").val() == "") {
                    alert("신장을 입력해주세요");
                    return false;
                }
                if ($("#weight").val() == "") {
                    alert("체중을 입력해주세요");
                    return false;
                }
                var len = parseFloat($('#length').val()) / 100;
                var wet = parseFloat($('#weight').val());
                var result = parseFloat(wet) / parseFloat(len * len);
                var resultText = "";
                if (result < 18.5) {
                    resultText = "저체중";
                } else if (result < 23) {
                    resultText = "정상";
                } else if (result < 25) {
                    resultText = "과체중";
                } else {
                    resultText = "비만";
                }
                resultText += " 입니다.";

                $("#bmiNumber").text(result.toString().match(/^.*\.\d{2}/) || result);
                $("#resultText").text(resultText);
            });

            $(":reset").click(function() {
                $("#bmiNumber").text("");
                $("#resultText").text("");
            });
        });
    </script>
</body>

스크립트에서 눈여겨볼 부분이 몇 군데 있습니다. 먼저 len에서 cm를 m로 바꾸고, 판정은 if ... else if 를 작은 값부터 차례로 비교하는 방식이라 경계값 처리가 깔끔합니다. 23.0이면 "정상" 조건(< 23)에 안 걸리고 바로 "과체중"으로 넘어가죠.

소수점 표시는 toString().match(/^.*\.\d{2}/) 로 처리하는데, 이건 반올림이 아니라 소수 둘째 자리에서 잘라내는 방식입니다. 22.4913이면 22.49, 22.499면 반올림했을 때와 달리 22.49가 됩니다. 소수 부분이 아예 없거나 한 자리뿐이면 정규식이 매칭되지 않아 || result 쪽 원래 값이 그대로 찍힙니다. 반올림 결과가 필요하면 result.toFixed(2) 로 바꾸는 편이 낫습니다.

빈 칸만 검사하고 숫자 여부는 확인하지 않는다는 점도 기억해 두세요. "abc"를 넣으면 parseFloat 가 NaN 을 돌려주고, 판정은 모든 비교가 거짓이 되어 "비만 입니다."가 나옵니다. 실제 서비스에 쓸 거라면 isNaN 검사를 하나 넣어 두는 게 안전합니다. 그리고 $().ready(...) 는 예전 jQuery 문법이라 최신 버전에서는 $(function() { ... }) 형태로 쓰는 걸 권장합니다.

VB.NET으로 옮기면

같은 판정 로직을 윈폼 프로그램에 넣을 일이 있어서 VB.NET 함수로도 적어 둡니다. 위 자바스크립트와 같은 기준이고, 반올림은 Math.Round 로 처리했습니다.

Public Function GetBmi(heightCm As Double, weightKg As Double) As Double
    Dim m As Double = heightCm / 100
    Return weightKg / (m * m)
End Function

Public Function GetBmiText(bmi As Double) As String
    If bmi < 18.5 Then
        Return "저체중"
    ElseIf bmi < 23 Then
        Return "정상"
    ElseIf bmi < 25 Then
        Return "과체중"
    Else
        Return "비만"
    End If
End Function

' 사용 예
' Dim bmi = GetBmi(170, 65)
' Label1.Text = Math.Round(bmi, 2).ToString() & " / " & GetBmiText(bmi)

키 입력값이 0이면 0으로 나누게 되니, 텍스트박스 값을 받을 때 Double.TryParse 로 숫자인지와 0보다 큰지를 먼저 걸러 주세요.

참고: 서울의료원 건강정보 - 나의 체질량지수(BMI)