
Java의 record는 Java 16에서 도입된 기능으로, 데이터를 간결하고 명확하게 표현하기 위해 설계된 불변(immutable) 데이터 클래스를 만드는 데 사용됩니다. 주로 데이터를 저장하고 전달하는 용도로 사용되며, DTO(Data Transfer Object)와 같은 단순한 데이터 구조를 쉽게 정의할 수 있습니다. record는 기본적으로 생성자, getter, equals, hashCode, toString 메서드를 자동으로 생성하여 코드의 간결성을 높입니다.
Record 예시:
public record Person(String name, int age) {}
위 코드에서 Person 클래스는 생성자와 필드 접근 메서드들이 자동으로 제공되므로, 매우 간결하게 데이터를 표현할 수 있습니다.
1) 클래스로 정의한 DTO 예시:
public class UserDto {
private final String name;
private final int age;
public UserDto(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserDto userDto = (UserDto) o;
return age == userDto.age && Objects.equals(name, userDto.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "UserDto{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
위 코드는 UserDto 객체를 정의하기 위해 생성자, getter, equals, hashCode, toString 메서드를 직접 작성해야 합니다. 이러한 반복적인 작업이 많아지면 유지보수에도 부담이 생길 수 있습니다.
2) Record로 정의한 DTO 예시:
public record UserDto(String name, int age) {}
record를 사용하면, 위의 클래스에서 작성했던 모든 메서드와 기능을 한 줄로 정의할 수 있습니다. record는 컴파일 시 자동으로 생성자와 getter, equals, hashCode, toString 메서드를 제공하기 때문에 코드가 훨씬 간결해집니다.
| 특성 | Class 기반 DTO | Record 기반 DTO |
|---|---|---|
| 코드 작성 | 수동으로 메서드 작성 | 자동으로 메서드 생성 |
| 불변성 | 기본적으로 가변적 | 기본적으로 불변적 |
| 초기화 및 추가 로직 | 복잡한 초기화 가능 | 간단한 초기화에 적합 |
| 상속 | 가능 | 불가능 |
record는 선언만으로 필요한 메서드가 자동으로 제공되기 때문에, 반복적인 코드 작성을 줄이고 코드의 가독성을 높여줍니다.record는 기본적으로 불변성을 유지합니다. 한 번 생성된 객체의 필드 값이 변경되지 않기 때문에 멀티스레드 환경에서 안전하게 사용할 수 있습니다. 반면, 클래스로 정의한 DTO는 가변적으로 필드를 수정할 수 있어 유연하게 사용할 수 있습니다.record는 단순한 데이터 전송에 주로 사용됩니다.Record를 사용할 때:
Class를 사용할 때:
record는 상속을 지원하지 않으므로, 상속 구조가 필요한 경우 클래스가 적합합니다.record는 불변이므로, 객체 생성 후 필드를 수정할 수 없습니다. 불변성을 유지하면서 객체의 필드를 수정해야 하는 경우, record 대신 클래스를 사용하는 것이 더 좋습니다.record 생성자에서 필드 검증 로직을 포함할 수 있지만, 복잡한 검증이 필요할 때는 클래스를 사용하는 것이 더 자연스러울 수 있습니다.record는 상속을 지원하지 않기 때문에 상속을 통해 공통 기능을 구현하고자 한다면 클래스를 사용해야 합니다. 대신 컴포지션(composition)을 고려해 볼 수 있습니다.record는 간결함이 장점이지만, 너무 많은 필드를 담고 있다면 오히려 가독성이 떨어질 수 있습니다. record의 사용 목적이 명확한 경우에만 사용하는 것이 좋습니다.DTO와 record는 상황에 따라 적절히 선택해야 합니다. 데이터의 불변성과 간결성이 중요하고, 추가적인 로직이 필요 없는 경우에는 record를 사용하는 것이 유리합니다. 반면, 데이터 수정이 필요하거나, 복잡한 초기화와 검증 로직이 필요한 DTO에는 클래스를 사용하는 것이 더 적합합니다.
결국, record도 DTO의 일종으로, 클래스와 record를 어떤 상황에서 사용할지 구분하는 것이 중요합니다. 처음 record를 사용하는 사람이라면, 이를 간단한 데이터 전달 목적으로 사용하고, 복잡한 로직이 포함된 DTO는 클래스로 구현하는 것이 좋습니다. 프로젝트의 특성과 요구사항에 맞게 record와 클래스를 적절히 선택하여 효율적이고 유지보수 가능한 코드를 작성합시다.