あなたもこんな経験ありませんか?
「Controllerに全部書いて動いたけど、なぜか現場では怒られた…」
「Repository?Service?どこに何を書くのが正解か分からない」
Spring Bootを学び始めたばかりの頃、MVC構成に戸惑う人は多くいます。
この記事を読めば、以下のような疑問がクリアになります。
-
なぜMVC構成が必要なのか
-
各レイヤー(Controller / Service / Repository)の役割
-
どこにロジックを記述すべきかの判断基準
-
実務でよくある構成パターンと落とし穴
検索意図(Why/What)
「MVCって何?」「役割の違いは?」「どこに処理を書くべき?」という悩みを、実務レベルで解消したい方に向けた解説です。
MVC構成とは?まず全体像を把握しよう
Spring Bootで採用されるMVC(Model-View-Controller)は、処理を役割ごとに分離して、保守性・可読性を高める設計思想です。
[ユーザー操作]
↓
Controller(司令塔)
↓
Service(業務ロジック)
↓
Repository(DBアクセス)
各層の役割をやさしく解説
-
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:objectとth:fieldの正しい使い方を徹底解説