본문 바로가기
웹디자인 (HTML,JS)

예약 폼 입력 검증, 브라우저와 서버의 역할 나누기

by myview73188 2026. 10. 14.

예약 폼 입력 검증, 브라우저와 서버의 역할 나누기

728x90

독감 예방접종 예약이 몰리는 시기에는 예약 폼에 입력이 집중됩니다. 생년월일을 비워 보내거나, 연락처에 문자를 넣거나, 같은 요청을 여러 번 보내는 일이 실제로 자주 일어납니다. 그래서 입력값을 어디에서 어떻게 확인할지가 실무에서 자주 문제가 됩니다.

이 글에서는 HTML 폼의 JavaScript 검증을 사용성 도구로 두고, 신뢰 판단은 서버에서 다시 하는 기준을 정리합니다. 필수값·형식·길이 검증 예시와 클라이언트 검증만 믿을 때 생기는 우회 문제를 함께 봅니다. 끝까지 읽으면 자사 예약 폼을 점검할 순서를 얻을 수 있습니다.

브라우저 검증과 서버 검증은 역할이 다릅니다

브라우저의 JavaScript 검증은 사용자가 잘못 입력했을 때 바로 알려 주는 용도입니다. 제출 버튼을 누르기 전에 "연락처를 입력해 주세요"라고 안내하면 불필요한 왕복이 줄고 입력 실수도 빨리 고칠 수 있습니다. 다만 이 코드는 사용자 기기에서 실행되므로 누구든 끄거나 바꿀 수 있습니다.

서버 검증은 요청이 실제로 처리되기 전에 "이 값을 받아도 되는가"를 다시 판단하는 관문입니다. 브라우저를 거치지 않는 요청, 개발자 도구로 수정한 요청, 자동화 스크립트의 요청까지 모두 같은 기준을 통과해야 합니다. 두 검증은 중복이 아니라 목적이 다른 두 층입니다.

필수값·형식·길이는 항목별로 정의합니다

검증 규칙은 "어떻게 검사할까"보다 먼저 "이 필드가 무엇인가"를 정해야 합니다. 예방접종 예약 폼이라면 이름, 생년월일, 연락처, 접종 희망일, 접종 기관 정도가 기본 필드입니다. 필드마다 필수 여부, 허용 형식, 최대 길이를 먼저 적어 두면 화면 검증과 서버 검증이 같은 기준을 공유할 수 있습니다.

필수값

필수 여부는 서버에서 빈 문자열, 공백만 있는 값, 키 자체가 없는 요청을 모두 실패로 처리해야 합니다. 화면에 required 속성을 붙였더라도 서버는 그 요청이 화면을 거쳤다고 가정하지 않습니다. 앞뒤 공백을 제거한 뒤 길이를 확인하면 공백만 든 값이 통과하는 일을 막을 수 있습니다.

형식

연락처는 허용할 문자와 자릿수를 정규식으로 제한하고, 접종 희망일은 날짜로 파싱해 실제로 존재하는 날짜인지 확인합니다. 예를 들어 2026-02-30은 모양만 보는 정규식을 통과할 수 있지만, 날짜 파싱 단계에서 걸러집니다. 형식 검사는 모양만 확인하므로, 과거 날짜 금지나 접종 가능 기간 같은 의미 검사를 별도로 둡니다.

길이

길이 제한은 입력 칸의 maxlength만으로는 부족합니다. 요청 본문은 얼마든지 길게 보낼 수 있으므로, 서버에서 필드별 최대 길이를 넘는 값은 잘라 쓰지 말고 거부하는 쪽이 안전합니다. 임의로 자르면 사용자가 보낸 값과 저장된 값이 달라져 나중에 추적하기 어려워집니다.

클라이언트 검증만 믿으면 생기는 문제

브라우저 검증이 통과했다는 사실은 정상 사용자가 화면을 거쳐 보냈다는 뜻에 가깝습니다. 요청 값은 개발자 도구에서 숨겨진 필드를 고치거나, 제출 함수를 덮어쓰거나, 같은 주소로 직접 요청을 보내는 방식으로 쉽게 바뀔 수 있습니다.

가상의 사례입니다. 어떤 예약 페이지는 정원 확인을 JavaScript에서만 하고, 서버는 클라이언트가 보낸 남은 좌석 수를 그대로 믿고 있었습니다. 특정 시간대에 자동화된 요청이 정원을 넘겨 접수되었고, 화면에는 마감으로 보이는데 DB에는 초과 예약이 남아 있었습니다. 화면 검사가 우회되었는데 서버가 그 값을 다시 계산하지 않은 것이 원인입니다.

이 문제의 핵심은 값을 믿는 위치입니다. 서버는 "남은 좌석 수"나 "가격" 같은 값을 클라이언트에서 받더라도 판단 근거로 쓰지 말고, 자신의 DB 상태로 다시 계산해야 합니다. 같은 맥락에서 중복 제출과 재시도도 서버에서 막아야 하며, 이는 예약 API의 중복·재시도 설계와 함께 봐야 합니다.

서버가 다시 판단하는 기준을 표로 정리합니다

아래 표는 같은 항목을 두 층에서 어떻게 다루는지 정리한 것입니다. 화면에서 즉시 알려 줄 것과 서버가 최종 판단할 것을 나누어 적으면 점검 대상이 분명해집니다.

항목 브라우저(JS) 역할 서버 역할 실패 시 처리
필수값 빈 칸 안내 누락·공백 거부 400 응답과 필드명 반환
형식 입력 중 힌트 제공 정규식과 날짜 파싱 재검사 400 응답, 재입력 요청
길이 maxlength로 입력 제한 초과 시 자르지 않고 거부 400 응답, 거부 로그 기록
의미(정원·중복) 마감 여부 표시 DB 기준으로 원자적 판단 409 또는 마감 응답
권한·상태 버튼 노출 제어 세션과 소유자 확인 401 또는 403 응답

오류 메시지에는 사용자가 고칠 수 있을 만큼만 담습니다. 내부 테이블명, 스택 트레이스, 판단 로직의 세부 조건은 응답에 넣지 않습니다.

바로 해 볼 점검 순서

  1. 예약 폼의 필드 목록과 필수·형식·길이 기준을 한 장짜리 표로 만듭니다.
  2. 브라우저의 스크립트를 끈 상태에서 폼을 제출해 보고, 서버가 같은 결과를 내는지 확인합니다.
  3. 같은 엔드포인트에 빈 값, 지나치게 긴 값, 형식이 틀린 값을 직접 보내 거부되는지 봅니다. 이 테스트는 승인된 테스트 환경에서만 합니다.
  4. 정원과 중복 판단이 서버 DB 기준으로 이뤄지는지, 동시 요청이 들어와도 정원을 넘지 않는지 확인합니다.
  5. 거부된 요청을 로그로 남기고, 반복 거부 패턴을 모니터링 항목에 추가합니다.

자주 묻는 질문

서버에서 검증하면 JavaScript 검증은 필요 없나요?

필요합니다. 입력 실수를 즉시 알려 주어 사용성을 높이고, 명백히 잘못된 요청이 서버까지 가는 횟수도 줄여 줍니다. 다만 보안 통제로 취급하지 않고, 최종 판단 기준은 언제나 서버에 둡니다.

같은 검증 규칙을 화면과 서버에 두 번 쓰면 유지보수가 어렵지 않나요?

규칙 정의를 한 곳에 두고 양쪽이 참조하는 방식이 좋습니다. 공통 스키마 파일이나 검증 명세 문서를 만들어 두면 불일치를 줄일 수 있습니다. 구현 방식은 팀의 기술 스택에 맞춰 고르세요. 관련 인증 항목의 정확한 문구는 KISA와 ISMS-P 공식 안내에서 직접 확인하시기 바랍니다.

서버 검증 실패 메시지는 어디까지 보여 줘도 되나요?

어느 필드가 잘못되었는지 정도가 일반적인 기준입니다. 내부 구현이 드러나는 정보는 노출하지 않습니다. 조직별 오류 노출 기준은 내부 보안 기준서와 맞춰 정하세요.

정리

  • 브라우저 검증은 사용성을 위한 안내이고, 신뢰 판단은 서버가 다시 합니다.
  • 필수값·형식·길이·의미 검사를 필드별 명세로 정하고, 화면과 서버가 같은 기준을 씁니다.
  • 정원·중복처럼 상태가 걸린 판단은 클라이언트 값이 아니라 서버 DB 기준으로 처리합니다.

오늘 할 일: 자사 예약 폼의 필드 목록을 열고, 서버에 빈 값과 형식이 틀린 값을 직접 보내 거부되는지 테스트 환경에서 확인합니다.

728x90

댓글