Spring BootのDTO設計:適切な切り分け方(新人エンジニア向け)

こんにちは。ゆうせいです。
Spring Boot でWebアプリケーションを作るとき、
「DTO(Data Transfer Object)はどうやって設計すればいいの?」 という疑問を持つことがありますよね。

「DTOは何のために必要?」
「どこまでDTOを作るべき?」
「DTOをどう切り分ければ、メンテナンスしやすい設計になる?」

結論:
DTOは「データの受け渡し専用」にして、エンティティ(DBモデル)とは分離するのが基本!
今回は、新人エンジニア向けに、Spring BootのDTOの適切な設計方法 をわかりやすく解説します!


1. DTO(Data Transfer Object)とは?

DTO(データ転送オブジェクト)は、レイヤー間(Controller ⇔ Service ⇔ Repository)でデータをやりとりするためのオブジェクト です。

📌 DTOを使う理由

  1. エンティティ(DBモデル)とAPIレスポンスを分離できる
  2. セキュリティ(パスワードなどの機密情報を隠せる)
  3. APIのリクエストやレスポンスの形式を統一できる
  4. 拡張性が高まり、メンテナンスしやすくなる

2. DTOを作らないとどうなる?(悪い例)

DTOを使わずに、エンティティ(DBモデル)を直接APIのレスポンスに使う のは、一般的に避けるべきです。

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String email;
    private String password;  // 🔴 パスワードがAPIレスポンスに含まれてしまう!
}

@RestController
@RequestMapping("/users")
public class UserController {
    
    private final UserRepository userRepository;

    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) { // 🔴 エンティティをそのまま返してしまう
        return userRepository.findById(id).orElseThrow();
    }
}



❌ この設計の問題点

  1. セキュリティの問題パスワードなどの機密情報がそのまま返る可能性がある
  2. APIの仕様変更に弱い → DBの構造が変わると、フロントエンドにも影響が出る
  3. データ転送量が無駄に増える → 必要のない情報までAPIレスポンスに含まれる

📌 エンティティ(DBモデル)とAPIレスポンスを分離するために、DTOを使うべき!


3. DTOの適切な設計

✅ 基本的なDTOの分け方

DTOの種類役割
RequestDTO(入力用)クライアントからのリクエストデータを受け取る
ResponseDTO(出力用)APIのレスポンスデータを整形して返す
内部DTO(Service間のデータ受け渡し)Service ⇔ Repository の間で使う

✅ DTOを適切に設計した例

1. ユーザー情報のDTO

public class UserDTO {
    private Long id;
    private String username;
    private String email;

    public UserDTO(Long id, String username, String email) {
        this.id = id;
        this.username = username;
        this.email = email;
    }

    // ゲッター・セッター
}

📌 パスワードなどの機密情報は含めない!


2. APIリクエスト用のDTO(UserRequestDTO)

public class UserRequestDTO {
    private String username;
    private String email;
    private String password;

    // ゲッター・セッター
}

📌 クライアント(フロントエンド)からの入力データ用


3. APIレスポンス用のDTO(UserResponseDTO)

public class UserResponseDTO {
    private Long id;
    private String username;
    private String email;

    public UserResponseDTO(User user) {
        this.id = user.getId();
        this.username = user.getUsername();
        this.email = user.getEmail();
    }

    // ゲッターのみ(レスポンスなので、書き換え不可)
}

📌 エンティティとは分離し、APIのレスポンス専用にする


4. DTOをコントローラーとサービスでどのように使うか?

✅ 正しいDTOの使い方(Service層を挟む)

@RestController
@RequestMapping("/users")
public class UserController {
    
    private final UserService userService;

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

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

    @PostMapping
    public void createUser(@RequestBody @Valid UserRequestDTO userRequest) {
        userService.createUser(userRequest);
    }
}

📌 コントローラーでは、DTOを受け渡しに使い、エンティティは扱わない!


✅ Service 層でDTOを変換

@Service
public class UserService {

    private final UserRepository userRepository;

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

    public void createUser(UserRequestDTO userRequest) {
        User user = new User();
        user.setUsername(userRequest.getUsername());
        user.setEmail(userRequest.getEmail());
        user.setPassword(userRequest.getPassword()); // 🔴 ここで暗号化するのがベスト

        userRepository.save(user);
    }
}

📌 DTOをエンティティに変換し、データをやりとりする!


5. まとめ

設計のポイント説明
DTOはエンティティと分離するDBの変更がAPIレスポンスに影響しないようにする
DTOをリクエストとレスポンスで分けるUserRequestDTO(入力用) / UserResponseDTO(出力用)
DTOを使ってセキュリティを強化パスワードや機密情報をレスポンスに含めない
DTOはコントローラーで使い、エンティティはサービスで使う@Service でDTOをエンティティに変換する

6. 結論

🚀 DTOは「データの受け渡し専用」にして、エンティティ(DBモデル)とは分離!
🚀 リクエストDTO(入力用)とレスポンスDTO(出力用)を分けると、APIが整理される!
🚀 コントローラーでDTOを使い、エンティティは @Service で扱う!

この設計を守れば、「セキュリティが強く、メンテナンスしやすいSpring Bootアプリ」 を作れます!
ぜひ実践してみてください!

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

投稿者プロフィール

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