Just Do IT!

DAO, DTO, Entity 차이 알아보기 본문

개발 공부/Spring

DAO, DTO, Entity 차이 알아보기

MOON달 2025. 2. 25. 17:17
728x90
반응형

데이터 흐름

직접 그려본 applicaton 흐름 (참고:https://cobi-98.tistory.com/61)

  1. 사용자가 브라우저에서 데이터를 입력하여 DTO 형태로 서버에 전송
  2. 서버는 이 DTO를 받아 DAO를 통해 데이터베이스에 저장
  3. 데이터를 조회할 때 DAO를 통해 데이터베이스에서 데이터를 가져와 DTO로 클라이언트에게 반환

 

Spring Boot 에서의 활용

  • Repository : DAO 역할을 한다
  • Controller : DTO를 받아 서비스 계층으로 전달하거나, 서비스 계층에서 받은 데이터를 DTO로 변환하여 클라이언트에게 반환한다

추가 구조 보러가기: https://daydream-sy.tistory.com/333

 

 

 


 

 

 

DTO (Data Tranfer Object)

  • 계층 간(Controller, View, Business Layer / Spring Boot에서는 뷰, 컨트롤러, 서비스, DAO, DB를 의미) 데이터 교환을 위해 사용되는 객체
  • 순수한 데이터 객체 : 비즈니스 로직 X, 데이터만 포함
  • getter/setter 메서드만 포함 : 주로 Java Beans 형태로 구현 => 로직을 가지지 않은 순수한 데이터 객체
    • setter를 가지고 있어 값이 변할 수 있다
  • 주로 비동기 처리를 할 때 사용
  • Controller layer에서 Response DTO 형태로 Client에 전달
  • 직렬화 가능 : 네트워크 통신에 적합
  • 데이터 캡슐화 : 여러 데이터를 하나의 객체로 묶어 전송
  • 한 개의 DTO를 사용하거나 두 개의 DTO(Request/ Response)를 사용한다.

사용 목적

  • 계층 간 (Controller, View, Business Layer) 데이터 전송
  • 네트워크 호출 최적화 : 여러 데이터를 한 번에 전송하여 호출 횟수 감소
  • API 응답이나 네트워크로 전송되는 데이터 표현

RequestDTO / ResponseDTO

  • requestDTO
    • 클라이언트로부터 전달받은 요청 데이터를 담고 있는 객체
    • 컨트롤러에서 사용되어 비즈니스 로직에서 필요한 데이터를 추출하여 서비스나 DAO에 전달하는 용도로 사용된다.
    • @RequestParam으로 데이터를 일일이 받을 필요 없이 객체 하나로 한꺼번에 받을 수 있다
    • Bean Validation, Controller에서 검증 기능을 분리할 수 있다
    • 엔티티 내부를 캡슐화할 수 있다 (엔티티의 값이 변경되지 않도록)
  • responseDTO
    • 비즈니스 로직에서 생성된 데이터를 클라이언트에 반환하기 위한 객체이며, 컨트롤러에서 생성되어 클라이언트에 반환된다.
    • 넘겨줄 필요가 없는 데이터를 보내지 않을 수 있다 (화면에 꼭 필요한 데이터만 보낼 수 있다)
    • 순환참조를 예방할 수 있다
    • 엔티티 내부를 캡슐화할 수 있다

예제

댓글(Comment) DTO

@Data
@Builder
public class BookCommentResponse {
    private Long id;
    private String comment;
    private Long userId;                    // 작성자 ID
    private String username;                // 작성자
    private String userProfile;     // 생성한 사람 프로필
    private Long likeCount;                 // 좋아요 수
    private Long bookId;                    // 문제집 ID
    private boolean isLiked;   // 사용자가 북마크했는지 여부

    @JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createdAt;        // 생성 날짜 (최신순 정렬 위해 필요)
}

→ request / response 두 DTO를 사용하였기에 response DTO만 예제로 적어두었다.

→ 댓글 관련 기능 구현할 때 사용하는 DTO이다.

 

 

 

 

 

 

 

 

 

DAO (Data Access Object)

  • 데이터베이스와 상호작용을 추상화하는 객체
    • 데이터 접근 추상화 : DB 접근 로직을 캡슐화한다
  • CRUD 작업 수행 : 데이터 생성, 조회, 수정, 삭제 기능 제공
  • 비즈니스 로직과 데이터 접근 로직 분리 : 관심사 분리 원칙을 따른다
  • 일관된 인터페이스 제공 : 데이터 소스와 상관없이 동일한 방식으로 데이터에 접근
  • 어플리케이션 호출을 데이터 저장 부분( Persistence Layer )에 매핑함으로써 DAO는 데이터베이스의 세부 내용을 노출하지 않고 특정 데이터 조작 기능을 제공
    • 단일 책임 원칙( Single Responsibilty Principle )에 기반
      • 객체 지향 프로그래밍에서 모든 컨텍스트( 클래스, 기능, 변수 등 )은 하나의 책임만 가져야 한다는 것이며, 이는 컨텍스트에 의해 완전히 캡슐화 되어야 한다는 것이다.
      • 그리고 모든 서비스들은 해당 책임에 맞춰 조정되어야 한다.
      • 다른 말로는 "클래스를 수정해야 할 이유는 오직 하나여야 한다"고 한다.

사용 목적

  • 데이터베이스 접근 로직 중앙화
  • 코드 재사용성 향상
  • 서비스 레이어와 데이터베이스 연결

예제

@Repository
public interface BookCommentRepository extends JpaRepository<BookComment, Long> {

    // 최신순 댓글 전체 조회
    Page<BookComment> findByBookIdOrderByCreatedAtDesc(Pageable pageable, Long bookId);

    // 유저 댓글 목록 조회
    Page<BookComment> findByUserIdOrderByCreatedAtDesc(Long userId, Pageable pageable);

}

→ Spring boot에서는 repository가 DAO 역할을 하기 때문에 repository 클래스가 예제이다.

→ DB와 상호작용해서 CRUD 작업을 수행한다.

 

 

 

 

 

 

 

Entity

  • 실제 DB의 테이블과 1:1로 매핑되는 클래스
  • DB의 테이블내에 존재하는 컬럼만을 속성(필드)으로 가져야 한다
  • Entity 클래스는 상속을 받거나 구현체여서는 안되며, 테이블내에 존재하지 않는 컬럼을 가져서도 안된다.

예제

public class BookComment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(updatable = false)
    private Long id;

    @Column(nullable = false)
    private String comment;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "book_id")
    private Book book;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    @CreatedDate
    @Column(name = "created_at")
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;

    @OneToMany(mappedBy = "commentId", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<BookCommentLike> commentLikes;

    public void updateComment(String comment) {
        this.comment = comment;
    }
}

 

 

 

 

 

 

 

 

Entity와 DTO Class 분리 이유

  • DB Layer와 View Layer 사이의 역할을 분리 하기 위해서
  • Entity 클래스는 실제 테이블과 매핑되어 만일 변경되게 되면 여러 다른 클래스에 영향을 끼치고, DTO 클래스는 View와 통신하며 자주 변경되므로 분리 해주어야 한다.
  • 결국 DTO는 Domain Model 객체를 그대로 두고, 복사하여 다양한 Presentation Logic을 추가한 정도로 사용한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Kernel 팀에서 프로젝트 실습 관련 토의를 하다가 문득 궁금해져서 블로그 글로 정리하게 되었다.

처음에 domain과 entity 분리의 이유부터 dto, dao가 무엇인지 등등...

그저 배운대로 domain 폴더에 request, response 생성하고 entity는 따로 entity 폴더에...

라고만 생각했었는데 본격적으로 자세히 찾아보고 공부해보니까 이제야 정리가 되는 기분이다.

한 번 정리했다고 끝이 아니라 누군가에게 설명할 수 있도록 열심히 복습해야겠다.

 

 

 

 

참고

https://velog.io/@chosj1526/VO-DAO-DTO-ENTITY%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%9E%A5%EB%8B%A8%EC%A0%90-%EB%B0%8F-%EC%B0%A8%EC%9D%B4#dao-data-access-object--%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%91%EA%B7%BC-%EA%B0%9D%EC%B2%B4

 

VO, DAO, DTO, ENTITY의 개념과 장단점 및 차이

DTO와 비슷하지만 차이점은 VO는 read only 속성을 갖는다.관계 데이터 베이스의 레코드에 대응되는 자바 클래스이다. (레코드 = row 한 줄)형태 : db 레코드를 구성하는 필드(=컬럼)들을 VO의 Attribute로

velog.io

https://velog.io/@cyseok123/Spring-Boot-JPA-Dto%EC%99%80-Entity%EB%A5%BC-%EB%B6%84%EB%A6%AC%ED%95%B4%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

 

[Spring Boot] JPA - Dto와 Entity를 분리해서 사용하기

보안 문제 Entity는 데이터베이스 테이블과 직접 매핑되어 있어, 불필요하거나 민감한 정보까지 모두 노출될 수 있습니다. 순환 참조 문제 Entity가 서로를 참조하는 양방향 관계일 경우, JSON 직렬

velog.io

https://velog.io/@haron/Spring-DAO-DTO-Entity-Class%EC%9D%98-%EC%B0%A8%EC%9D%B4

 

[Spring] DAO, DTO, VO, Entity Class의 차이

실제로 DB에 접근하는 객체이다.Persistence Layer(DB에 data를 CRUD하는 계층)이다.Service와 DB를 연결하는 고리의 역할을 한다.SQL를 사용(개발자가 직접 코딩)하여 DB에 접근한 후 적절한 CRUD API를 제공한

velog.io

기타 AI 답변 등

728x90