Loading
  • LIGHT

  • DARK

ROUTE

ルートゼロの
アクティビティ

MVC構成を理解すれば現場で詰まらない | Spring Boot実装ガイド

1

あなたもこんな経験ありませんか?

「Controllerに全部書いて動いたけど、なぜか現場では怒られた…」
「Repository?Service?どこに何を書くのが正解か分からない」
Spring Bootを学び始めたばかりの頃、MVC構成に戸惑う人は多くいます。

この記事を読めば、以下のような疑問がクリアになります。

  • なぜMVC構成が必要なのか

  • 各レイヤー(Controller / Service / Repository)の役割

  • どこにロジックを記述すべきかの判断基準

  • 実務でよくある構成パターンと落とし穴

検索意図(Why/What)
「MVCって何?」「役割の違いは?」「どこに処理を書くべき?」という悩みを、実務レベルで解消したい方に向けた解説です。


MVC構成とは?まず全体像を把握しよう

Spring Bootで採用されるMVC(Model-View-Controller)は、処理を役割ごとに分離して、保守性・可読性を高める設計思想です。

[ユーザー操作]Controller(司令塔)
   ↓
Service(業務ロジック)
   ↓
RepositoryDBアクセス)

各層の役割をやさしく解説

  • Controller:ユーザーのリクエストを受け取り、Serviceに処理を依頼する窓口。
    ※例:「画面遷移やリクエストパラメータの受け取りを担う」

  • Service:ビジネスロジックを記述。計算や条件分岐などの処理もここ。
    ※例:「在庫チェックやユーザー認証などの業務ロジック」

  • Repository:DB操作を担当。JPAやJDBCを使ってデータの取得・更新を行う。
    ※例:「SQLの実行やEntityの保存・検索」


サンプル構成:Spring Bootでの実装例

以下は「ユーザー情報を取得して表示する」処理のMVC実装例です。

Controller

@RestController
@RequestMapping("/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/{id}")
    public UserDto getUser(@PathVariable Long id) {
        return userService.getUserById(id);
    }
}

Service

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public UserDto getUserById(Long id) {
        User user = userRepository.findById(id)
                          .orElseThrow(() -> new RuntimeException("User not found"));
        return new UserDto(user);
    }
}

Repository

public interface UserRepository extends JpaRepository<User, Long> {
}

よくあるつまずき:全部Controllerに書いてしまう

❌ Before:ありがちなNG実装

@GetMapping("/{id}")
public UserDto getUser(@PathVariable Long id) {
    User user = userRepository.findById(id).orElseThrow();
    return new UserDto(user);
}

→ 一見動作しますが、ビジネスロジックがControllerに混在しており、後々の保守が困難になります。


✅ After:適切なMVC分離

// Controller
@GetMapping("/{id}")
public UserDto getUser(@PathVariable Long id) {
    return userService.getUserById(id);
}

// Service
public UserDto getUserById(Long id) {
    User user = userRepository.findById(id)
                    .orElseThrow(() -> new RuntimeException("User not found"));
    return new UserDto(user);
}

→ 各レイヤーの責務が明確になり、再利用性・テスト性が向上します。


【よくある質問・補足】

Q:Serviceって必要?ControllerとRepositoryだけじゃダメ?
→ 小規模では成り立つ場合もありますが、機能拡張やテストの観点で分離すべきです。

Q:Repositoryにはどこまで書いていいの?
→ 基本はDBアクセスのみに限定。条件分岐や計算はServiceへ。


まとめ | MVC構成が理解できれば、設計に迷わない

  • MVCは責務を分離してコードを見通し良くする設計パターン

  • Controller:リクエストの受付と振り分け

  • Service:業務ロジックの処理

  • Repository:データベースとのやり取り

実務に強いSpring Boot開発のためには、構成ルールを守る習慣が非常に大切です。


【外部リンク】

Spring Boot公式サイト
Spring Framework公式ガイド – Spring MVC

【内部リンク】

Spring Bootアプリ開発で頻発するWhitelabel Error Page|Thymeleafのテンプレートエラーと対策まとめ

【Spring Boot実践ガイド】List型・Map型の違いとBeanクラスの基礎&応用

Spring Bootのよく使われるアノテーションとは?初心者必見の解説と活用法

Spring Boot バリデーション入門|MVC統合とカスタムアノテーション実践例

【保存版】JPA vs JDBC│Spring Bootでの実務的な使い分けと導入判断ガイド

Thymeleafの「th:field」とは何か

フォーム値が消える?Thymeleaf th:objectとth:fieldの正しい使い方を徹底解説

Javaのfor文をStreamに書き換えるには?Spring Bootでの実践例付きでわかる!

JavaとSpring Bootで学ぶWebアプリ作成の第一歩|初心者向けステップバイステップガイド

RANKINGranking-icon

LATEST POSTS

もっとルートゼロを知りたいなら

DISCOVER MORE