본문 바로가기
메이킹 로그와 트러블슈팅

[깡통전세 위험도 분석기 #04] NaN과 Infinity의 공포! 프론트엔드 엣지 케이스(예외 처리) 완벽 방어 가이드

by 코드메이트 2026. 4. 16.

안녕하세요! 프론트엔드 개발의 쏠쏠한 재미와 치열한 삽질의 기록을 전해드리는 웹개발 블로거입니다.

드디어 제가 개인 사이트에 야심 차게 준비 중인 '깡통전세 및 전세사기 위험도 분석기' 메이킹 로그의 마지막, 4편에 도착했습니다!

지난 1~3편을 통해 우리는 Next.js로 아키텍처를 설계하고, 억 단위 숫자에 예쁘게 콤마를 찍어주고, 부동산 경매 로직을 Tailwind CSS로 화려하게 렌더링하는 것까지 완벽하게 마쳤습니다. 화면을 띄워놓고 매매가 3억, 전세가 2억을 넣어보니 결과가 아주 기가 막히게 뜹니다. "아, 완벽해! 이제 진짜 배포만 누르면 끝이다!" 라며 승리의 커피를 마시려던 찰나였습니다.

QA(품질 테스트)를 한답시고 입력창을 지우고 장난을 치던 저는, 화면 한가운데에 떠오른 충격적인 텍스트를 보고 마시던 커피를 뿜을 뻔했습니다.

바로 종합 위험도: NaN%, 그리고 프로그레스 바가 화면을 뚫고 무한대로 뻗어나가는 Infinity의 공포를 마주한 것입니다. 오늘은 프론트엔드 개발자의 진짜 실력이 판가름 나는 곳, '사용자의 바보 같은 입력을 막아내는 예외 처리(Validation)와 UX 개선기'에 대해 아주 딥하게 썰을 풀어보겠습니다.

 

1. "매매가가 0원이라고?" 자바스크립트의 무서운 수학 시간

우리가 만든 분석기의 가장 핵심이 되는 수학 공식은 바로 '실질 부채비율(LTV) = (전세금 + 대출금) / 매매가 * 100' 입니다.

정상적인 사용자라면 매매가에 '30000(3억)'이라는 숫자를 넣겠죠. 그런데 만약 사용자가 입력창을 전부 백스페이스로 지워서 빈칸으로 만들거나, 매매가에 장난으로 '0'을 입력하면 어떻게 될까요?

다른 프로그래밍 언어에서는 0으로 나누기(Divide by Zero)를 시도하면 프로그램이 비명을 지르며 터져버립니다. 하지만 우리의 관대한(?) 자바스크립트는 앱을 죽이는 대신 기상천외한 결과값을 뱉어냅니다.

  • 100 / 0 을 계산하면 👉 Infinity (무한대) 가 나옵니다.
  • 0 / 0 을 계산하면 👉 NaN (Not a Number, 숫자가 아님) 이 나옵니다.

결과창에 Infinity%라는 기괴한 숫자가 찍히고, 막대그래프(프로그레스 바)의 가로 길이(width)가 무한대로 계산되면서 브라우저 화면 레이아웃이 완전히 박살이 나버렸습니다. 사용자는 절대 개발자의 의도대로만 움직여주지 않는다는 '엣지 케이스(Edge Case)'의 무서움을 뼈저리게 느낀 순간이었습니다.

 

자바스크립트 프론트엔드 NaN Infinity 나누기 0 에러

 

2. 철벽 방어 로직: 엣지 케이스(Edge Case) 잡아내기

이 사태를 막기 위해 저는 '방어적 프로그래밍(Defensive Programming)' 모드로 돌입했습니다. 코드가 계산을 시작하기 전에, 입력값이 수학적으로 말이 되는 숫자인지 먼저 검문소를 통과하게 만드는 것입니다.

지난번 작성했던 useEffect 내부의 계산 로직 최상단에, 아주 강력한 if 조건문을 하나 추가했습니다.

 

// (수정된 로직) 콤마를 떼고 숫자로 변환한 값들
const market = parseFloat(marketPrice.replace(/,/g, ''));
const jeonse = parseFloat(jeonsePrice.replace(/,/g, ''));
const loan = parseFloat(seniorLoan.replace(/,/g, '')) || 0;

// 🛡️ 1차 방어막: 매매가와 전세가가 제대로 된 숫자인지, 그리고 매매가가 0보다 큰지 확인!
if (!isNaN(market) && !isNaN(jeonse) && market > 0) {
  
  // 🛡️ 2차 방어막: 깡통전세의 극한, 전세금이 매매가보다 큰 말도 안 되는 상황인지 확인
  if (jeonse > market) {
    // 에러 상태를 true로 만들고 계산 중단
    setErrorMessage('전세 보증금이 매매가보다 클 수 없습니다. 숫자를 다시 확인해 주세요!');
    setLtvRatio(null);
    return; // 여기서 함수 종료!
  }

  // 위 검문소를 무사히 통과한 정상적인 값들만 아래 계산 로직을 탑니다.
  const calculatedLtv = ((jeonse + loan) / market) * 100;
  setLtvRatio(parseFloat(calculatedLtv.toFixed(1)));
  setErrorMessage(''); // 에러 메시지 초기화

} else {
  // 숫자가 아니거나 매매가가 0원이라면 아예 결과창을 빈 화면으로 리셋시킵니다.
  setLtvRatio(null);
  setIsHugPossible(null);
  setLossAmount(null);
  setIsVillaGapRisk(false);
  setErrorMessage('');
}

 

이렇게 isNaN(market)으로 숫자가 아닌 빈 문자열을 걸러내고, market > 0 이라는 조건으로 '0으로 나누기' 참사를 원천 차단했습니다. 이제 사용자가 매매가에 0을 넣거나 다 지워버리면, 결과창은 조용히 초기화 상태("가격을 입력해 주세요" 화면)로 돌아가며 에러를 뿜지 않습니다.

 

프론트엔드 폼 유효성 검사 엣지 케이스 방어 로직

 

3. 에러를 다루는 품격: 사용자 경험(UX) 개선하기

자, 앱이 터지는 것은 막았습니다. 그런데 여기서 만족한다면 삼류 개발자입니다. 사용자가 실수로 매매가 2억짜리 집에 전세금을 3억이라고 입력했다고 칩시다. 앱이 안 터지고 조용히 초기화 화면으로 돌아가버리면, 사용자는 "어? 내가 숫자 다 입력했는데 왜 계산이 안 돼? 이 사이트 고장 났네!" 하고 뒤로 가기를 눌러버릴 것입니다.

사용자가 뭔가 잘못된 행동을 했을 때는, 그 행동이 왜 잘못되었는지 아주 친절하고 명확하게 시각적으로 알려주어야 합니다. (절대 구시대적인 alert() 창을 띄워서 사용자를 깜짝 놀라게 해선 안 됩니다!)

저는 입력창 바로 아래에 붉은색 텍스트로 에러의 이유를 설명해 주는 조건부 렌더링 UI를 추가했습니다.

 

{/* 전세금 입력 인풋 영역 아래에 추가된 에러 메시지 UI */}
<div>
  <label className="block text-sm font-semibold text-gray-700 mb-2">
    전세 보증금 (단위: 만 원)
  </label>
  <input
    // ... 인풋 속성들 ...
    className={`w-full py-3 ${errorMessage ? 'border-red-500 focus:ring-red-500' : 'border-gray-200'}`}
  />
  
  {/* 에러 상태가 존재할 때만 스르륵 나타나는 빨간색 경고 문구 */}
  {errorMessage && (
    <p className="text-sm text-red-500 mt-2 font-bold animate-pulse">
      🚨 {errorMessage}
    </p>
  )}
</div>

 

이렇게 처리하니, 전세금이 매매가를 넘어서는 순간 인풋 박스의 테두리가 빨갛게 변하면서 아래에 "🚨 전세 보증금이 매매가보다 클 수 없습니다. 숫자를 다시 확인해 주세요!" 라는 문구가 부드럽게 등장합니다. 사용자는 즉시 자신의 타이핑 실수를 깨닫고 숫자를 고치게 되죠.

사용자를 화나게 하지 않으면서도, 올바른 길로 유도하는 완벽한 UX의 승리입니다!

 

리액트 사용자 경험 UX 친절한 폼 에러 메시지 UI

 

 

[전세사기 분석기 시리즈를 마치며]

총 4편에 걸친 '전세사기 위험도 분석기' 메이킹 로그 대장정이 막을 내렸습니다. 처음에 기획할 때만 해도 "그냥 더하기 빼기 해서 LTV 띄워주는 계산기 하나 만드는 건데 하루면 끝나겠지?"라고 생각했습니다.

하지만 SSR 환경의 Hydration 에러를 극복하고, 복잡한 부동산 경매 지식을 코드로 풀어내고, 마지막으로 사용자의 기상천외한 입력값(0, 널값)을 방어하는 예외 처리까지 구현하면서 프론트엔드 개발이 얼마나 섬세하고 깊이 있는 작업인지 다시 한번 깨닫게 되었습니다. 개발 시간의 20%는 기능을 만드는 데 쓰고, 나머지 80%는 에러를 막고 사용자 경험을 다듬는 데 쓴다는 말이 100% 사실이더군요.

 

제가 피땀 흘려 만든 이 코드는 제 개인 사이트의 툴(Tools) 코너에 예쁘게 포장되어 올라갈 준비를 마쳤습니다. 추후 도메인이 정식 오픈되고 애드센스 승인까지 마무리되면, 블로그를 통해 제일 먼저 접속 링크를 공유해 드리겠습니다!

그때까지 여러분의 전세금도, 여러분의 코드도 모두 버그 없이 안전하길 바랍니다. 다음에도 더 재밌고 영양가 넘치는 웹개발 트러블슈팅 스토리로 돌아오겠습니다. 감사합니다!