[Spring Boot] DTO

handa·2024년 12월 18일
0
post-thumbnail

1. DTO

DTO(Data Transfer Object)는 계층 간 데이터 전송에 사용되는 객체입니다. 주로 컨트롤러, 서비스, 리포지토리 계층 간 또는 클라이언트와 서버 간 데이터를 교환하기 위해 사용됩니다. DTO는 데이터를 담는 데 집중하며, 비즈니스 로직을 포함하지 않습니다.


2. DTO를 사용하는 이유

  1. 캡슐화된 데이터 전달
    • 엔티티 클래스와 분리된 구조로, 필요한 데이터만 전송하거나 노출할 수 있습니다.
    • 예: 사용자의 민감한 정보(비밀번호 등)를 제외하고 안전하게 데이터를 전달.
  2. 엔티티 보호
    • 엔티티 클래스는 데이터베이스와 밀접하게 연관되어 있어, 이를 직접 노출하면 구조가 변경될 경우 API가 깨질 가능성이 있습니다.
    • DTO는 엔티티를 외부에 직접 노출하지 않도록 보호합니다.
  3. 유연성
    • 엔티티와 상관없이 API 요청 및 응답의 데이터 구조를 자유롭게 정의할 수 있습니다.
    • 예: 클라이언트의 요청에 따라 특정 필드만 포함하거나 가공된 데이터를 제공.
  4. 레이어 간 의존성 제거
    • DTO를 사용하면 서비스 계층에서 엔티티와 데이터 전송을 분리할 수 있습니다.
    • 결과적으로, 데이터베이스 구조 변경이 컨트롤러와 클라이언트에 영향을 미치지 않습니다.
  5. 입력 및 출력 데이터 검증
    • DTO는 특정 요청의 데이터 검증(@Valid, @NotNull 등)을 포함하여 클라이언트 입력 데이터의 무결성을 보장합니다.
    • 출력 데이터를 포맷팅하거나 특정 요구 사항에 맞춰 데이터를 가공할 수 있습니다.

3. DTO의 활용 방식

  1. 요청 데이터 처리(Request DTO)
    • 클라이언트에서 서버로 전송되는 데이터를 캡슐화.
    • 주로 입력 데이터의 유효성 검증에 사용.
@Getter
@Setter
public class CreateQuestionRequest {
    @NotBlank(message = "제목은 필수 항목입니다.")
    private String subject;

    @NotBlank(message = "내용은 필수 항목입니다.")
    private String content;
}
  1. 응답 데이터 처리(Response DTO)

    • 서버에서 클라이언트로 전송되는 데이터를 캡슐화.
    • 엔티티를 가공하거나 필요한 데이터만 선택적으로 노출.
@Getter
@Setter
public class QuestionResponse {
    private Long id;
    private String subject;
    private String content;
    private LocalDateTime createdDate;
}
  1. 양방향 변환(엔티티 <-> DTO)

    • DTO와 엔티티 간 변환 로직은 서비스 계층이나 별도의 Mapper 클래스를 사용해 구현.
public class QuestionMapper {
    public static Question toEntity(CreateQuestionRequest dto) {
        Question question = new Question();
        question.setSubject(dto.getSubject());
        question.setContent(dto.getContent());
        return question;
    }

    public static QuestionResponse toDTO(Question entity) {
        QuestionResponse response = new QuestionResponse();
        response.setId(entity.getId());
        response.setSubject(entity.getSubject());
        response.setContent(entity.getContent());
        response.setCreatedDate(entity.getCreatedDate());
        return response;
    }
}

DTO의 사용 흐름

  1. 클라이언트 요청 (Request DTO)

    • 클라이언트가 보낸 데이터를 @RequestBody로 컨트롤러에서 받음.
@PostMapping("/questions")
public ResponseEntity<Void> createQuestion(@RequestBody @Valid CreateQuestionRequest dto) {
    questionService.createQuestion(dto);
    return ResponseEntity.status(HttpStatus.CREATED).build();
}
  1. 서비스 계층에서 엔티티와 DTO 변환

    • 요청 데이터를 엔티티로 변환하여 데이터베이스 작업 수행.
public void createQuestion(CreateQuestionRequest dto) {
    Question question = QuestionMapper.toEntity(dto);
    questionRepository.save(question);
}
  1. 클라이언트 응답 (Response DTO)

    • 가공된 데이터를 Response DTO로 변환 후 반환.
@GetMapping("/questions/{id}")
public ResponseEntity<QuestionResponse> getQuestion(@PathVariable Long id) {
    Question question = questionService.findById(id);
    return ResponseEntity.ok(QuestionMapper.toDTO(question));
}

Spring Boot에서 DTO는 데이터의 캡슐화, 보안 강화, 유지보수 용이성, 유연한 API 설계, 데이터 유효성 검증 등의 이점을 제공합니다. 따라서, 대부분의 실무 프로젝트에서 DTO는 필수적인 구성 요소로 사용됩니다.

profile
진짜 해보자

0개의 댓글