Skip to content

Dto VS Record

Lee kangmin edited this page Sep 17, 2024 · 2 revisions

Dto vs Record

Record타입이란?

  • record 타입은 Java 16에서 도입된 데이터 구조로, 필드 선언과 함께 간단하게 자동으로 getter, toString, equals, hashCode, constructor 등을 생성해주는 역할을 합니다. 기본적으로 record의 body는 비어있을 수 있지만, 필요한 경우 다음과 같은 내용을 포함할 수 있습니다.

body에 들어갈 내용?

  • 추가적인 메서드

    • record는 필요한 경우 메서드를 추가할 수 있습니다. 일반적인 클래스처럼 비즈니스 로직이나 데이터를 가공하는 메서드를 포함할 수 있습니다. -
  • 정적 메서드(static method)

    • 클래스처럼 정적 메서드를 정의할 수 있습니다.
  • 정적 필드(static field)

    • 정적 필드도 포함 가능합니다.
  • 인스턴스 초기화 블록(instance initializer block)

    • 객체가 생성될 때 실행되는 초기화 블록을 정의할 수 있습니다.
  • 커스텀 생성자

    • record는 기본 생성자를 자동으로 생성하지만, 필요한 경우 생성자를 커스터마이징할 수 있습니다. 예를 들어, 필드에 대한 추가적인 유효성 검사를 포함하는 생성자를 만들 수 있습니다.
  • 추가 인터페이스 구현

    • record는 다른 인터페이스를 구현할 수 있습니다.

코드 보기

public record LeagueCreateRequest(
    String name,
    String description,
    String tierLimit,
    String status,
    String matchType,
    LocalDateTime leagueAt,
    LocalDateTime closedAt,
    Long playerCount,
    LocalDateTime createdAt,
    LocalDateTime modifiedAt
) {
    // 커스텀 생성자 (유효성 검사)
    public LeagueCreateRequest {
        if (playerCount < 0) {
            throw new IllegalArgumentException("Player count cannot be negative.");
        }
    }
    // 정적 메서드
    public static LeagueEntity createRequestToEntity(LeagueCreateRequest request) {
		return new LeagueEntity(
			request.name(),
			request.description(),
			request.leagueAt(),
			request.tierLimit(),
			request.closedAt(),
			request.status(),
			request.playerCount(),
			request.matchType(),
			request.createdAt(),
			request.modifiedAt()
		);
	}
}

차이

dto는 아래와 같이 어노테이션을 많이 붙인다.

@Builder
@Getter
@AllArgsConstructor
@RequiredArgsConstructor
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@ToString
public class LeagueCreateRequest {

	@Schema(description = "경기 이름", example = "배드민턴 경기")
	private String name;
     // .. 이하 내용 생략
}

반면 record는 Getter Builder 등 기본적으로 적용하는 기능이 많아 생략이 가능하다.

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public record LeagueCreateRequest(

	@Schema(description = "경기 이름", example = "배드민턴 경기")
	String name,

객체의 불변성 여부

Dto 객체를 불변성으로 만들기 위해서는 setter를 사용하지 않는 방법이 있지만 메서드를 통해서 변경이 가능하다. 만약 객체의 불변성을 보장하고 객체의 값이 변하지 않는 것이 더 나은 선택이라면 Record 타입의 객체도 좋은 것 같다.

public record Person(String name, int age) {
    // 생성자에서 유효성 검사 가능
    public Person {
        if (age < 0) {
            throw new IllegalArgumentException("Age cannot be negative.");
        }
    }
}

//객체의 불변성 보장
public class Main {
    public static void main(String[] args) {
        Person person = new Person("Alice", 30);

        // 값 읽기
        System.out.println(person.name());  // 출력: Alice
        System.out.println(person.age());   // 출력: 30

        // person의 필드를 수정하려고 하면 오류 발생 (불변성 보장)
        // person.name = "Bob";  // 컴파일 오류

        // 새로운 객체를 생성해서 수정된 값을 할당해야 함
        Person updatedPerson = new Person("Bob", 35);

        System.out.println(updatedPerson.name());  // 출력: Bob
        System.out.println(updatedPerson.age());   // 출력: 35
    }
}

우리의 스타일은?

아직 까지는 Dto의 객체의 값을 변경시키거나 값을 재할당하는 일은 없다. 객체의 불변성을 보장하면서 정적팩토리 메서드를 사용해야 한다면 Record 타입을 고려해보는 것이 어떨까?

Clone this wiki locally