Spring Boot JPA에서 사용하는 Entity와 DTO의 차이점을 설명한다.
1. Entity
Entity 클래스는 실제 DataBase의 테이블과 1 : 1로 매핑 되는 클래스로, DB의 테이블내에 존재하는 컬럼만을 속성(필드)으로 가져야 한다.
Entity 클래스는 상속을 받거나 구현체여서는 안되며, 테이블내에 존재하지 않는 컬럼을 가져서도 안된다.
Entity 클래스에 대하여 설명해보자면
Entity는 마치 데이터베이스의 테이블과 같은 구조로 작성하는 클래스이다.
엔티티 클래스는 Spring Data JPA에서 반드시 @Entity라는 어노테이션을 추가해야만하고, @Entity는 해당 클래스가 엔티티를 위한 클래스이며, 해당 클래스의 인스턴스들이 JPA로 관리되는 엔티티 객체라는 것을 의미한다.
Entity 클래스 생성방법이다.
엔티티로 지정한 클래스의 예제 코드 1
@Entity//엔티티 클래스 해당 클래스의 인스턴스들이 JPA로 관리되는 엔티티 객체
@Table(name = "tbl_memo")
@ToString
@Getter //Lombok의 Getter 메서드 생성
@Builder //객체를 생성할 수 있게 처리
@AllArgsConstructor // @Builder를 사용하기 위해서 추가 항상 NoArgsConstructor 랑 같이 추가
@NoArgsConstructor // @Builder를 사용하기 위해서 추가
public class Memo {
@Id// primary Key
@GeneratedValue(strategy = GenerationType.IDENTITY)//자동으로 생성되는 번호 -> PK를 자동으로 생성할 때 사용
private Long mno;
@Column(length = 200, nullable = false)
private String memoText;
}
어노테이션 설명
- @Entity : 엔티티 클래스 해당 클래스의 인스턴스들이 JPA로 관리되는 엔티티 객체로 @Entity가 있는 클래스의 멤버 변수에 따라서 자동으로 칼럼들이 생성
- @Table : @Entity 어노테이션과 같이 사용할 수 있는 어노테이션으로 데이터베이스상에서 엔티티 글래스를 어떠한 테이블로 생성할 것인지에 대한 정보를 담기 위한 어노테이션, name을 지정하여 원하는 테이블 이름으로 생성도 가능
- @ToString : LOMBOK 라이브러리가 제공하는 toString()메소드 자동 생성
- @Getter : LOMBOK 라이브러리가 제공하는 getter()메소드 자동 생성 -> @Setter를 추가하지 않은 이유는 Entity클래스에 setter()메소드를 추가하지 않는 것이 원칙임 그 이유는 setter()메소드를 이용하여 데이터가 조작될 수 있기 때문에 불가피한 상황이 아니라면 거의 사용하지 않는 것을 권함
- @Builder : LOMBOK 라이브러리가 제공하는 build 생성 패턴 사용할 수 있게 해줌
- @AllArgsConstructor : 모든 필드에 대해서 생성자 자동 생성
- @NoArgsConstructo : 파라미터가 없는 생성자 자동 생성
- @Id : @Entity가 붙은 클래스는 Primary Key(PK)에 해당하는 특정 필드를 @Id로 지정해야만 함 @Id가 사용자가 입력하는 값을 사용하는 경우가 아니면 자동으로 생성되는 번호를 사용하기 위해서 @GeneratedValue라는 어노테이션을 활용해야함
- @GeneratedValue(strategy = GenerationType.IDENTITY) : PK를 자동으로 생성하고자 할 때 사용함(키 생성 전략)
- @Column : 추가적인 필드(컬럼) 이 필요한 경우에 추가
추가적으로 같은 컬럼을 여러 엔티티 클래스가 사용할 수 있는 방법은
하나의 엔티티 클래스에 공통 컬럼을 지정하고, 그 컬럼을 사용하고 싶은 엔티티 클래스에 공통 컬럼을 가지고 있는 클래스를 확장하는 것이다.
엔티티로 지정한 클래스의 예제 코드 2
1. 공통 컬럼을 가지고 있는 클래스
@MappedSuperclass //어노테이션이 적용된 클래스는 테이블로 따로 생성되지 않음
//AuditingEntityListener : JPA내부에서 엔티티 객체가 생성/변경되는 것을 감지하는 역할
@EntityListeners(value = {AuditingEntityListener.class})
@Getter
abstract class BaseEntity {
@CreatedDate //JPA에서 엔티티의 생성 시간을 처리
@Column(name = "regdate", updatable = false)
private LocalDateTime regDate;
@LastModifiedDate //JPA에서 최종 수정시간을 자동으로 처리하는 용도
@Column(name = "moddate")
private LocalDateTime modDate;
}
2. 공통컬럼을 사용하고 싶은 엔티티 클래스
@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
// BaseEntity에 regdate, moddate가 존재 GuestBook이 상속받게 되면 regdate, moddate 자동으로 컬럼이 생성됨
public class GuestBook extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long gno;
@Column(length = 100, nullable = false)
private String title;
@Column(length = 1500, nullable = false)
private String content;
@Column(length = 50, nullable = false)
private String writer;
//원래 Entity 클래스는 set기능을 만들지 않는 것이 원칙
public void changeTitle(String title){
this.title = title;
}
public void changeContent(String content){
this.title = content;
}
}
-> 2. 공통컬럼을 사용하고 싶은 엔티티 클래스 GuestBook 클래스에서 공통 컬럼을 가지고 있는 클래스 BaseEntity클래스를 상속받게 되면 자동으로 regdate컬럼과, moddate컬럼이 생성된다.
이어서 바로 DTO에 대한 설명이다.
2. DTO(Data Transfer Object)
DTO(Data Transfer Object)는 데이터 전송(이동) 객체라는 의미를 가지고 있다.
DTO는 주로 비동기 처리를 할 때 사용한다.
DTO는
계층간 데이터 교환을 위한 객체(Java Beans)이다.
DB의 데이터를 Service나 Controller 등으로 보낼 때 사용하는 객체를 말한다.
즉, DB의 데이터가 Presentation Logic Tier로 넘어올때는 DTO로 변환되어 오고가는 것이다.
로직을 갖고 있지 않는 순수한 데이터 객체이며, getter/setter 메서드만을 갖는다.
또한 Controller Layer에서 Response DTO 형태로 Client에 전달한다.
* 유저가 입력한 데이터를 데이터베이스에 저장할 시
- 화면에서 데이터를 입력하여 form에 있는 데이터를 DTO에 담아서 Service나 Controller 에 넘김
- DTO를 받은 서버가 DAO를 이용하여 데이터베이스에 저장함
DTO로 지정한 클래스의 예제 코드
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
// GuestbookDto는 엔티티 클래스인 Guestbook과 거의 동일한 필드들을 가지고 있고,
// getter/setter 을 통해 자유롭게 값을 변경할 수 있는 점이 장점
public class GuestbookDTO {
private Long gno;
private String title;
private String content;
private String writer;
private LocalDateTime regDate, modDate;
}
DTO는 더 별게 없다. GuestBook Entity클래스에서 컬럼들을 선언만 하면 된다.
LOMBOK에서 제공해주는 어노테이션 @Data를 추가해주면 @Getter/Setter, @ToString 등등.. 자동생성된다.
Entity와 다른 점은 Setter가 추가되었다는 것 인데, DTO는 데이터베이스와 직접 연결하여 작업하지 않기 때문에 Service단에서 set을 이용하여 데이터를 수정할 수 있도록 편리를 제공한다.
부가적으로 DTO와 VO의 차이점을 설명해보겠다!
3. DTO와 VO 차이점
VO는 DTO와 동일한 개념이지만 read only 속성을 갖는다.
VO는 특정한 비즈니스 값을 담는 객체이고, DTO는 Layer간의 통신 용도로 오고가는 객체를 말한다.
VO(Value Object)는 말 그대로 값 객체라는 의미를 가지고 있다.
VO의 핵심 역할은 equals()와 hashcode() 를 오버라이딩 하는 것이다.
VO 내부에 선언된 속성(필드)의 모든 값들이 VO 객체마다 값이 같아야, 똑같은 객체라고 판별한다.
DTO는 Getter와 Setter를 가질 수 있으며, VO는 테이블 내에 있는 속성 외에 추가적인 속성을 가질 수 있으며, 여러 테이블(A, B, C)에 대한 공통 속성을 모아서 만든 BaseVO 클래스를 상속받아서 사용할 수도 있다.
4. Entity와 DTO의 차이점
DTO는 엔티티 객체와 달리 각 계층끼리 주고받는 우편물이나 상자의 개념이다. 순수하게 데이터를 담고 있다는 점에서는 엔티티 객체와 유사하지만, 목적 자체가 데이터의 전달이므로 읽고, 쓰는 것이 모두 허용되는 점이 가능하고 일회성으로 사용되는 성격이 강하다.
JPA를 이용하게 되면 엔티티 객체는 단순히 데이터를 담는 객체가 아니라 실제 데이터베이스와 관련이 있고, 내부적으로 엔티티 매니저(Entity Manager)가 관리하는 개체이다. DTO가 일회성으로 데이터를 주고받는 용도로 사용되는 것과 달리 생명주기도 전혀 다르기 때문에 분리해서 처리하는 것을 권장한다.
DTO를 사용하면 엔티티 객체의 범위를 한정 지을 수 있기 때문에 좀 더 안전한 코드를 작성할 수 있고, 화면과 데이터를 분리하려는 취지에도 좀 더 부합하다. 다만, DTO를 사용하는 경우 가장 큰 단점은 Entity와 유사한 코드를 중복으로 개발한다는 점과 엔티티 객체를 DTO로 변환하거나 반대로 DTO 객체를 엔티티로 변환하는 과정이 필요하다는 것이다.
5. DAO(Data Access Object)
데이터베이스에 data에 접근하기 위한 객체. 데이터베이스에 접근하기 위한 로직 & 비지니스 로직을 분리하기 위해 사용됨
-> mapper 에서 DAO를 이용하여 데이터에 값을 넣음
'Spring Boot' 카테고리의 다른 글
[Spring Boot]ResponseEntity (0) | 2021.11.28 |
---|---|
[Spring Boot] JPQL, Repository 확장 (0) | 2021.11.07 |
[Spring Boot] Spring Data JPA (0) | 2021.10.23 |
[Spring Boot] RedirectAttributes, FlashAttributes (0) | 2021.10.01 |