cyh-lab.com
← 블로그 목록으로

cyh-lab.com 개발기 · 2026-08-22

재테크 계산기 사이트를 만들면서 겪은 것들 — calc.cyh-lab.com

취득세는 주택 수·조정대상지역·매매가 구간에 따라 세율이 완전히 달라졌다. 세법 기준을 코드로 옮기고 검증한 과정을 정리했다.

작성자: cyh-lab.com 운영자

취득세 계산기를 검색할 때마다 광고가 덕지덕지 붙은 사이트가 나왔다. 계산 결과보다 배너가 더 넓은 경우도 있었다. 어차피 Next.js로 정적 사이트 만드는 게 익숙해진 김에 직접 만들었다. 연봉 실수령액, 퇴직금, 대출이자, DSR, 적금·예금 이자, 연금저축·IRP·ISA 세액공제, 취득세까지 계산기 7개를 calc.cyh-lab.com에 모았다.

계산 로직이 생각보다 복잡했다

연봉 실수령액 계산기부터 만들었는데, 단순히 세율 곱하는 계산이 아니었다. 4대보험 각각의 요율이 다르고, 건강보험은 장기요양보험료가 붙고, 소득세는 간이세액표 기준으로 구간마다 달라진다.

function calcIncomeTax(monthlyIncome: number, dependents: number): number {
  // 간이세액표 기준 적용
  const taxTable = getSimplifiedTaxTable()
  const bracket = taxTable.find(
    (b) => monthlyIncome >= b.min && monthlyIncome < b.max
  )
  if (!bracket) return 0
  return Math.max(0, bracket.base + (monthlyIncome - bracket.threshold) * bracket.rate - bracket.dependentDeduction * dependents)
}

세법 기준이 매년 바뀌기 때문에 계산식을 하드코딩하지 않고 세율 테이블을 상수로 분리했다. 기준 연도가 바뀌면 테이블만 업데이트하면 된다.

DSR 계산기는 기준을 이해하는 게 먼저였다

DSR(총부채원리금상환비율)은 단순 계산이 아니라 금융 기준 자체를 이해해야 했다. 기존 대출의 연간 원리금 상환액과 신규 대출의 연간 원리금 상환액을 합산해서 연소득으로 나누는 구조인데, 대출 종류마다 원리금 산정 방식이 다르다.

카드론이나 마이너스통장은 만기 일시상환으로 처리하고, 할부는 잔여 개월로 나눠서 계산한다. 이 기준을 금융감독원 DSR 산정 기준 문서에서 직접 확인하면서 반영했다.

function calcDSR(annualIncome: number, loans: Loan[]): number {
  const totalAnnualRepayment = loans.reduce((sum, loan) => {
    return sum + calcAnnualRepayment(loan)
  }, 0)
  return (totalAnnualRepayment / annualIncome) * 100
}

계산 결과와 함께 “현재 DSR: 38.4% (기준 40% 이하)” 식으로 판단 기준을 같이 보여주는 게 사용자한테 더 의미 있다고 생각했다.

취득세는 케이스가 많다

취득세가 제일 까다로웠다. 주택 수, 조정대상지역 여부, 매매가 구간에 따라 세율이 달라진다. 1주택자가 조정대상지역에서 6억 이하 주택을 살 때와 3주택자가 같은 걸 살 때 세율이 완전히 다르다.

type HousingCondition = {
  houseCount: number       // 취득 후 주택 수
  isRegulatedArea: boolean // 조정대상지역 여부
  price: number            // 매매가
}

function getAcquisitionTaxRate(condition: HousingCondition): number {
  const { houseCount, isRegulatedArea, price } = condition

  if (houseCount === 1) {
    if (price <= 600_000_000) return 0.01
    if (price <= 900_000_000) return 0.02
    return 0.03
  }

  if (houseCount === 2) {
    return isRegulatedArea ? 0.08 : 0.01
  }

  return isRegulatedArea ? 0.12 : 0.08
}

케이스를 정리하다 보니 함수 하나로 처리하기보다 조건별로 쪼개는 게 나중에 세율 기준이 바뀌었을 때 수정하기 쉬울 것 같아서 그렇게 구성했다.

서버 없이 전부 클라이언트에서 처리했다

charades 파티게임 사이트와 마찬가지로 서버가 없다. 모든 계산이 클라이언트에서 실행된다. 입력값이 서버로 안 나가는 구조라 민감한 재무 정보를 다루는 서비스에 더 잘 맞는다고 생각했다. Vercel 무료 플랜으로 운영하기도 편하다.

입력값이 바뀔 때마다 실시간으로 계산 결과를 업데이트했다. debounce 없이 바로 반영해도 계산이 가벼워서 문제가 없었다.

수식 검증을 어떻게 했나

계산 결과가 맞는지 확인하는 게 개발에서 제일 중요한 부분이었다. 시중 계산기 사이트 두 세 개와 직접 비교하면서 결과를 맞춰봤다. 연봉 실수령액은 국세청 근로소득세 계산 기준으로, DSR은 금감원 기준으로, 취득세는 행안부 기준으로 각각 확인했다.

몇 가지 엣지케이스에서 기준 문서와 계산식이 맞지 않는 경우가 있었는데, 대부분 세율 적용 구간 경계값 처리 문제였다.

광고 없이 만든 이유

처음 목적이 “광고 없는 깔끔한 계산기”였다. 개인적으로 쓰려고 만든 거라 수익화 목적이 아니었다. 나중에 서비스가 안정되면 애드센스를 붙이는 걸 고려할 수 있지만, 계산 결과 위아래에 배너가 붙는 건 피하고 싶다.