初心者がやりがち!Spring Bootの落とし穴7選とその回避法

こんにちは。ゆうせいです。

Spring Bootは、JavaによるWebアプリケーション開発のハードルをぐっと下げてくれる素晴らしいフレームワークです。しかし、「簡単に書ける」からこそ、初心者が知らず知らずのうちにやってはいけない実装に手を出してしまうことも少なくありません。

今回は、Spring Boot初学者がよくやってしまうミス7選を、具体的なコード例や図解とともに解説します!


1. セッションに何でも入れてしまう

問題点:

セッションはログイン状態や一時的なフラグなど、「最低限の情報」を保持するための仕組みです。検索結果の一覧やフォームの状態などを何でも詰め込むと、メモリ不足や意図しない動作の原因になります。

例:

session.setAttribute("form", form);
session.setAttribute("searchResultList", hugeList);

解決策:

  • フォームの一時データは @ModelAttribute
  • リダイレクト間のデータは RedirectAttributes を使う
  • セッションは最終手段と心得よう!

2. ViewからViewへ直接遷移する

問題点:

テンプレートファイルに直接リンクすると、コントローラーを経由しないため、初期化処理やセキュリティチェックが抜け落ちるリスクがあります。

NG例:

<a href="/templates/form.html">フォームへ</a>

解決策:

@GetMapping("/form")
public String showForm(Model model) {
    model.addAttribute("form", new Form());
    return "form";
}
<a th:href="@{/form}">フォームへ</a>



3. コントローラーにビジネスロジックを全部書いてしまう

問題点:

コントローラーに全て詰め込むと、責任が曖昧になりテストが困難になります。バリデーション、DB操作、状態管理などが混在していると、再利用性も失われます。

解決策:

  • ビジネスロジックは @Service クラスに分離
  • コントローラーは「データの受け取りと渡すだけ」に徹する

4. 設定ファイルを環境ごとに分けていない

問題点:

application.properties を1つしか使っていないと、開発用設定がそのまま本番で使われることがあります。これは、セキュリティ事故やパフォーマンス問題の原因になりかねません。

解決策:

  • Springのプロファイル機能を活用しよう!
# application-dev.properties
spring.datasource.url=jdbc:h2:mem:test

# application-prod.properties
spring.datasource.url=jdbc:mysql://本番DB



起動時に --spring.profiles.active=prod を指定すれば切り替えできます。


5. バリデーションをフロント側だけに任せる

問題点:

JavaScriptだけで入力チェックをしていると、悪意のあるリクエストに無防備になります。サーバー側でのバリデーションがなければ、危険な値がそのまま登録されてしまう可能性も。

解決策:

  • @Valid アノテーションと BindingResult を併用
  • Bean Validation(JSR-380)を使えば簡潔に記述できます!
@PostMapping("/submit")
public String submit(@Valid @ModelAttribute Form form, BindingResult result) {
    if (result.hasErrors()) return "form";
    service.save(form);
    return "redirect:/done";
}


6. 共通の例外処理をしない

問題点:

例外が発生したとき、白い画面に英語のエラーだけが出てくると、ユーザーは困惑し、開発者もデバッグに時間がかかります

解決策:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public String handleException(Exception e, Model model) {
        model.addAttribute("message", "予期せぬエラーが発生しました。");
        return "error";
    }
}
  • @ControllerAdvice で例外ハンドリングを共通化


7. 入力値を直接エンティティにバインドする

問題点:

フォームから受け取ったデータをそのままDBエンティティに渡すと、意図しないデータ上書きやセキュリティ上の問題が起こる可能性があります。

解決策:

  • 入力用の DTO(Data Transfer Object) を作成し、Entityとは分離
  • DTO → Entity 変換は Service層で明示的に行う

例:

public class UserForm {
    private String name;
    private String email;
}

public User toEntity(UserForm form) {
    return new User(form.getName(), form.getEmail());
}




一覧表:7つの典型的なミスと対策

番号ミス内容問題点推奨される対応策
1セッションに何でも保存メモリ圧迫、状態の混乱Flash属性やModelで管理
2ViewからViewに直接遷移コントローラー処理がスキップされるControllerを必ず経由
3ロジックをControllerに直書き責任不明瞭、テスト困難Service層に処理を分離
4環境別の設定を分けていない本番環境で事故が起きるProfileで環境を分離
5バリデーションをフロントだけに依存サーバー側が無防備@ValidとBindingResultを活用
6共通の例外処理をしていないユーザーに不親切、デバッグ困難@ControllerAdviceを使う
7入力値をEntityに直接バインドしているセキュリティ・データ整合性の問題DTOを作り、Entityと分離

今後の学習の指針

これらのポイントを意識するだけで、アプリケーションの品質や保守性が一段階アップします!

次に学ぶと良いトピックは以下の通りです。

  • Springのスコープ(@RequestScope, @SessionScope)の違い
  • Model, RedirectAttributes, DTOの設計パターン
  • Spring Securityによる画面制御とアクセス制御
  • 例外ハンドリングとログ出力の設計

迷ったら「なぜこの方法が推奨されるのか?」と一度立ち止まって考えるのが、実力アップの近道です。じっくりと、でも確実に学んでいきましょう!


セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。