๐Ÿ“ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ/SPRING

DTO๋ฅผ Request, Response๋กœ ๋‚˜๋ˆ„๋Š” ์ด์œ 

Yeom.log 2025. 2. 15. 04:34
๋ฐ˜์‘ํ˜•

DTO(Data Transfer Object)๋ฅผ request์™€ response๋กœ ๋‚˜๋ˆ„๋Š” ์ด์œ ๋Š” ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์˜ ์—ญํ• ์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ.


๐Ÿ“Œ ์ฃผ์ œ: "๋„์„œ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ" (Library Management System)

  • ์‚ฌ์šฉ์ž๊ฐ€ ์ฑ…์„ ์ถ”๊ฐ€ํ•  ๋•Œ Request DTO
  • ์‚ฌ์šฉ์ž๊ฐ€ ์ฑ… ์ •๋ณด๋ฅผ ์กฐํšŒํ•  ๋•Œ Response DTO

โœ… 1. Request DTO (์ž…๋ ฅ)

  • ํด๋ผ์ด์–ธํŠธ → ์„œ๋ฒ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ๋•Œ ์‚ฌ์šฉ
  • ์ฃผ๋กœ POST, PUT, PATCH ์š”์ฒญ์—์„œ ์‚ฌ์šฉ๋จ
  • ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ(ex: @Valid, @NotNull)๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Œ
  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—”ํ‹ฐํ‹ฐ์™€ 1:1 ๋งคํ•‘๋˜์ง€ ์•Š์•„๋„ ๋จ (ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฆ„)
package com.example.library.dto.request;

import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Positive;

@Getter
@NoArgsConstructor
public class BookRequestDto {
    @NotBlank
    private String title;

    @NotBlank
    private String author;

    @Positive
    private int price;

    public BookRequestDto(String title, String author, int price) {
        this.title = title;
        this.author = author;
        this.price = price;
    }
}

โœจ ์‚ฌ์šฉ ์˜ˆ์‹œ

@PostMapping("/books")
public ResponseEntity<Void> createBook(@RequestBody @Valid BookRequestDto requestDto) {
    bookService.createBook(requestDto);
    return ResponseEntity.ok().build();
}

๐Ÿ‘‰ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋‚ธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์„œ ์ฑ…์„ ๋“ฑ๋กํ•˜๋Š” ๋กœ์ง

  • @NotBlank → title, author๊ฐ€ ๋น„์–ด ์žˆ์œผ๋ฉด ์•ˆ ๋จ
  • @Positive → price๋Š” 0๋ณด๋‹ค ์ปค์•ผ ํ•จ

โœ… 2. Response DTO (์ถœ๋ ฅ)

  • ์„œ๋ฒ„ → ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ๋•Œ ์‚ฌ์šฉ
  • ์ฃผ๋กœ GET ์š”์ฒญ์—์„œ ์‚ฌ์šฉ๋จ
  • ์—”ํ‹ฐํ‹ฐ ๊ทธ๋Œ€๋กœ ๋…ธ์ถœํ•˜์ง€ ์•Š๋„๋ก ๋ณดํ˜ธํ•˜๋Š” ์—ญํ• 
  • ๋ถˆํ•„์š”ํ•œ ์ •๋ณด(์˜ˆ: createdAt, updatedAt, DB ID)๋ฅผ ์ œ๊ฑฐ ๊ฐ€๋Šฅ
  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ํ˜•์‹์œผ๋กœ ๊ฐ€๊ณต ๊ฐ€๋Šฅ
package com.example.library.dto.response;

import com.example.library.entity.Book;
import lombok.Getter;

@Getter
public class BookResponseDto {
    private Long id;
    private String title;
    private String author;
    private int price;

    public BookResponseDto(Book book) {
        this.id = book.getId();
        this.title = book.getTitle();
        this.author = book.getAuthor();
        this.price = book.getPrice();
    }
}

โœจ ์‚ฌ์šฉ ์˜ˆ์‹œ

@GetMapping("/books/{id}")
public ResponseEntity<BookResponseDto> getBookById(@PathVariable Long id) {
    BookResponseDto responseDto = bookService.getBookById(id);
    return ResponseEntity.ok(responseDto);
}

๐Ÿ‘‰ ์ฑ… ์ •๋ณด๋ฅผ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๊ธฐ ์ข‹๊ฒŒ ๊ฐ€๊ณตํ•ด์„œ ์‘๋‹ต

  • id๋ฅผ ํฌํ•จํ•˜์—ฌ ์ฑ…์˜ ์ •๋ณด๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Œ

๐Ÿ”ฅ DTO๋ฅผ ๋‚˜๋ˆ„๋Š” ์ด์œ 

๊ตฌ๋ถ„ Request DTO Response DTO

์—ญํ•  ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋Š” ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค„ ๋ฐ์ดํ„ฐ
์‚ฌ์šฉ ์˜ˆ์‹œ POST /books GET /books/{id}
์œ ํšจ์„ฑ ๊ฒ€์‚ฌ @Valid ์‚ฌ์šฉ ๊ฐ€๋Šฅ ํ•„์š” ์—†์Œ
๋ณ€ํ™˜ ๋ชฉ์  toEntity() ๋ฉ”์„œ๋“œ๋กœ ์—”ํ‹ฐํ‹ฐ ๋ณ€ํ™˜ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๊ฐ€๊ณต
๋ณด์•ˆ DB ID ๋…ธ์ถœ ํ•„์š” ์—†์Œ ๋ถˆํ•„์š”ํ•œ ํ•„๋“œ ์ˆจ๊น€ ๊ฐ€๋Šฅ

โœ… ์ •๋ฆฌ

  1. Request DTO: ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•˜๊ณ  ์—”ํ‹ฐํ‹ฐ๋กœ ๋ณ€ํ™˜
  2. Response DTO: ์—”ํ‹ฐํ‹ฐ ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๊ธฐ ์ข‹์€ ํ˜•ํƒœ๋กœ ๊ฐ€๊ณต
๋ฐ˜์‘ํ˜•