
Record란 무엇일까?
불변 객체
- Java로 프로젝트 진행 시 DB결과, 쿼리 결과, 서비스 정보와 같은 데이터를 단순히 담기 위한 객체를 생성하게 되는데 대부분 불변 객체를 사용
- 불변 객체를 사용 함으로써 내부 필드값 불변 보장 -> 유지보수에서 많은 이점을 챙길 수 있음
Person 이라는 불변 객체를 만든다고 가정
- name과 address라는 불변 객체를 담기 위함
- 하지만 equals, hashCode, getter, toString 등 너무나 많은 메서드를 정의해줘야 한다는 단점
- 소위 말하는 Bolierplate Code가 많다.
- 최소한의 수정으로 여러 곳에서 자주 반복되는 코드
- 생성자, equals 등 메서드
- 만일 필드값이 추가된다면?
- 기존에 정의된 Bolierplate 코드들이 모두 수정해야 하는 문제 필요
- 단순히 name과 address의 속성만 담는 객체를 기대했는데, 너무 많은 메서드들이 생성되다 보니 의미가 퇴색될 수 있음
public class Person {
private final String name;
private final String address;
public Person(String name, String address) {
this.name = name;
this.address = address;
}
레코드의 등장
public record Person(String name, String address) {
}
- 위 record와 이전 코드와 동일
- 위처럼 정의해도 위 코드에 있던 Bolierplate 코드들이 자동으로 정의됨
어떻게 사용할까?
선언
public record Person(String name, String address) {
private static final String value = "something";
}
- 레코드는 선언과 동시에 내부에서 사용할 필드값들을 정의 해야함
- 내부 필드 선언 시 에러 발생
- static으로 된 정적 필드 추가 가능
호출
public record Person(String name, String address) {
}
Person person = new Person("타칸", "루터회관");
String name = person.name();
String address = person.address();
- 일반 객체처럼 사용
- 필드 접근 시
get
이 붙지 않음
메서드 재정의
public record Person(String name, String address) {
@Override
public String toString() {
return "닝겐입니다.";
}
}
- Bolierplate 자동 생성하지만 재정의 하고자 하는 메서드는 재정의 해주면 됨
생성자
일반 객체
public class Person {
private final String name;
private final String address;
public Person(String name, String address) {
this.name = name;
this.address = address;
}
Record
public record Person(String name, String address) {
public Person {
validate(name, address);
}
}
- Record는 일반 객체와 다르게 Compact 생성자 기능 제공
- 생성자에서 사용하는 파라미터와 레코드 필드 값이 서로 동일한 경우 생략할 수 있음
- 초기화 로직은 마지막에 자동 호출(this.name = name)
왜 getXXX를 안쓸까??
- 레코드는 일반 객체의 문제점을 해결하기 위해 등장한 것이 아니기 때문
- 즉 레코드가 일반 객체의 컨벤션을 따를 필요는 없다고 볼 수 있음
- 오라클 공식 문서 JEP 395
- 레코드를 선언할 때 간결성을 제공하지만 보일러 플레이트와의 전쟁을 선언하는 것은 목표가 아니다.
- 특히 자바빈 명명 규칙을 사용하는 일반 클래스의 문제를 해결하는 것은 목표가 아니다.
Lombok을 사용하면 안될까?
@Data
@AllArgsConstructor
public class Person {
private final String name;
private final String address;
}
public record Person(String name, String address) {
}
- Lombok을 사용하면 보일러 플레이트 정리해주는 것과 유사한 기능
- 가독성 측면 : 레코드가 좀 더 간결
- 기능적 측면 : Data, 생성자, SLF4J와 같은 추가적 다양한 기능 제공
- 의존성 측면
- 롬복 : 외부 라이브러리기 때문에 별도 라이브러리 추가 필요, IDEA도 그에 맞는 플러그인 설치
- Record : JDK16 이상 포함되어 별도 설치 없이 사용할 수 있음
- 상황에 따라 사용
- 간결하고 의존성 없는 프로젝트 -> 레코드가 더 나을듯
- 기능과 유연성 -> 롬복이 더 나을듯
도메인 객체로 사용할 수 있을까?
- 지양하는 것이 좋다
- 오라클 공식 문서 JEP 395
- 레코드는 불변 데이터를 전달하기 위한 캐리어다.
- 단순한 값의 집합을 표현하는 객체 지향적인 구성을 고안한다.
- 개발자가 확장 가능한 동작보다는 불변의 데이터 모델링에 집중할 수 있도록 도와준다.
- 따라서 도메인 객체는 단순 데이터를 가지고 있는 것 뿐만 아닌 비즈니스 로직이 들어가기 때문에 단순히 데이터만 전달하기 위해 사용되는 레코드의 목적성에는 부합하지 않는다고 볼 수 있음
- 도메인 객체 보다는 DTO에서 활용하는 것이 좋을 듯