🔶 Entity, DTO, VO 알아보기
🔹Entity
Entity(엔터티)는 객체지향 프로그래밍과 데이터베이스 모델링 부문에서 비슷한 의미로 쓰인다.
나는 객체지향 프로그래밍을 공부중이므로, 객체지향 관점에서 Entity를 살펴보겠다.
객체지향 프로그래밍에서 "Entity(엔터티)"란 시스템 내에서 독립적으로 존재하며 식별 가능한 객체를 나타낸다.
엔터티는 현실 세계의 개념이나 사물을 프로그램 안에서 모델링한 것이다.
엔터티는 클래스(class)로 표현되며, 클래스는 해당 엔터티의 속성과 메서드를 정의한다.
엔터티 클래스는 객체(object)의 틀이 되며, 이를 기반으로 실제로 사용되는 객체를 생성하여 프로그램에서 활용할 수 있다.
즉, 실제 DB 테이블과 매핑되는 핵심 클래스로, 데이터베이스의 테이블에 존재하는 컬럼들을 필드로 가지는 객체이다.
예를 들어, 은행 시스템을 개발한다고 가정해보겠다. 이 시스템에서는 고객(Customer)과 계좌(Account)라는 두 가지 엔터티를 다루어야 할 것이다. 고객 엔터티는 이름, 주소, 전화번호 등과 같은 속성을 가지며, 로그인, 정보 수정 등의 동작을 수행할 수 있다. 계좌 엔터티는 계좌 번호, 잔액, 입출금 등의 속성을 가지며, 입금, 출금, 잔액 조회 등의 동작을 수행할 수 있다.
이러한 엔터티 클래스는 객체지향 프로그래밍에서 상속, 캡슐화, 다형성 등의 개념을 활용하여 설계되며, 객체들 간의 상호작용을 통해 시스템을 구축하고 확장할 수 있다.
▶️ Entity 클래스 사용규칙
- 상속을 받거나 구현체여서는 안되며, DB 테이블내에 존재하지 않는 컬럼을 가져서도 안된다.
- Entity 는 데이터베이스 영속성(persistent)의 목적으로 사용되는 객체이며, 요청(Request)이나 응답(Response) 값을 전달하는 클래스로 사용하는 것은 좋지 않다.
- 외부에서 Entity 클래스의 Data Field 에 접근하지 못하도록 제한해야 한다.
- Proxy 생성을 위해 기본 생성자는 필수이며, public(지양) 또는 protected 생성자이어야 함(private 사용불가)
- final, enum, interface, inner 클래스는 Entity로 사용불가
- setter 사용을 지양해야 한다.
- 무분별한 Setter 사용은 Entity 클래스의 Instance가 언제, 어디에서 변경되었는지 파악하기 어려우므로
일관성 유지를 위함.
- Setter 대신 Builder 패턴을 활용하면 멤버 변수가 많아져도 필요한 데이터만 filed에 넣는 것이 용이
(Entity 예시코드)
@Entity
@Table(name = "employee")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 필수 입력 & 10글자 초과 입력불가
@Column(nullable = false, length = 10)
private String name;
@Column
private int age; // 객체 이름과 다르게 column 이름 개별지정
@Column(name = "salary")
private int pay;
}
@Entity // 해당 클래스가 Entity클래스임을 알리는 역할
@Getter // 필드값 조회를 위한 Getter 자동 생성
@NoArgsConstructor(access = AccessLevel.PROTECTED)
// 파라미터 없는 기본 생성자 생성, 초기값이 final인 경우 컴파일 에러 발생
@Id // Entity의 Primary Key(기본키)값 지정
@GeneratedValue(strategy = GenerationType.IDENTITY)
// 기본키(PK) 값에 대한 생성 전략을 제공한다. @Id 와 함께 엔티티 또는 매핑된 슈퍼클래스의 기본 키 속성 또는 필드에 적용할 수 있다.
@Column(nullable = false, length = 10)
// nullable(Boolean, Optional)
- 역할: 해당 Field 값이 반드시 입력받아야 할지 여부 결정
- 기본값: true
🔹DTO(Data Transfer Object)
DTO는 객체지향 프로그래밍에서 데이터를 전달하기 위한 객체이다.
주로 데이터베이스와의 상호작용이나 서비스 간의 데이터 전송에 사용된다.
DTO는 데이터를 담는 목적으로 설계되며, 주로 속성만을 가지고 있고 메서드는 간단한 접근자(getter)와 설정자(setter)로 구성된다.
즉, 데이터 교환만을 위해 사용하므로 비지니스 로직을 갖지 않고, getter/setter 메소드만 갖는다.
또한, Controller 같은 클라이언트와 직접 마주하는 계층에서 DTO 를 사용하여 데이터를 요청/응답을 하며, 주로 View 와 Controller 사이에서 데이터를 주고받을 때 활용한다.
다음은 DTO의 예시코드이다. 사용자(User) 정보를 담는 UserDTO 클래스를 만들어 보겠다.
public class UserDTO {
private String name;
private String email;
private int age;
public UserDTO(String name, String email, int age) { // 생성자 생성 및 객체 초기화
this.name = name; // name, email, age 라는 속성 설정
this.email = email;
this.age = age;
}
// 위의 각 속성에 대한 Getter와 Setter 메서드
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
▶️ getter, setter 만드는 이유?
=> 클래스의 필드에 직접 접근을 막아 메서드를 통해 DTO 객체의 속성에 접근하고 값을 가져오거나 설정하기 위함.
이로 인해 데이터의 캡슐화와 접근 제어 가능.
- getter: 속성 값을 반환하는 메서드
- setter: 속성 값을 설정하는 메서드
🔹VO(Value Object)
VO는 값을 갖는 객체로서 불변성(Immutable)을 가지는 특징을 갖는 개념이다. VO는 주로 도메인 모델링이나 비즈니스 로직에서 사용되며, 데이터의 표현과 처리를 담당한다.
▶️ VO의 특성
1. 불변성(Immutable): VO 객체는 한 번 생성되면 내부의 데이터를 변경할 수 없다.
=> 객체의 안정성과 예측 가능성을 높이는데 도움
2. 값 기반: VO 객체는 주로 값(value)을 표현하는데 사용된다. 즉, 객체의 식별자가 아닌 내부의 데이터를 기준으로 동등성(equality)을 판단한다. 같은 값을 갖는 두 개의 VO 객체는 동등하다고 간주한다.
3. 도메인 모델링: VO는 주로 도메인 모델링에서 사용되며, 개념적인 의미를 가지는 객체로 사용된다.
예를 들어, 주소(Address), 날짜(Date) 등은 값으로 취급되어야 하는데, 이러한 개념들을 VO로 표현할 수 있다.
다음은 VO의 예시 코드이다. 주소(Address)를 표현하는 AddressVO 클래스를 만들어 보자.
public class AddressVO {
private final String city;
private final String street;
private final String zipCode;
public AddressVO(String city, String street, String zipCode) {
this.city = city;
this.street = street;
this.zipCode = zipCode;
}
public String getCity() {
return city;
}
public String getStreet() {
return street;
}
public String getZipCode() {
return zipCode;
}
}
위의 코드를 보면, 불변성을 가지기 위해 속성은 final 키워드로 선언되었고, 생성자를 통해 초기화되었다.
Getter 메서드를 통해 속성의 값을 읽을 수 있다.
그리고 VO는 getter 메소드는 가질수 있지만, setter 메소드는 가지지 않는다.(ReadOnly 특징을 가진다.)
출처: 뤼튼, https://heytech.tistory.com/274, https://dev-jwblog.tistory.com/148, https://rutgo-letsgo.tistory.com/306
'IT || 개발공부 > Spring' 카테고리의 다른 글
[Spring MVC] Unexpected character ('u' (code 117)): was expecting double-quote to start field name 오류 (0) | 2024.06.07 |
---|---|
[Spring] DDD설계와 SQL 중심 설계 (0) | 2023.11.09 |
[Spring] HTTP method에 대하여 (0) | 2023.11.06 |
[Spring] 스프링 빈 등록 후 의존성 주입해보기 (1) | 2023.11.06 |
[Spring boot] intelliJ로 Controller 생성 및 실행하기 (0) | 2023.11.02 |
댓글