본 포스트는 https://www.baeldung.com/java-record-keyword 를 참고하여 작성 되었습니다.
Java 를 다루어 특정한 서비스를 만들다보면, 불변한 객체를 다룰일이 꽤나 많다.
예를들어, 데이터베이스 에서 추출한 결과를 객체로 가지고 있기 위해서나, 서비스에서 사용되는 정보를 단순히 가지고있는 클래스들과 같은것 말이다.
나 같은 경우는, Spring boot의 DTO 객체를 작성하다가, record 라는것을 알게 되어 개념정리차 게시글을 작성하게 되었다. DTO 또한 변경될 일이 없기에 불변의 속성을 가진 객체라고 할 수 있다.
Java Record는 이런 불변한 객체들을 작성할때 발생하는 고질병들을 해결하기 위해 만들어 낸 데이터 형식의 클래스 이다. Java 14부터 추가 되었다.
우리는 그동안 불변한 특성을 가진 클래스를 만들때 어떻게 해왔을까?
아래는 예시인 Person 클래스 이다.
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;
} else if (!(obj instanceof Person)) {
return false;
} else {
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 + "]";
}
// standard getters
}
1. 필드마다 private, final 을 붙여준다...
2. 각 필드별 Getter를 작성한다.....
3. equals, toString, hashCode 와 같은 메서드들을 필드에 맞게 매번 작성 해준다........
3-1. 필드에 변경 사항이 생길때마다 3번 에서 언급한 메소드들을 업데이트 해준다............
4. ..................................
꽤나 자주 작성하는 클래스 임에도 불구하고 너무 귀찮다....
또한, 코드를 보는 관점에서도 문제가 좀 있다. 위의 Person 클래스는 사실 데이터를 단순히 저장하는데 사용되는 불변객체 임에도 불구하고 지저분한 메소드들로 인해 이 클래스의 목적을 바로 알아채기가 어려워진다.
어노테이션 달아주셈ㅠㅠ
public record Person (String name, String address) {}
이 짧은 코드가 위에 작성된 Person클래스와 동일한 역할을 수행 할 수있다.
즉, record를 이러한 반복적인 데이터클래스 들과 작업들을 단번에 해결할 수 있다.
저렇게 작성하고 나서 끝임? 뭐 어떻게 쓰라고?
이제부터 하나하나 뜯어보자.
생성자
record를 사용하면 아래와 같이 모든 Arguments 들을 받아오는 생성자가 자동으로 생성된다.
public Person(String name, String address) {
this.name = name;
this.address = address;
}
그렇기 때문에, 직접 생성자를 작성해 줄 필요도 없고 외부에서 사용할때도 기존방식대로 그대로 사용해도 전혀 문제가 없다!
Person person = new Person("John Doe", "100 Linda Ln.");
Getter
record는 필드별로 public getter 메소드들도 제공한다. 이 역시 평소처럼 외부에서 쓰던대로 쓰면 된다.
String name = "John Doe";
String address = "100 Linda Ln.";
Person person = new Person(name, address);
System.out.println(person.name() + person.adress());
equals, hashCode, toString
위 Person 클래스에 존재하던 equals, hashCode, toString 메소드 또한 제공한다. 이 역시 평소처럼 외부에서 쓰던대로 쓰면 된다.
String name = "John Doe";
String address = "100 Linda Ln";
Person person1 = new Person(name, address);
Person person2 = new Person(name, address);
perosn1.equals(person2) // True
person1.hashCode(); // person1의 hashCode. record의 hashCode 메소드는 객체의 필드값이 전부 같으면 같은 해시값을 반환한다.
person1.toString(); // Person[name=John Doe, address=100 Linda Ln]
생성자 커스터마이징
그럼 record 쓰면 저렇게 생성된 생성자 밖에 못씀?;;
record 형님이 밥으로 보이는가, 당연히 생성자 커스터 마이징 역시 제공한다.
다만, 이 커스터마이징은 유효성 검사 측면으로 사용되도록 의도되었고, 가능한 단순할수록 좋다.
public record Person(String name, String address) {
public Person(String name) {
this(name, "Unknown");
}
}
예를 들어, 위와같이 작성하면 매개변수로 name 만을 받는 생성자를 직접 커스텀하여 작성해 줄 수 있다.
결론
알아두고, 잘쓰면 자바인생이 편해지는 record에 대해서 간단하게 알아 보았다.
위에서 언급된것 이외에도 자세한 내용들이 많지만, 바로 당장 사용하는데에는 별 문제가 없을 것이다.
'Web' 카테고리의 다른 글
자바 vs 노드 당신의 선택은?! (3) | 2025.01.18 |
---|---|
NestJS + TypeORM + Testcontainers 를 사용한 통합 테스트 DB환경 구축하기 (1) | 2025.01.17 |
코딩테스트 준비를 위한 Java 입출력 정리 (0) | 2024.05.23 |