Java | Web 基礎・HTTP・REST:Web 全体像 - 3 層アーキテクチャ

Java Java
スポンサーリンク

3 層アーキテクチャを一言でいうと

3 層アーキテクチャは、
「Web アプリを 3 つの役割にきれいに分けて作ろう」という設計の型 です。

プレゼンテーション層(画面・API の入り口)
アプリケーション層(ビジネスロジック)
データアクセス層(DB とのやり取り)

この 3 つに分けることで、
「どこに何を書くか」がはっきりし、
コードが読みやすく、変更しやすく、テストしやすくなります。

Java の Web アプリ(特に Spring)では、
ほぼ標準の考え方だと思っていいです。


全体像:3 つの層がどうつながるか

上から下へ、下から上へ

ざっくりいうと、流れはこうです。

ブラウザ(またはクライアント)がリクエストを送る
プレゼンテーション層(Controller)が受け取る
アプリケーション層(Service)がビジネスロジックを実行する
データアクセス層(Repository / DAO)が DB とやり取りする
結果が逆順で戻ってきて、レスポンスとして返される

重要なのは、
「層ごとに責務(役割)が違う」
「下の層の詳細を、上の層に漏らさない」
という考え方です。


プレゼンテーション層(Controller)の役割

「外からの入り口」としての顔

プレゼンテーション層は、
「外の世界(ブラウザや他システム)とアプリをつなぐ窓口」 です。

Spring なら @Controller@RestController がここに当たります。

やることはシンプルで、
リクエストを受け取る
パラメータを取り出す
サービス層を呼び出す
結果を HTML や JSON にして返す

という「受け付けと返却」の仕事です。

例:ユーザー一覧 API の Controller

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

    private final UserService userService;

    @GetMapping
    List<UserResponse> list() {
        var users = userService.findAll();
        return users.stream()
                    .map(UserResponse::from)
                    .toList();
    }
}
Java

ここでやっていることは、
HTTP の世界(URL、メソッド)と
アプリケーションの世界(userService.findAll())をつなぐことだけです。

「ビジネスルール」はここには書きません。
あくまで「入り口」としての役割に徹します。


アプリケーション層(Service)の役割

「ビジネスロジックの本体」

アプリケーション層は、
「このシステムが何をしたいのか」を表現する場所 です。

ユーザー登録
注文処理
料金計算
在庫チェック

といった「業務としての意味がある処理」は、
基本的にここに書きます。

Spring なら @Service がここに当たります。

例:ユーザー取得の Service

@Service
class UserService {

    private final UserRepository userRepository;

    List<User> findAll() {
        return userRepository.findAll();
    }

    User register(UserRegisterCommand command) {
        // ここにビジネスルールを書く
        // 例:メールアドレスの重複チェックなど
        var user = new User(command.email(), command.name());
        return userRepository.save(user);
    }
}
Java

ここで重要なのは、
Controller は「HTTP のこと」を知っているが、
Service は「HTTP のことを知らない」
という分離です。

Service は、
「ユーザーを登録する」「一覧を取得する」といった
純粋なビジネスの言葉だけで書かれているのが理想です。


データアクセス層(Repository / DAO)の役割

「DB とだけ話す層」

データアクセス層は、
「DB(や外部ストレージ)とのやり取りを一手に引き受ける層」 です。

SQL を書いたり、
ORM(JPA / Hibernate など)を使って
エンティティを保存・検索したりするのはここです。

Spring なら @Repository や、JpaRepository を継承したインターフェースがここに当たります。

例:ユーザーの Repository

interface UserRepository extends JpaRepository<User, Long> {

    Optional<User> findByEmail(String email);
}
Java

Service はこの UserRepository を使って、
「ユーザーを保存する」「メールアドレスで検索する」
といった操作を行います。

ここで重要なのは、
Controller は Repository を直接触らない
Service が Repository をまとめて扱う
という構造にすることです。


なぜ 3 層に分けるのか(ここが一番大事)

1. 変更に強くなる

例えば、
「DB を MySQL から PostgreSQL に変えたい」
「画面を HTML から SPA(フロント JS)に変えたい」

といった変更が入ったとき、
3 層がきちんと分かれていれば、
影響範囲を限定できます。

DB を変えるときは、基本的に Repository 層だけを直せばよい
画面の作り方を変えるときは、Controller とフロント側を直せばよい
Service のビジネスロジックはそのまま

という状態を目指します。

層がごちゃ混ぜになっていると、
「画面を変えたいだけなのに、ビジネスロジックも DB も全部巻き込まれる」
という地獄になります。

2. テストしやすくなる

Service 層がきちんと分かれていると、
「HTTP 抜きでビジネスロジックだけをテストする」
ことができます。

Repository をモックにして、
Service のメソッドを直接呼び出すテストを書けば、
Web サーバーを立ち上げなくてもロジックの確認ができます。

逆に、Controller にビジネスロジックと DB アクセスが全部書かれていると、
テストが非常にやりにくくなります。

3. 読みやすく、役割が明確になる

「この処理、どこに書けばいいんだろう?」
という迷いが減ります。

HTTP に関すること(URL、ステータスコード、ヘッダなど)は Controller
ビジネスルールは Service
DB の詳細は Repository

というルールがあるだけで、
チーム全体のコードの方向性が揃います。


よくあるアンチパターンと、その危険性

Controller に全部書いてしまう

初心者がやりがちなのは、
Controller のメソッドの中に、

パラメータ取得
バリデーション
ビジネスロジック
DB アクセス
レスポンス組み立て

を全部書いてしまうパターンです。

最初は動きますが、
機能が増えるとすぐに 300 行、500 行のメソッドになり、
誰も触りたくない「巨大メソッド」が誕生します。

3 層アーキテクチャは、
これを避けるための「分割の型」だと思ってください。

Repository を直接 Controller から呼ぶ

Controller から直接 Repository を呼ぶと、
「ビジネスロジックがどこにあるのか」が分からなくなります。

ある処理は Controller に書いてあり、
別の処理は Service にあり、
さらに別の処理は Repository に…

という状態になると、
仕様変更のたびにコード全体を探し回ることになります。


初心者向けの実践ステップ

まずは「3 つのクラス」を意識して作ってみる

例えば、「ユーザー一覧表示」という機能を作るときに、
必ずこの 3 つを用意してみてください。

UserController
UserService
UserRepository

最初は中身が薄くても構いません。
「とりあえず 3 つに分ける」という習慣をつけることが大事です。

Controller は「受け取って渡す」だけ
Service は「ビジネスの意味がある処理」
Repository は「DB とのやり取り」

という役割を意識して、
少しずつ中身を移していくイメージです。


まとめ:3 層アーキテクチャを自分の言葉で説明するなら

あなたの言葉で整理すると、こうなります。

「3 層アーキテクチャとは、
Web アプリを
プレゼンテーション層(Controller)、
アプリケーション層(Service)、
データアクセス層(Repository)
の 3 つに分けて、
それぞれの役割をはっきりさせる設計の型。

Controller は“入り口”、Service は“ビジネスロジックの本体”、Repository は“DB と話す人”。
こう分けることで、変更に強く、テストしやすく、読みやすいコードになる。」

タイトルとURLをコピーしました