건강 관련 화면이나 사내 복지 페이지 같은 걸 만들다 보면 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보다 큰지를 먼저 걸러 주세요.