[게시판 프로젝트] ArticleRequest와 ArticleResponse를 사용하는 상황의 차이 이해하기, DTO를 따로 만들어 사용하는 이유

2024. 8. 26. 19:07웹 개발/프로젝트

 

요청 응답 DTO를 사용하는 상황의 차이를 이해하고,
왜 요청/응답을 DTO로 만들어서 사용하는지
그 이점과 예시를 알아보자

 

1. ArticleRequest: 클라이언트에서 서버로 데이터를 전송할 때 사용

  • 사용 목적
    • ArticleRequest는 주로 클라이언트(사용자)로부터 입력된 데이터를 서버로 전달받을 때 사용됩니다.
    • 예를 들어, 사용자가 게시글 작성 폼에 내용을 입력하고 제출할 때, 그 데이터는 ArticleRequest 객체로 매핑됩니다.
    • 즉, 사용자 입력 데이터를 서버가 받을 수 있도록 하기 위한 객체입니다.
  • 사용 예시
    • 게시글 작성: 사용자가 작성한 게시글의 제목, 내용 등을 서버로 전송할 때 ArticleRequest가 사용됩니다.
    • 게시글 수정: 기존 게시글을 수정하는 폼에서도 수정된 데이터를 받아올 때 사용됩니다.
@PostMapping("/form")
public String postNewArticle(ArticleRequest articleRequest, @AuthenticationPrincipal BoardPrincipal boardPrincipal) {
    articleService.saveArticle(articleRequest.toDto(boardPrincipal.toDto()));
    return "redirect:/articles";
}
  • 이 메소드에서 ArticleRequest는 사용자가 작성한 게시글 데이터를 받아오는 데 사용됩니다.

2. ArticleResponse: 서버에서 클라이언트로 데이터를 전송할 때 사용

  • 사용 목적
    • ArticleResponse는 서버에서 클라이언트로 데이터를 전송할 때 사용됩니다. 주로 서버가 클라이언트에게 특정 데이터를 제공할 때 이 객체를 사용하여 응답(response)을 만듭니다.
    • 데이터베이스에서 조회한 Article 객체나 비즈니스 로직을 통해 생성된 데이터를 클라이언트가 이해할 수 있는 형식으로 변환합니다.
  • 사용 예시
    • 게시글 조회: 서버가 특정 게시글의 내용을 클라이언트에게 반환할 때, 그 데이터를 ArticleResponse객체로 만들어 전달합니다.
    • 게시글 목록: 여러 게시글을 조회하여 목록으로 반환할 때, 각 게시글을 ArticleResponse 객체로 변환하여 전송합니다.
@GetMapping("/{articleId}")
public String article(@PathVariable Long articleId, ModelMap map) {
    ArticleWithCommentsResponse article = ArticleWithCommentsResponse.from(articleService.getArticleWithComments(articleId));
    map.addAttribute("article", article);
    map.addAttribute("articleComments", article.articleCommentsResponse());
    map.addAttribute("totalCount", articleService.getArticleCount());
    map.addAttribute("searchTypeHashtag", SearchType.HASHTAG);
    return "articles/detail";
}
  • 이 메소드에서 ArticleResponse (또는 ArticleWithCommentsResponse)는 데이터베이스에서 가져온 게시글 데이터를 클라이언트에게 전달하기 위해 사용됩니다.

응답/요청 DTO를 따로 만들어 사용하는 이유

응답(Response)과 요청(Request) DTO(Data Transfer Object)를 따로 만들어 사용하는 이유는 애플리케이션의 계층 구조를 명확하게 하고, 각 계층 간의 데이터 전송을 효과적으로 관리하기 위해서입니다. 이러한 접근 방식은 여러 가지 이점을 제공합니다.

 

1. 책임 분리 (Separation of Concerns)
  • 요청(Request) DTO는 클라이언트가 서버로 전송하는 데이터를 캡슐화합니다. 이 DTO는 주로 사용자의 입력 데이터(예: 폼 데이터)를 받아서 서버로 전달하는 역할을 합니다.
  • 응답(Response) DTO는 서버가 클라이언트로 전송하는 데이터를 캡슐화합니다. 이 DTO는 주로 서버에서 처리된 결과나 데이터베이스에서 조회된 데이터를 클라이언트에게 반환하는 데 사용됩니다.
  • 이처럼 요청과 응답을 분리하면 각 DTO가 명확한 역할을 가지게 되어 코드의 가독성과 유지보수성이 향상됩니다.

 

2. 보안 (Security)
  • 클라이언트가 서버로 전송하는 데이터와 서버가 클라이언트로 보내는 데이터는 서로 다를 수 있습니다. 예를 들어, 클라이언트가 보내야 할 정보는 게시글의 제목과 내용이지만, 서버가 반환하는 데이터에는 게시글의 작성일이나 작성자 정보 등이 추가될 수 있습니다.
  • 요청과 응답 DTO를 분리하면 클라이언트가 불필요하게 민감한 데이터를 전달하지 않도록 하거나, 서버에서 민감한 데이터를 클라이언트로 반환하지 않도록 할 수 있습니다.

 

3. 유연성 및 확장성 (Flexibility and Scalability)
  • 요청과 응답 DTO를 분리하면, 서버의 내부 구조나 데이터베이스 스키마에 변화가 있어도 클라이언트와의 인터페이스를 안정적으로 유지할 수 있습니다.
  • 예를 들어, 서버 쪽에서 데이터베이스 스키마가 변경되어도, 요청이나 응답 DTO를 적절히 조정하면 클라이언트와의 인터페이스를 그대로 유지할 수 있습니다.

 

4. 데이터 검증 (Validation)
  • 요청 DTO는 클라이언트로부터 전달된 데이터를 서버에서 검증하는 데 사용될 수 있습니다. 이 과정에서 필요한 데이터 유효성 검사를 요청 DTO에서 수행할 수 있습니다.
  • 응답 DTO는 서버에서 클라이언트로 데이터를 전달하기 전에 필요한 가공을 수행할 수 있습니다.

 

5. 명확한 API 설계
  • 요청과 응답 DTO를 분리하여 사용하면 API 설계가 명확해집니다. API 사용자(클라이언트)에게 어떤 데이터가 필요한지, 그리고 어떤 데이터를 반환할지를 명확하게 정의할 수 있습니다.

 

요청(Request) DTO

public record ArticleRequest(
    String title,
    String content,
    String hashtag
) {
    public static ArticleRequest of(String title, String content, String hashtag) {
        return new ArticleRequest(title, content, hashtag);
    }

    public ArticleDto toDto(UserAccountDto userAccountDto) {
        return ArticleDto.of(
            userAccountDto,
            title,
            content,
            hashtag
        );
    }
}
  • 클라이언트 → 서버: 클라이언트가 서버로 보내는 게시글의 제목, 내용, 해시태그 정보를 캡슐화합니다.
  • toDto 메소드: ArticleRequest를 ArticleDto로 변환하여 서비스 계층으로 전달합니다.

응답(Response) DTO

public record ArticleResponse(
    Long id,
    String title,
    String content,
    String hashtag,
    String author,
    LocalDateTime createdAt
) {
    public static ArticleResponse from(Article article) {
        return new ArticleResponse(
            article.getId(),
            article.getTitle(),
            article.getContent(),
            article.getHashtag(),
            article.getAuthor(),
            article.getCreatedAt()
        );
    }
}
  • 서버 → 클라이언트: 서버가 클라이언트로 반환하는 게시글 ID, 제목, 내용, 해시태그, 작성자, 작성일 등의 정보를 캡슐화합니다.
  • from 메소드: 데이터베이스에서 가져온 Article 엔티티를 ArticleResponse로 변환하여 클라이언트에게 반환합니다.