본문 바로가기
언어/Java

[Java] record type

by Geunny 2022. 12. 6.
반응형

jdk 14 버전 이후부터 제공되는 데이터 타입.

class 형태중 불변 class로 정의할 때 사용된다. 

즉 해당 클래스는 생성자와 getter(), toString() 메소드를 포함하고 있는 형태라고 볼수있다.

 

기존의 불변객체 정의

public class Test {
    private final String name;
    private final String contents;

    public Test(String name, String contents) {
        this.name = name;
        this.contents = contents;
    }

    public String getName() {
        return name;
    }

    public String getContents() {
        return contents;
    }
}

record를 이용

public record TestRecord (
        String name, String contents
        ){
}

 

생성자와 getter 메세지 뿐만 아니라 객체 비교에 있어서 사용되는 equals() 메소드와 hash() 메소드도 포합되어 있어 equals 비교시 컨텐츠가 같다면 동일한 객체로 동작한다.

 

테스트를 위한 TestClassWithEquals  클래스도 정의해 주었다 (비교하기 위함)

public class TestClassWithEquals {
    private final String name;
    private final String contents;

    public TestClassWithEquals(String name, String contents) {
        this.name = name;
        this.contents = contents;
    }

    public String getName() {
        return name;
    }

    public String getContents() {
        return contents;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        TestClassWithEquals that = (TestClassWithEquals) o;
        return Objects.equals(name, that.name) && Objects.equals(contents, that.contents);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, contents);
    }
}

 

 

테스트 코드 작성

 

class TestClassTest {

    @Test
    void 불변객체_비교(){
        TestClass t1 = new TestClass("제목", "내용");
        TestClass t2 = new TestClass("제목", "내용");
        assertThat(t1).isNotEqualTo(t2);
    }

    @Test
    void 불변객체_비교_equals_hash_정의된_class(){
        TestClassWithEquals t1 = new TestClassWithEquals("제목", "내용");
        TestClassWithEquals t2 = new TestClassWithEquals("제목", "내용");
        assertThat(t1).isEqualTo(t2);
    }

    @Test
    void 레코드_비교(){
        TestRecord t1 = new TestRecord("제목","내용");
        TestRecord t2 = new TestRecord("제목","내용");
        assertThat(t1).isEqualTo(t2);
    }

}

 

테스트 결과

 

그렇다면 이 불변객체는 어디서 사용될수 있을까?

 

레코드는 한번 만들면 내부 필드의 내용을 외부에서는 절대  변경할 수 없다.

처음에 불변객체를 들었을 때 그래서 데이터만 받아서 어쩔건데.. 하는 생각이 들었다.

서비스 로직에서 불변데이터로 사용될수 있는 데이터가 무엇이 있을까 생각했을때..

 

웹 외부에서 받아온 DTO 또는 클라이언트로 보내주는 DTO의 경우에 모든 서비스 로직을 거친후

단순 데이터를 담아 전달해 주는 역할을 해줄 수 있어 record 타입은 DTO의 성격으로 사용될수 있다고 생각되었다.

 

기존 프로젝트에서 @Getter, @NoArgsConstru....등등 덕지덕지 붙여주던 너셕들을 record를 도입하게 된다면

조금더 깔끔한 DTO 로서 사용될 수 있을것 같다.

 

다만 아직까지 record 타입의 객체가 JSON으로 파싱되려면 '@JsonProperty("필드명")'  어노테이션을 추가해 줘야 직렬화가 가능한 것 같다. 

라는 글을 보았으나 jdk 17 이상에서 공식으로 채택되면서 ObjectMapper 를 통한 직렬화시 어노테이션 없이도 동작되는 것을 확인하였다. (정확히는 JDK16에서 정식 스펙으로 포함)

 

    @Test
    void 레코드_직렬화_어노테이션_미포함() throws JsonProcessingException {
        TestRecord t1 = new TestRecord("제목","내용");
        ObjectMapper mapper = new ObjectMapper();
        String s = "{\"name\":\"제목\",\"contents\":\"내용\"}";
        System.out.println(mapper.writeValueAsString(t1));
        System.out.println(mapper.readValue(s, TestRecord.class));
    }

댓글