728x90
반응형
record의 구조 및 특징
// 레코드명(헤더) { 바디 }
public record Subin(String name, int age, String gender) { }
- 헤더에 나열된 필드 (String name, String age, String gender) = 컴포넌트
- 레코드의 각 필드(=헤더에 나열한 컴포넌트)는 private final
- 즉, 위의 예시는 이름은 Subin, name, age, gender를 private final 필드로 가진 레코드
- 레코드에서는 헤더에서 정의한 멤버만을 관리한다. => 내부에 멤버 변수 선언 불가. static 변수는 생성 가능.
- 레코드는 불변 객체로 abstract로 선언 불가. 묵시적으로 final로 선언. 한 번 정해진 값은 setter를 통해 변경할 수 없고, 상속도 할 수 없다.
- 컴파일러는 헤더를 통해 내부 필드를 추론하여 접근자, 생성자, toString, equals, hashCode를 명시적으로 선언하지 않아도 이를 자동으로 구현한다.
- 레코드는 개발자가 명시적으로 인스턴스 필드를 초기화하지 않아도 모든 필드를 초기화 할 수 있는 생성자 하나만을 자동으로 생성한다. = 컴팩트 생성자
- 보통 컴팩트 생성자는 입력 받은 데이터를 검증할 때 사용한다. (null 값 여부, 음수 여부 등을 확인하여 에러를 반환할 수 있다.)
- 예) 매개 변수 값이 null인지 체크하고, null인 경우 에러를 반환
// 레코드명(헤더) { 바디 }
public record Subin(String name, int age, String gender) {
// 컴팩트 생성자
public Subin {
Objects.requireNonNull(name);
Objects.requireNonNull(age);
Objects.requireNonNull(gender);
}
}
- 별도의 생성자가 필요한 경우 추가 가능하다.
// 레코드명(헤더) { 바디 }
public record Subin(String name, int age, String gender) {
// 컴팩트 생성자
public Subin {
Objects.requireNonNull(name);
Objects.requireNonNull(age);
Objects.requireNonNull(gender);
}
// 추가
public Subin(int age) {
this.name = "Subin";
this.age = age;
this.gender = "Female";
}
}
유의할 점
보일러 플레이트를 방지한다는 면에서 매력적이라 JPA의 entity로 쓰고 싶겠지만 record는 entity가 되기에는 부적절하다.
- 프록시 생성을 위해서 entity는 불변이어서는 안된다.
- 쿼리 결과 매핑 시 매개변수가 없는 생성자가 필요하다. 하지만 레코드는 매개변수가 없는 생성자를 제공하지 않는다. setter를 사용할 수 없기 때문에 모든 필드의 값을 입력해야 생성할 수 있다.
- 레코드의 getter는 필드명을 그대로 사용하기 때문에(예: age(), name()) 쿼리 결과 수행 후 접근이 어렵다.
- record는 DTO로 사용하는 것이 적절하다.
728x90
반응형