Record 클래스

백다진·2025년 10월 4일
post-thumbnail

DTO 클래스의 고민

JPA 프로젝트를 쫌쫌따리 진행하던 와중 DTO 클래스를 하나하나 만들면서 불편함을 느꼈다.
Entity도 아닌 Transfer 객체에 Entity에 버금가는 Lombok Annotaion(감사합니다 롬복님)을 버무려 놓고, 혹은 직접 오버라이드하여 사용하면 나중에 프로젝트가 매우 커졌을 때 유지보수 머리 아프겠는데? 라는 생각도 들었다.

DTO는 말그대로 데이터 전달 객체이므로, 필드를 final로 선언하고 생성자를 통해 초기화하면 Setter를 제공하지 않아 불변성을 보장해야 한다. 이러한 점에서 DTO 클래스마다 final 선언, getter, equals, tostring 등의 메소드 오버라이드는 필연적이며 이러한 점에서 반복된 작업 또한 불편하게 느껴졌던 것이다.


Record 클래스

그때, 한 줄기 빛 같은 Record 클래스를 발견했다.
Java 14에서 도입되어 17에서 본격적으로 빛을 발한 Record!

Record는 간결한 표현과 불변성을 위해 설계된 클래스다.
기존 DTO의 단점을 보완하며, 컴파일 시 자동으로 아래의 항목들이 작성된다.

  • 클래스와 필드 final 선언
  • 생성자
  • 접근자 → getId( )가 아닌 id( ) 형태
    👆 데이터 표현이 목적이므로 JavaBeans 규칙을 따르지 않고, setter가 없어 구분 필요 ❌
  • equals( ) / hashCode( ) / toString( ) 메서드 제공

Record 클래스 작성 및 컴파일 확인

  • Record 클래스는 간단히 아래와 같이 작성한다.

    public record UserDTO(Long id, String name, String email) {}
  • 위 코드는 컴파일 시 아래와 같이 작성된다.

    public final class UserDTO extends java.lang.Record {
        private final Long id;
        private final String name;
        private final String email;
    
        public UserDTO(Long id, String name, String email) {
            this.id = id;
            this.name = name;
            this.email = email;
        }
    
        public Long id() {
            return this.id;
        }
    
        public String name() {
            return this.name;
        }
    
        public String email() {
            return this.email;
        }
    
        @Override
        public String toString() {
            return "UserDTO[id=" + this.id + ", name=" + this.name + ", email=" + this.email + "]";
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof UserDTO other)) return false;
            return java.util.Objects.equals(this.id, other.id)
                && java.util.Objects.equals(this.name, other.name)
                && java.util.Objects.equals(this.email, other.email);
        }
    
        @Override
        public int hashCode() {
            return java.util.Objects.hash(this.id, this.name, this.email);
        }
    }

결론

Record 클래스는 DTO 작성 시간을 줄여줌과 동시에 휴먼 에러를 줄이고, final 필드를 통한 불변성까지 보장해주는 간결하면서도 안정적인 데이터 전달 객체 구현 방법이므로, 자바 17 이상 환경에서는 적극적으로 고려할 만하다.

다만 Jackson과 같은 라이브러리 사용 시 카멜 케이스 ↔ 스네이크 케이스 매핑 이슈가 있을 수 있으므로, application.yaml 설정이나 @JsonProperty, @JsonNaming과 같은 어노테이션으로 대응해야 한다.

  • 매핑 설정 예시 👇


    application.yaml
    
    	spring:
    		jackson:
          		property-naming-strategy: SNAKE_CASE
    

    public record UserDTO(
        @JsonProperty("user_id") Long userId,
        @JsonProperty("user_name") String userName
    ) {}
    

     

    출처 : https://youtu.be/Ojo-ZVTG4vk?si=kognVO2w1q6PLe_S

profile
awsome

0개의 댓글