はじめに — 確定申告の季節が来るたびに胃が痛い
フリーランス2年目の確定申告で、自分は完全にパニックになった。
1年目は開業届を出すのが精一杯で、経費の仕分けもろくにやってなかった。いざ申告の時期になって「所得税ってどう計算するんだっけ」「住民税は?」「国保って所得で変わるの?」と調べ始めたら、計算式が4種類もあって頭がバグった。
所得税、住民税、個人事業税、国民健康保険。それぞれ計算ロジックが違うし、控除の種類も違う。しかも毎年微妙に税率や控除額が変わる。Excelで管理しようとして3回挫折した。
結局「もう自分で計算ツール作るしかない」と思い立って、Next.jsで税金シミュレーターを作った話を書く。
そもそも何を計算する必要があるのか
フリーランスが把握すべき税金・社会保険料は主に4つ。
| 項目 | 概要 | 計算の厄介さ |
|---|---|---|
| 所得税 | 累進課税。課税所得に応じて5%〜45% | 控除が多くて課税所得の算出が面倒 |
| 住民税 | 一律10%(都道府県4% + 市区町村6%)+ 均等割 | 所得税と控除額が微妙に違う |
| 個人事業税 | 業種によって3〜5%。290万円の事業主控除あり | 対象業種かどうかの判定が必要 |
| 国民健康保険 | 自治体ごとに料率が違う。所得割+均等割+平等割 | 自治体によって計算式がバラバラ |
これを毎回手計算するのは現実的じゃない。特に「売上がこれくらいだったら手取りいくらになるのか」をサクッと知りたい場面が多い。見積もり段階で「この案件受けたら税金いくら増えるんだろう」とか。
計算ロジックの実装
所得税の累進課税テーブル
まず所得税。これが一番ややこしい。日本の所得税は超過累進税率で、課税所得の金額によって税率が段階的に上がる。
// 令和5年分以降の所得税率テーブル
interface TaxBracket {
min: number;
max: number;
rate: number;
deduction: number;
}
const INCOME_TAX_BRACKETS: TaxBracket[] = [
{ min: 0, max: 1_949_999, rate: 0.05, deduction: 0 },
{ min: 1_950_000, max: 3_299_999, rate: 0.10, deduction: 97_500 },
{ min: 3_300_000, max: 6_949_999, rate: 0.20, deduction: 427_500 },
{ min: 6_950_000, max: 8_999_999, rate: 0.23, deduction: 636_000 },
{ min: 9_000_000, max: 17_999_999, rate: 0.33, deduction: 1_536_000 },
{ min: 18_000_000, max: 39_999_999, rate: 0.40, deduction: 2_796_000 },
{ min: 40_000_000, max: Infinity, rate: 0.45, deduction: 4_796_000 },
];
function calcIncomeTax(taxableIncome: number): number {
if (taxableIncome <= 0) return 0;
const bracket = INCOME_TAX_BRACKETS.find(
b => taxableIncome >= b.min && taxableIncome <= b.max
);
if (!bracket) return 0;
// 基本の所得税額
const baseTax = Math.floor(taxableIncome * bracket.rate - bracket.deduction);
// 復興特別所得税(2.1%)を加算
const reconstructionTax = Math.floor(baseTax * 0.021);
return baseTax + reconstructionTax;
}
ポイントは deduction(控除額)をテーブルに持たせているところ。超過累進課税は本来「各段階ごとに税額を計算して合算」するんだけど、控除額を使えば一発で計算できる。国税庁の速算表と同じ方式。
復興特別所得税の2.1%上乗せも忘れがち。2037年まで続く。
控除額の計算
課税所得を出すには、収入から経費と各種控除を引く必要がある。青色申告特別控除とか基礎控除とか、積み上げていく。
interface DeductionInput {
revenue: number; // 売上
expenses: number; // 経費
blueFormDeduction: boolean; // 青色申告か
iDeCoMonthly: number; // iDeCo月額
socialInsurance: number; // 社会保険料(国保+年金)
medicalExpenses: number; // 医療費
dependents: number; // 扶養人数
}
function calcTaxableIncome(input: DeductionInput): number {
const { revenue, expenses, blueFormDeduction, iDeCoMonthly,
socialInsurance, medicalExpenses, dependents } = input;
// 事業所得
const businessIncome = revenue - expenses;
// 青色申告特別控除(e-Tax + 電子帳簿保存で65万)
const blueDeduction = blueFormDeduction ? 650_000 : 0;
// 基礎控除(合計所得2,400万以下で48万)
const basicDeduction = businessIncome <= 24_000_000 ? 480_000 : 0;
// 社会保険料控除(全額控除)
const socialDeduction = socialInsurance;
// 小規模企業共済等掛金控除(iDeCo)
const iDeCoDeduction = iDeCoMonthly * 12;
// 医療費控除(10万円超の部分、上限200万)
const medicalDeduction = Math.min(
Math.max(medicalExpenses - 100_000, 0),
2_000_000
);
// 扶養控除(一般38万、特定63万は簡略化して38万で計算)
const dependentDeduction = dependents * 380_000;
const totalDeductions = blueDeduction + basicDeduction + socialDeduction
+ iDeCoDeduction + medicalDeduction + dependentDeduction;
// 課税所得(1,000円未満切り捨て)
return Math.max(
Math.floor((businessIncome - totalDeductions) / 1000) * 1000,
0
);
}
実務上は配偶者控除や生命保険料控除とか他にもあるんだけど、フリーランスが「ざっくり手取りを知りたい」レベルなら上の項目でだいたいカバーできる。
住民税・事業税・国保の計算
住民税は所得税と似てるけど、控除額が微妙に違う(基礎控除が43万円など)。個人事業税は290万円の事業主控除がある。国保は自治体によって全然違うので、東京23区のデフォルト値を入れつつ、料率をカスタマイズできるようにした。
function calcResidentTax(taxableIncome: number): number {
// 住民税の課税所得は控除額が所得税と異なるが、
// ここでは簡略化して所得税の課税所得を流用
const incomePortion = Math.floor(taxableIncome * 0.10);
const equalPortion = 5_000; // 均等割(標準税率)
return incomePortion + equalPortion;
}
function calcBusinessTax(businessIncome: number, taxRate: number = 0.05): number {
// 事業主控除290万円
const taxable = Math.max(businessIncome - 2_900_000, 0);
return Math.floor(taxable * taxRate);
}
function calcNationalHealthInsurance(
businessIncome: number,
rates: { medical: number; support: number; care: number } = {
medical: 0.0786, // 医療分(東京23区の例)
support: 0.0270, // 後期高齢者支援金分
care: 0.0222, // 介護分(40-64歳のみ)
},
includeCarePortion: boolean = false
): number {
const base = Math.max(businessIncome - 430_000, 0); // 基礎控除43万
let total = Math.floor(base * rates.medical) + Math.floor(base * rates.support);
if (includeCarePortion) {
total += Math.floor(base * rates.care);
}
// 均等割(世帯人数1人の場合の概算)
total += 52_000 + 17_400;
if (includeCarePortion) total += 17_000;
return total;
}
UIの設計思想
計算ロジックができたら、あとはUIの話。自分が欲しかったのは「数字を入れたらリアルタイムで結果が変わる」体験。ページ遷移とか送信ボタンとか要らない。
売上のスライダーを動かすと、所得税・住民税・事業税・国保がリアルタイムに計算されて、最終的な手取り額が表示される。経費率も調整できるようにした。
フリーランス仲間に使ってもらったら「見積もり出す前にこれで手取り計算してから単価決めてる」という使い方をしてる人がいて、それは想定外だった。確かに「月50万の案件」と言われて、実際の手取りがいくらになるかパッと計算できると便利。
作ってみて気づいたこと
税金の計算ロジック自体はそこまで複雑じゃない。面倒なのは「どの控除が自分に適用されるか」の判断と、「自治体ごとに違う国保の料率」の対応。
国保については、主要都市の料率をプリセットとして持たせて、それ以外はユーザーが手入力できるようにした。全自治体分のデータを持つのは現実的じゃないので。
あと、税制改正への対応が地味にコストかかる。毎年12月に翌年の税制大綱が出るので、年末年始にテーブルを更新する必要がある。これは仕方ない。
ツールは tax.mildsolt.jp で公開している。売上と経費を入れるだけで4種類の税金が自動計算される。自分と同じように確定申告で苦しんでるフリーランスの役に立てば嬉しい。
まとめ
- フリーランスの税金計算は4種類(所得税・住民税・事業税・国保)
- 超過累進課税は控除額テーブルで一発計算できる
- 国保は自治体ごとに料率が違うのが最大の罠
- リアルタイム計算UIにすると実用性が跳ね上がる
「自分の税金は自分で把握したい」というフリーランスの方は、tax.mildsolt.jp を試してみてほしい。見積もり前の手取りシミュレーションにも使える。
ソースコードはGitHubで公開してるので、税制改正に合わせてPR送ってくれる人がいたら助かる。