HTML number 입력: min·max·step과 소수 허용 방법

HTML의 input type="number"는 수량처럼 크기를 비교하거나 증감시키는 숫자를 입력받습니다. min·max는 허용 범위, step은 유효한 값의 간격을 정합니다. 소수를 허용하려면 간격과 기준값을 함께 고려해야 하며, 숫자로 보이는 전화번호·우편번호에는 일반적으로 다른 입력 형식이 적합합니다.

min·max·step의 역할

min과 max는 키보드로 범위 밖 숫자를 적는 것까지 무조건 막는 장치가 아닙니다. 잘못된 값을 입력할 수 있더라도 일반적인 폼 제출 시 유효성 검사가 제출을 막습니다. 빈 값을 허용하지 않으려면 required도 필요합니다.

step의 기준은 유효한 min이 있으면 그 값, 없으면 HTML의 유효한 value 속성, 둘 다 없으면 0입니다. 기준에서 간격의 정수 배만큼 떨어진 값이 유효합니다. 기본 간격은 1이지만 기준이 소수라면 유효한 값도 소수일 수 있으므로, 단순히 “기본값에서는 소수가 모두 금지된다”라고 이해하면 안 됩니다.

설정 유효한 값 예시 주의점
min="0" step="1" 0, 1, 2 0.5는 간격에 맞지 않습니다.
min="0" step="0.01" 1, 1.2, 1.23 1.234는 간격에 맞지 않습니다. 표시를 항상 소수 둘째 자리로 맞추는 기능은 아닙니다.
min="0" step="3" 0, 3, 6, 9 0을 기준으로 한 3의 배수입니다.
min="1" step="3" 1, 4, 7, 10 기준이 1이므로 3의 배수와 다릅니다.
step="any" 범위 안의 여러 소수 값 간격 제약을 없앱니다. 다른 범위·필수 입력 제약은 유지됩니다.

정수와 소수 입력을 함께 확인하는 예제

다음 전체 코드를 number.html로 저장해 브라우저에서 여세요. 별도 서버 없이 수량과 무게를 검증하고 전송 값과 JavaScript 숫자 값을 비교할 수 있습니다. 무게는 이 실습에서 0~100kg, 0.01kg 단위로 정했습니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>숫자 범위와 간격</title>
  <style>
    body { margin: 24px; font-family: sans-serif; }
    label { display: block; margin: 16px 0 6px; }
    input { width: 12rem; max-width: 100%; box-sizing: border-box; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
  <h1>수량과 무게 입력</h1>
  <form id="demo">
    <label for="quantity">수량 (1~10개, 1개 단위)</label>
    <input id="quantity" name="quantity" type="number"
      min="1" max="10" step="1" value="2" required>
    <label for="weight">무게 (0~100kg, 0.01kg 단위)</label>
    <input id="weight" name="weight" type="number"
      min="0" max="100" step="0.01" value="1.25" required>
    <p><button type="submit">값 확인</button>
      <button type="reset">초기화</button></p>
  </form>
  <pre id="result" aria-live="polite"></pre>
  <script>
    const form = document.querySelector('#demo');
    const quantity = document.querySelector('#quantity');
    const weight = document.querySelector('#weight');
    const result = document.querySelector('#result');
    form.addEventListener('submit', (event) => {
      event.preventDefault();
      result.textContent = JSON.stringify({
        formData: [...new FormData(form).entries()],
        numbers: { quantity: quantity.valueAsNumber, weight: weight.valueAsNumber }
      }, null, 2);
    });
    form.addEventListener('input', () => { result.textContent = ''; });
    form.addEventListener('reset', () => { result.textContent = ''; });
  </script>
</body>
</html>
  1. 초기 상태에서 값 확인을 누르면 폼 데이터에는 문자열 "2"·"1.25", numbers에는 숫자 2·1.25가 표시됩니다.
  2. 수량을 11로 바꾸어 제출하면 최댓값 검사에 걸립니다. 2.5로 바꾸면 간격 검사에 걸리고, 값을 모두 지우면 필수 입력 검사에 걸립니다. 수량을 2로 되돌립니다.
  3. 무게를 1.23으로 바꾸면 제출할 수 있지만 1.234는 간격에 맞지 않아 제출되지 않습니다. 소수점 이하 자릿수를 고정하여 표시하는 기능과 유효한 숫자 간격은 다르다는 점을 확인하세요.
  4. 수량의 step="1"만 step="3"으로 바꾸어 파일을 다시 여세요. min="1"이므로 초기값 2는 유효하지 않고 4는 유효합니다. 확인 후 step을 1로 복원합니다.
  5. 초기화를 누르면 수량 2, 무게 1.25로 돌아가며 결과가 지워집니다.

숫자만 있는 식별자와 구분하기

전화번호·우편번호·회원번호는 숫자로 계산하기보다 문자열 그대로 보존해야 하는 경우가 많습니다. 예를 들어 앞자리 0과 하이픈을 유지해야 할 수 있습니다. 전화번호에는 type="tel", 숫자 모양의 식별자에는 type="text" inputmode="numeric" 등을 검토하세요. inputmode는 키보드 종류에 대한 힌트이며 자체적인 숫자 검증 규칙은 아닙니다.

number 입력은 maxlength나 pattern으로 자리 수·정규식 패턴을 제한하는 용도가 아닙니다. 너비도 size가 아닌 CSS로 조절합니다. 브라우저에 따라 문자 입력 허용 방식, 증감 화살표, 소수 구분자 표시가 다르므로 특정 모양이나 입력 차단 동작에 의존하지 마세요.

JavaScript와 서버의 숫자 처리

input.value와 일반적인 폼 전송 값은 문자열입니다. 계산할 숫자가 필요하면 valueAsNumber를 사용할 수 있으며, 빈 값이나 숫자로 바꿀 수 없는 상태에서는 NaN이 됩니다. 빈 문자열을 무심코 Number()로 바꾸면 0이 되므로, 빈 값이 0과 다른 의미라면 먼저 구분해야 합니다.

브라우저 검증을 통과했다는 사실만으로 서버가 값을 신뢰해서는 안 됩니다. 서버에서도 숫자 형식, 유한한 값인지, 범위·간격을 확인하세요. 금액처럼 소수의 정확성이 중요한 계산에서는 JavaScript의 이진 부동소수점 오차를 고려하고, 최소 화폐 단위의 정수 또는 적절한 십진수 처리 방식을 선택해야 합니다.

속성과 기준값 규칙은 MDN number 입력 문서에서 확인할 수 있습니다.