레코드란?
레코드가 무엇인지 모르는 분들을 위해 간략히 설명을 하자면 다음과 같다.
1. 불변(immutable) 데이터 객체를 쉽게 생성할 수 있게 돕는 새로운 타입의 클래스 파일이다.
2. JDK 16에서 정식 스펙으로 포함되었기 때문에 프로젝트에서 사용하기 위해선 build.gradle에서 반드시 16이상의 자바 버전을 맞추어 줘야한다.
기존의 불변 데이터 객체를 만들기 위해선 class를 하나 생성하고 여러 작업을 해줘야하며 그로 인해 생기는 불편한 점들이 다수 있었는데 정리해 보자면 다음 코드를 보면서 설명하겠다.
일반 객체 예시
@Getter
@Setter
@NoArgsConstructor
public class PeopleDTO {
@Getter
@Setter
public static class SavePeopleDTO{
private String id;
private String name;
private Integer age;
public People toEntity(){
return People.builder()
.name(name)
.age(age)
.build();
}
}
}
위 클래스에서 상태를 관리해야하는 필드값은 총 3개이다.
이를 불변객체로 만들기 위해선 아래의 목차들을 지켜야한다.
- 모든 필드변수에 final을 사용하여 명시적으로 정의한다.
- 필드 값을 모두 포함한 생성자가 필요하다.
- 모든 필드에 대해 접근자가 필요하다.
- 상속을 막기위해 클래스 자체에 final을 선언하기도 한다.
하나의 일반 객체를 불변 객체로 변환시키기 위해 상당히 여러 제약이 존재한다.
하지만 정식으로 출시된 recode 타입을 쓰면 해당작업들의 불편함을 개선할 수 있다.
레코드 타입으로 객체를 생성할 경우의 이점은 다음과 같다.
- 객체 내부의 멤버 변수들은 불변값으로 생성된다.
- 간결한 방식으로 동일한 불변 데이터 객체를 정의할 수 있다.( 이름(클래스명),헤더(필드 변수 1, 필드 변수2),바디({}) )
- 컴파일러는 헤더를 통해 내부 필드값을 알 수 있다.(생성자를 작성하지 않아도된다)
DTO의 타입으로 레코드가 적절한가?
DTO의 경우 값의 이동이 있을 경우 중간 역할을 하기 때문에 대부분 역할이 명확하다.
예를 들어 회원가입 관련 DTO가 있다고 생각해보자. 회원가입의 경우 회원 Entity자체의 요구사항이 변하지 않는 이상 DTO의 내부 필드가 변환될 일이 없다. 그렇기 때문에 불변 객체로 작성하여도 무방하다.
recode 타입 객체 예시
@NoArgsConstructor
public static record MemberSignUpDto(@NotBlank(message = "아이디를 입력해주세요") @Size(min = 7, max = 25, message = "아이디는 7~25자 내외로 입력해주세요")
String username,
@NotBlank(message = "비밀번호를 입력해주세요")
@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,30}$",
message = "비밀번호는 8~30 자리이면서 1개 이상의 알파벳, 숫자, 특수문자를 포함해야합니다.")
String password,
@NotBlank(message = "닉네임을 입력해주세요.")
@Size(min=2, message = "닉네임이 너무 짧습니다.")
@NotBlank String nickName,
@NotNull(message = "이메일을 입력해주세요")
@Email
String email) {
public Member toEntity() {
return Member.builder().username(username).password(password).nickname(nickName).email(email).build();
}
}
이 처럼 객체의 필드가 한정적이고 불변할거라는 확신이 있는 DTO라면 recode타입으로 작성하는게 좋다고 생각한다.
또한 지금 예시에서는 Validation의 어노테이션을 사용하여 값의 제한을 두었지만 recode 타입의 객체일 경우 기본적으로 값을 제한할 수 있기 때문에 해당 방법을 사용하여도 되는 이점을 얻을 수 있다.
위의 DTO에서 message 필드의 길이제한부분만 따온예시
@NoArgsConstructor
public static record MemberSignUpDto(String username){
public MemberSignUpDto{
if(username.length()<7||username.length()>25){
throw new IllegalArgumentException("Username length can be 7~25");
}
}
}
결론
결과적으로 DTO는 값의 중간자이기 때문에 목적별로 생성된다. 그렇기 때문에 목적이 명확하고 불변을 확신하는 DTO는 일반적인 객체로 생성하기 보다는 recode타입으로 생성하는 것이 좋다고 생각한다. 그리고 DTO이기 때문에 상속할 일도 사실 없다고 본다.
'Java' 카테고리의 다른 글
==, equlas() (0) | 2024.01.04 |
---|---|
equals()와 hashCode() (1) | 2024.01.03 |
HashTable vs ConcurrentHashMap (3) | 2023.12.26 |
[Java] Record 와 스프링에서의 사용 (1) | 2023.11.11 |
[Java] Wrapper Class 주의점 (0) | 2023.09.26 |