DTO로 Record 사용하기

전홍영·2023년 11월 1일
1

Java

목록 보기
10/15

나는 DTO, (Data Transfer Object)로 Record를 주로 사용한다. Record를 DTO class를 만드는 것보다 코드가 간결해져서 사용하곤 했다. 그러나 Record를 왜 사용하는지는 잘 모르고 사용하는 것 같아 정리해본다.

Record란?

Record는 자바 14부터 도입된 문법으로 간결한 문법으로 데이터를 담는 불변 객체를 생성할 수 있게 해주는 기능이다. Record는 다음과 같은 특징을 갖는다.

  • 간결성: 간결한 문법으로 필드, 생성자, getter, equals, toString 등을 개발자가 직접 생성할 필요없이 생성이 가능하다. 이는 코드의 가독성을 높이고, 유지보수를 용이하게 해준다.
  • 불변성: Record는 기본적으로 불변 객체이다. 그래서 데이터의 안정성을 보장할 수 있기 때문에 DTO와 같이 데이터를 전달하는 역할을 하기에 적합하다.
  • 제한된 상속: Record는 final 클래스이므로 상속을 할 수 없다. 이 부분이 불변성을 보장하는데 중용한 요소이다.
  • 구성요소 접근: Record 클래스의 필드를 구성요소(compoonet)라 하는데, 이 구성요소에는 public 접근자가 자동으로 부여되어 getter 없이 접근이 가능하다.

Record를 이용한 DTO

다음은 Student 클래스를 StudentDTO에 담는 코드를 보여준다.

//Student 클래스
class Student{
    private final String name;

    public Student(String name){
        this.name = name;
    }
    
    public String getName(){
    	return this.name;
    }
}

//Record DTO
record StudentDtoByRecord(String name){
	public static StudentDtoByRecord from(Student){
    	return new StudentDtoByRecord(student.getName());
    }
}

//클래스 DTO
class StudentDtoByClass {
    private final String name;

    public StudentDTO(String name){
        this.name = name;
    }
}

위의 코드를 보면 class로 만들어진 DTO보다 Record가 딱봐도 훨씬 간결하고 사용하기가 좋다. 이외에도 위에서 언급한 레코드의 특징을 이용한 코드를 살펴보자.

간결성 & 구성요소 접근

class로 만들어진 dto의 필드에 접근을 하기위해서는 getter 메서드가 필요하지만 record에는 getter가 자동으로 만들어지고 필드가 public이기 때문에 접근이 가능하다.

public static void main(String[] args){
	Student student = new Student("name");
    StudentDtoByRecord studentDTO = StudentDtoByRecord.from(student);
    String name = studentDTO.name();
}

불변성

레코드의 필드는 final이기 때문에 수정이 불가능하여 불변성을 유지한다.

record StudentDtoByRecord(String name){
	public void setName(String name){
        this.name = name; // 오류 발생 -> name은 final이기 때문에 수정 불가
    }
}

equals & hashCode

만약 클래스라면 equals와 hashCode를 오버라이드하여 다시 정의하여야 두 객체의 값을 비교하여 같은 객체인지를 비교할 수 있다. 하지만 레코드는 equals와 hashCode를 오버라이할 필요없이 자동으로 생성해준다.

public static void main(String[] args) {
        // TODO: 프로그램 구현
        Student student = new Student("name");
        StudentDTO studentDTO1 = StudentDtoByRecord.from(student);
        StudentDTO studentDTO2 = StudentDtoByRecord.from(student);
        System.out.println(studentDTO1.equals(studentDTO2)); // true 결과 출력
}

toString

Object 클래스의 toString은 해당 객체의 클래스 명과 hashCode를 문자열로 반환하지만 Record가 자동으로 생성해주는 toString은 레코드 명과 그 필드 값을 문자열로 반환해준다. (물론 Record의 toString 메서드도 오버라이드 가능하다)

public static void main(String[] args) {
        // TODO: 프로그램 구현
        Student student = new Student("name");
        StudentDTO studentDTO = StudentDtoByRecord.from(student);
 		student.toString();// Student@1d81eb93
        studentDTO.toString();// StudentDTO[name=name]
}

결론

Record 문법이 등장하기 전에는 class를 dto로 만들어서 여러 오버라이드와 설정을 통해 dto를 만들었다면 개발자가 하기 귀찮은 과정을 줄여주고 훨씬 간결한 문법으로 data class를 사용할 수 있는 record 문법이 있으니 프로젝트를 하다가 dto를 만들 필요가 있을 경우 class와 record 중 더 나은 방법을 선택하자!

profile
Don't watch the clock; do what it does. Keep going.

0개의 댓글