Spring Bootのコントローラー設計:適切な切り分け方(新人エンジニア向け)

こんにちは。ゆうせいです。
Spring Boot でWebアプリケーションを開発するとき、
「コントローラーの設計をどう分ければいいの?」 と悩むことがありますよね。

「1つのコントローラーに全部書くのはダメ?」
「どこまでコントローラーで処理すべき?」
「コントローラーをどう分割すればいい?」

結論:
コントローラーは「機能ごと」に分割し、ビジネスロジックは @Service に移すのが基本!
今回は、新人エンジニア向けに、Spring Boot のコントローラーの適切な設計方法 をわかりやすく解説します!


1. コントローラーの基本的な役割

Spring Boot のコントローラーは、「クライアントのリクエストを受け取り、レスポンスを返す」 役割を持っています。

📌 コントローラーの主な役割

  1. リクエストを受け取る@GetMapping@PostMapping など)
  2. リクエストパラメータの取得・バリデーション
  3. @Service を呼び出してビジネスロジックを実行
  4. レスポンスを JSON や HTML として返す

📌 コントローラーでは「画面の操作」や「データの取得・送信」に関する処理を担当し、ビジネスロジックは @Service に移す!


2. 1つのコントローラーにすべて詰め込むのはNG!

よくある間違い は、1つのコントローラーにすべての処理を詰め込むこと です。

@RestController
@RequestMapping("/users")
public class UserController {
    
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        // ユーザー情報取得
    }

    @PostMapping
    public void createUser(@RequestBody User user) {
        // ユーザー作成
    }

    @PutMapping("/{id}")
    public void updateUser(@PathVariable Long id, @RequestBody User user) {
        // ユーザー更新
    }

    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        // ユーザー削除
    }

    @PostMapping("/login")
    public void login(@RequestBody LoginRequest request) {
        // ユーザーログイン処理
    }
}

❌ この設計の問題点

  • 役割が混ざっている(ユーザー管理と認証が同じクラスにある)
  • コードが肥大化し、可読性が低い
  • 変更が入ると影響範囲が大きくなる

📌 「1つのクラスにすべてを詰め込む」のではなく、「責務(役割)ごと」に分割するのがベスト!


3. コントローラーの適切な分割方法

✅ 基本的なコントローラーの分け方

コントローラー名役割
UserControllerユーザー管理(CRUD操作)
AuthController認証(ログイン・ログアウト)
ProductController商品管理(商品情報の取得・登録)
OrderController注文管理(カート・注文処理)

📌 機能ごとにコントローラーを分割すれば、コードが整理されて可読性が向上する!


✅ 適切に分割したコントローラーの実装例

1. ユーザー管理 (UserController)

@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);
    }

    @PostMapping
    public void createUser(@RequestBody UserDTO user) {
        userService.createUser(user);
    }

    @PutMapping("/{id}")
    public void updateUser(@PathVariable Long id, @RequestBody UserDTO user) {
        userService.updateUser(id, user);
    }

    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
    }
}


2. 認証 (AuthController)

@RestController
@RequestMapping("/auth")
public class AuthController {
    
    private final AuthService authService;

    public AuthController(AuthService authService) {
        this.authService = authService;
    }

    @PostMapping("/login")
    public String login(@RequestBody LoginRequest request) {
        return authService.authenticate(request);
    }

    @PostMapping("/logout")
    public void logout() {
        authService.logout();
    }
}


4. コントローラーをシンプルに保つ

✅ コントローラーに「ビジネスロジック」を書かない!

ビジネスロジック(計算・データ処理など)は @Service に移す!

NG例(コントローラーにロジックが入っている)

@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
    User user = userRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found"));
    user.setLastAccessed(new Date());  // 直接データ変更
    return user;
}

OK例(@Service にロジックを移動)

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

UserService の中でロジックを処理

@Service
public class UserService {
    
    private final UserRepository userRepository;

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

📌 コントローラーは「受け取る & 返す」に集中し、ロジックは @Service に移す!


5. REST API の設計を意識する

コントローラーを設計するときは、RESTful API の原則 を意識すると整理しやすくなります。

✅ HTTPメソッドの使い分け

処理HTTPメソッドエンドポイント
ユーザー一覧取得GET/users
ユーザー詳細取得GET/users/{id}
ユーザー作成POST/users
ユーザー更新PUT/users/{id}
ユーザー削除DELETE/users/{id}

📌 データ操作の基本的なルールを守ると、開発しやすくなる!


6. まとめ

原則説明
コントローラーは責務ごとに分割1つのクラスに詰め込まず、機能ごとに分ける
ロジックは @Service に移すコントローラーはシンプルに保ち、ビジネスロジックは @Service で処理
RESTful API の設計を意識するHTTPメソッドを適切に使い、エンドポイントを整理する
コードの可読性を重視するチーム開発を考え、誰が見ても分かりやすい構成にする

7. 結論

🚀 Spring Boot のコントローラーは「役割ごとに分ける」のがベスト!
🚀 ロジックは @Service に移して、コントローラーはシンプルに!
🚀 REST API の設計を意識して、分かりやすいエンドポイントを作る!

このルールを守れば、「メンテナンスしやすく、拡張しやすいSpring Bootアプリ」 を作れます!
ぜひ実践してみてください!

セイ・コンサルティング・グループでは新人エンジニア研修のアシスタント講師を募集しています。

投稿者プロフィール

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