[Java] record

Jungwoong (David) Yoon·2023년 8월 11일

Java

목록 보기
1/1

개인 프로젝트를 하다가 IDE에서 아래와 같은 문구를 발견하게 되었다.

"record 가 뭐지?" 라고 생각한 나는 바로 IDE의 조언대로 객체를 record를 변경해보았다.

어...?


record 에 전혀 모르고 있었던 나는 적잖이 당황했고, 이 record 라는 기능을 알아보기 위해 찾아보고 이해한 것들을 여기에 적어보기로 했다.


record 란?


보통 우리가 만드는 데이터 객체는 오직 데이더 (e.g. DB 결과, 쿼리 결과, 등) 를 보관하기 위해 주로 사용된다.

이런 용도로 사용되는 객체들은 불변하게 만드는데, 이런 객체 간의 변경 불가능한 데이터를 전달할 시, Java 14 이전에는 boilerplate field 와 method가 포함된 클래스를 생성해야 해서 코드가 많이 복잡해진다.

  • lombok의 annotation들을 사용하면 훨씬 간결해질 수도 있지만, 필요한 경우 직접 필요한 코드들을 클래스에 작성해야 할 수도 있다.

하지만, Java 14가 출시되고서 부터 record keyword 를 사용하여 이러한 문제를 해결할 수 있게 되었다.

record 는 Java 14 에서 preview 로 나왔고 Java 16 에서 정식 기능으로 포함되었다.


적용


현재 진행 중인 개인 프로젝트를 예로 들면,

public class UserVO {

    private final Long id;

    private final String username;

    private final String email;

    public UserVO(Long id, String username, String email) {
        this.id = id;
        this.username = username;
        this.email = email;
    }
    
    public Long getId() {
    	return id;
    }
    
    public String getUsername() {
    	return username;
    }
    
    public String getEmail() {
    	return email;
    }
}

사용자의 간단한 정보들을 담기 위해 UserVO 만들어 사용하고 있다. 현재 이 클래스는 필드, 생성자, getter를 모두 담고 있어서 코드가 매우 길다.

여기서 lombok의 @Getter@RequiredArgsConstructor 를 사용하면,

@Getter
@RequiredArgsConstructor
public class UserVO {

    private final Long id;

    private final String username;

    private final String email;
}

코드가 훨씬 간결해진 것을 볼 수 있다.

하지만, 여전히 이런 클래스를 작성할 때 마다, 모든 필드를 명시하고,final로 정의해야 한다.


만약 record 를 사용한다면?

public record UserVO(Long id, String username, String email) {}

이렇게 더 간결하게 작성할 수 있다.


기능


Constructor

위의 record를 사용해 객체를 생성하는 방법은 간단하다.

UserVO user = new UserVO(1L, "user", "user@gmail.com");

이렇게 클래스와 같은 방식으로 객체를 인스턴스화 할 수 있다.

Getter

아래와 같이 필드 이름과 같은 getter method를 사용할 수 있다.

UserVO user = new UserVO(1L, "user", "user@gmail.com");

assertEquals("user", user.name());
assertEquals("user@gmail.com", user.address());

위의 기능들 외에도 더 다양한 기능들을 포함하고 있다

  • equals()

  • toString()

  • hashCode()

  • Compact Contructor*

  • Static variables & methods


Compact Contructor 란?

비공개 필드를 초기화하는 것 이상의 작업 (필드 validation, etc) 을 수행하도록 도와주는 생성자. 클래스 생성자와 달리 레코드 생성자에는 공식적인 매개변수 목록이 없는 것이 특징이다.

아래처럼 validation을 추가하거나,

public record UserVO(Long id, String username, String email) {

    public UserVO {
        Objects.requireNonNull(username);
        Objects.requireNonNull(email);
    }
}

또는 아래처럼 다른 argument 목록을 제공하여 다른 argument를 가진 새로운 생성자를 생성할 수도 있다.

public record UserVO(Long id, String username, String email) {
    public UserVO(String name) {
        this(name, "Unknown");
    }
}

제한 사항


  1. record 는 다른 클래스를 상속받을 수 없으며, private final 이외의 인스턴스 필드를 선언할 수 없다. 선언되는 다른 모든 필드는 static 이어야 한다.

    • 이러한 제약 사항은 상태 설명만으로 표현을 정의할 수 있도록 보장해준다.
  2. 레코드는 암시적으로 fianl 이다. abstract 일 수 없다.

    • record 의 API가 상태 설명에 의해서만 정의되며 나중에 다른 클래스나 레코드에 의해 변경되거나 나아질 수 없음을 강조한다.


References:

profile
깨부하는 개발자

0개의 댓글