バリデーション入門編

2024/05/09に公開

ご注意

この記事はジュニアクラスのWebアプリケーションエンジニア向けに、バリデーションの解説をするものです。
個別の言語やライブラリに関するものではありません。

Webアプリケーションにおけるバリデーション

1. バリデーションとはなにか?

バリデーションとは、入力された値や送信されたデータが適切かどうかをチェックする処理のことです。Webアプリケーションにおいては、ユーザーが入力したフォームデータや、APIへのリクエストパラメータなどを検証する必要があります。適切なバリデーションを行うことで、不正なデータの受け入れを防ぎ、アプリケーションの安全性と整合性を確保できます。

バリデーションには、以下のようなルールが含まれます。

  • 必須項目のチェック
  • 文字列の長さチェック
  • データ型の検証(数値、日付など)
  • フォーマットの検証(メールアドレス、電話番号など)
  • 値の範囲チェック
  • 一意性チェック(ユーザー名やメールアドレスの重複など)

バリデーションは、フロントエンド(ブラウザ側)とバックエンド(サーバー側)の両方で行われます。それぞれの役割と特徴は異なります。

2. フロントエンドのバリデーション

フロントエンドでのバリデーションは、ユーザービリティの向上と無駄なデータ送信の削減を目的としています。JavaScript、HTMLの標準機能を使って、フォームの入力内容をチェックすることができます。

フロントエンドバリデーションのメリットは以下の通りです。

  • ユーザーに対してすぐにフィードバックを返すことができる
  • 不正なデータをサーバーに送信する前に防げる
  • サーバー側の負荷を軽減できる

一方で、フロントエンドバリデーションだけでは不十分な点もあります。

  • JavaScriptを無効にされた場合、バリデーションが機能しない
  • 悪意のあるユーザーがJavaScriptをバイパスする可能性がある

そのため、フロントエンドバリデーションはあくまでも補助的な役割にすぎず、バックエンドでのバリデーションが必須となります。

3. バックエンドのバリデーション

バックエンドでのバリデーションは、アプリケーションの信頼性と安全性を確保する上で非常に重要です。サーバー側でデータを検証することで、不正なデータが処理されるリスクを回避できます。

バックエンドバリデーションのメリットは以下の通りです。

  • 悪意のある攻撃からアプリケーションを守ることができる
  • データベースの整合性を維持できる
  • ビジネスロジックに基づいた複雑なバリデーションルールを設定できる

バックエンドバリデーションでは、フレームワークが提供するバリデーション機能や、独自のバリデーションロジックを実装することができます。どちらを選択するかは、アプリケーションの要件や複雑さによって異なります。

4. フロントエンド例

MDNのフォームを使ってHTMLのバリデーションを見てみましょう。
https://developer.mozilla.org/ja/docs/Web/HTML/Element/form

なにも入力しないで Subscribe を押すと、HTMLの required によるバリデーションの注意が出ます。

なにかしら入力すると、そのフォームには出なくなります。

必須以外にもHTML標準機能でいくつかのバリデーションは実行出来ます。
しかし、メッセージの出し方や範囲の指定など、少し凝ったことをするには JavaScript が必要になります。
具体的には react vue などを使うことが多いでしょう。

5. バックエンド例

言語によらずですが、基本的にフロントエンドでバリデーションされている前提を捨てて値をチェックします。
各値のバリデーションルールはフロントエンドと同様に、かつDBとの整合性チェックなど追加します。
JavaScript(TypeScript) での一例を示します。

import express, { Request, Response, NextFunction } from 'express'
const app = express()

app.post('/', async(req, res) => {
  const { userId, name, email } = req.body

  // userIdが1以上の整数であるか
  const isValidUserId = true  // チェックする

  // nameが半角英数字255文字以内であるか
  const isValidName = true  // チェックする

  // emailがメールアドレスの要件を満たしているか
  const isValidEmail = true  // チェックする

  // この時点で要件を満たさなかったらエラーを返す
  if (
    !isValidUserId ||
    !isValidName ||
    !isValidEmail
  ) {
    return res.send('not valid')
  }

  // userIdに該当するレコードがDBに存在するか
  const user = await getUserById(userId)
  if (!user) {
    return res.send('user not found')
  }

  // 以降の処理を実行する
  doSomething()

  return res.send('end do something')
})

実際には express を使っている場合、送信値のチェックには express-validator などを使う場合が多いでしょう。
送信された値を信用せずにバリデーションを行いましょう。
また、DBをCRUDする際には整合性のチェックも実行しましょう。
ログインユーザーのIDと、変更するユーザーのIDが正しいかといったチェックは、ユースケース層で行うのが良いでしょう。

まとめ

Webアプリケーションにおけるバリデーションは、フロントエンドとバックエンドの両方で行う必要があります。
フロントエンドバリデーションはユーザービリティの向上に役立ち、バックエンドバリデーションはアプリケーションの安全性と整合性を守ります。適切なバリデーションを実装することで、信頼性の高いWebアプリケーションを構築できます。

Discussion