Record
Java를 8과 11 버전만 사용하다 보니 그 이후 버전에서 추가된 기능들이 익숙하지 않아서 정리해 보았습니다. 이번 글에서는 Java 14에서 처음 도입된 Record에 대해 알아보려고 합니다. Record는 불변(immutable) 데이터를 간편하게 표현할 수 있는 기능인데요, 그 목적과 특징, 그리고 몇 가지 제약 사항까지 함께 살펴보겠습니다.
레코드(Record)의 등장 배경
Java 14 이전에는 데이터를 저장하고 전달하기 위해 클래스를 만들 때 반드시 boilerplate 코드를 작성해야 했습니다. 예를 들어, equals, hashCode, toString 메서드를 일일이 오버라이드하고 생성자를 작성해야 하는 번거로움이 있었죠.
이러한 반복적인 작업은 실수를 유발하기 쉽고, 클래스의 본래 목적도 흐려지게 만들었습니다.
단순히 데이터를 저장하려는 용도의 클래스인데도 불필요한 코드가 많아져서 복잡해 보이는 경우가 많았습니다.
Record의 목적
이러한 문제를 해결하기 위해 Java 14부터 record 키워드가 등장했습니다. 레코드는 불변 데이터 객체를 위해 설계된 간단한 구조입니다. 주목할 점은 레코드를 선언하기만 하면 컴파일러가 자동으로 필요한 메서드와 필드를 생성해 준다는 것입니다.
Record 선언 방법
일반 클래스와 다르게 Record는 매우 간결하게 선언할 수 있습니다.
아래의 예제를 보세요.
public record Person(String name, String address) {}
이 코드만으로도 다음과 같은 코드가 자동으로 생성됩니다.
- private final 필드
- 모든 필드를 받는 public 생성자
- 필드 이름과 동일한 getter 메서드 (예: name(), address())
- equals(), hashCode(), toString() 메서드
Record와 일반 클래스 비교
일반 클래스의 문제점
아래는 Java 14 이전에 사용하던 클래스를 예로 든 것입니다.
public class Person {
private final String name;
private final String address;
public Person(String name, String address) {
this.name = name;
this.address = address;
}
@Override
public int hashCode() {
return Objects.hash(name, address);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Person)) return false;
Person other = (Person) obj;
return Objects.equals(name, other.name) && Objects.equals(address, other.address);
}
@Override
public String toString() {
return "Person{name='" + name + "', address='" + address + "'}";
}
}
레코드로 변환하면?
위의 클래스를 Record로 바꾸면 코드가 이렇게 간단해집니다.
public record Person(String name, String address) {}
단 1줄로 동일한 기능을 제공하며, 코드의 가독성이 훨씬 좋아졌습니다.
Record의 주요 특징
1.생성자
각 필드를 받는 public 생성자가 자동으로 만들어집니다.
Person person = new Person("John Doe", "123 Street");
2. Getter 메서드
필드 이름과 동일한 getter가 자동으로 생성됩니다.
person.name(); // "John Doe"
person.address(); // "123 Street"
3. equals()와 hashCode()
필드 값이 동일하면 두 객체는 같다고 판단합니다.
4. toString()
객체의 값을 보기 쉽게 문자열로 반환합니다.
Person{name='John Doe', address='123 Street'}
Compact Constructor (컴팩트 생성자)
레코드에 컴팩트 생성자를 추가하면, 생성자 내에서 필드 값을 검증하거나 추가 로직을 넣을 수 있습니다.
예를 들어 null 값 검사를 하고 싶다면 이렇게 작성합니다.
public record Person(String name, String address) {
public Person {
Objects.requireNonNull(name, "Name cannot be null");
Objects.requireNonNull(address, "Address cannot be null");
}
}
Record의 제약 사항
레코드는 몇 가지 제약을 갖고 있습니다. 이러한 제약은 레코드의 목적을 더 명확하게 해줍니다.
1. 상속 금지
레코드는 다른 클래스를 상속할 수 없으며, final이기 때문에 서브클래스를 만들 수 없습니다.
2.인스턴스 필드 추가 금지
모든 필드는 private final이기 때문에 추가로 인스턴스 필드를 선언할 수 없습니다.
3.static 필드와 메서드만 허용
정적 필드와 메서드는 선언할 수 있습니다.
public record Person(String name, String address) {
public static final String DEFAULT_ADDRESS = "Unknown";
}
4.중첩 레코드는 암시적으로 static
레코드를 중첩해서 선언할 경우 자동으로 static으로 처리됩니다.
결론
Record는 데이터 전달용 객체를 간편하고 명확하게 표현할 수 있도록 도입된 기능입니다.
반복적인 boilerplate 코드를 줄여주기 때문에, 불변 데이터 객체를 자주 사용하는 상황에서 큰 도움이 될 것입니다.
Java 14에서는 프리뷰 기능으로 등장했지만, Java 16부터는 정식 기능으로 자리 잡았으니 최신 Java를 사용한다면 꼭 익혀 두시길 바랍니다!
'서버&백엔드 > 🔥 JAVA' 카테고리의 다른 글
JAVA | TDD예제를 통한 어댑터 패턴 설명 (0) | 2024.12.19 |
---|---|
JAVA | POJO로 개발한다는 무슨말일까? (0) | 2024.12.18 |
Inner클래스는 언제 쓸까? (0) | 2024.12.17 |
JAVA | 이진트리 구현 (0) | 2024.11.26 |
Stream | String문자열 내부 정렬 (0) | 2024.11.21 |