DevBoi

[Java] Record class란? 본문

Language/[Java]

[Java] Record class란?

HiSmith 2023. 5. 27. 22:02
반응형

Jdk 버전에 대한 팔로우업에 잊고 행복한 삶을 살다가

Jdk 14부터 정식 릴리즈한 Record class라는 애가 나왔고. DTO로써 사용하기 최고라고 추천을 받아

공부겸 포스팅을 진행하려고한다.

 

1) Record 클래스가 뭔데?

레코드란 데이터클래스 이며, 순수하게 데이터를 보유하기 위한 특수한 종류의 클래스이다.

코틀린의 데이터 클래스와 비슷한 느낌이다.

데이터의 유형만 딱 나타내는 느낌으로, DTO클래스를 생성할때 굉장히 간결해지는 장점이 있다.

 

2) 샘플 소스 및 대략적인 사용 예제

 

한 30%의 사람들 혹은 옛날 코드들은 이렇게 DTO가 짜여있다.

package com.inna.innabackend.dto;

public class SampleRecordDto {

  private String name;
  private String price;
  
  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getPrice() {
    return price;
  }

  public void setPrice(String price) {
    this.price = price;
  }
}

 

좀 지나면 롬복으로 간편화 할 수 있다.

package com.inna.innabackend.dto;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class SampleRecordDto {

  private String name;
  private String price;
}

 

만약에 생성자나, toString 등등 이것저것 붙일라면, 한 DTO에 어노테이션을 많이 붙이기도 해야하고

등등 좀 지저분해져서 코드의 기능이 눈에 잘 안들어오기 시작한다.

이럴때 쓰는 것이 레코드이다.

package com.inna.innabackend.dto;

import lombok.Getter;
import lombok.Setter;


public record SampleRecordDto(
  String name,
  String price
) {}

 

오.. 엄청 간편한데?

근데 이렇게 간편하면 사용할때 별로 못사용하는게 아닌가라는 생각을 할 수 있다.

 

1) Json Serialize 할때는 별도 표기를 해줘야함

package com.inna.innabackend.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;


public record SampleRecordDto(
  @JsonProperty("name") String name,
  @JsonProperty("price") String price
) {}

 

2) static 변수를 가질수 있고, static 이나 public 한 메소드를 가질 수 있다.

package com.inna.innabackend.dto;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;


public record SampleRecordDto(
  @JsonProperty("name") String name,
  @JsonProperty("price") String price
) {
  public static String sampleValue = "teststatic";
  
  @JsonIgnore
  public  String getInfo(){
    return "hi" + name + price;
  }
  
}

 

3. 생성자나, toString 같이 자주쓰는 메소드들은 알아서 지원해준다. 생성자 유효성을 사용해보자

콤팩트 생성자를 쓰면, 더 편하게 사용이 가능하다.

package com.inna.innabackend.dto;

import java.util.Objects;

public record SampleRecordDto(
  String name,
  String price
) {
  public SampleRecordDto{
    Objects.requireNonNull(name);
    Objects.requireNonNull(price);
  }

}
@GetMapping("/getMemberInfo")
  public String test(){
    SampleRecordDto dto = new SampleRecordDto("name","price");
    
    return "test!";
  }

컴팩트 생성자에 유효성검증식을 넣게 되면, 생성자에 대한 예외 처리도 추가할 수 있다

public record SampleRecordDto(
  String name,
  String price
) {
  public SampleRecordDto{
    Objects.requireNonNull(name);
    Objects.requireNonNull(price);
      if(name.contains("smith"))
        throw new RuntimeException();
  }

}

 

Record에 대해서 다른 DTO와 변환 식을 사용하면 좀 더 깔끔하다

package com.inna.innabackend.dto;

import java.util.Objects;

public record SampleRecordDto(
  String name,
  String price
) {
  public SampleRecordDto{
    Objects.requireNonNull(name);
    Objects.requireNonNull(price);
      if(name.contains("smith"))
        throw new RuntimeException();
  }
  public static SampleRecordDto of(UserDto user){
    return new SampleRecordDto(user.getId(), user.getPw());
  }

}

 

사용할때는 이렇다.

@GetMapping("/getMemberInfo")
  public String test(){
    SampleRecordDto record = new SampleRecordDto("name","price");
    UserDto userDto = new UserDto();
    userDto.setId("id");
    userDto.setPw("pw");
    SampleRecordDto record2 = record.of(userDto);
    return "test!";
  }

 

 

Bean Validation과 조합해서, 여러개의 레코드를 조합해보기

 

package com.inna.innabackend.dto;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;

public final class SampleDto {
  public static final class Request{
    public record Creation(
      @NotBlank @Pattern(regexp = "^[a-zA-Z가-힣]{2,10}$") String creation_name,
      @NotBlank String create_version
    ){}
    public record  User(
      @NotBlank String user_name,
      @NotBlank String tele_num
    ){}
  }
}

 

그러면 위의 내용과 생성자와 합치면, 아래와 같이 사용할 수 있다.

package com.inna.innabackend.dto;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;

public final class SampleDto {
  public static final class Request{
    public record Creation(
      @NotBlank @Pattern(regexp = "^[a-zA-Z가-힣]{2,10}$") String creation_name,
      @NotBlank String create_version
    ){}
    public record  User(
      @NotBlank String user_name,
      @NotBlank String tele_num
    ){
      public User{
        if(user_name.contains("smith"))
          throw new RuntimeException();
      }
    }
  }
}
반응형