Record 키워드

배지원·2023년 5월 22일
0

JAVA

목록 보기
31/32

1. Record 사용 목적

웹페이지의 동작방식으로 크게는 유저(클라이언트) <-> 프론트 <-> 백엔드(서버) <-> 데이터베이스로 동작이 된다. 이때 서버에서는 데이터베이스에서 데이터를 가져와 프론트로 값을 전송해 유저가 볼 수 있도록 동작하게 되는데 이때 값을 가져오는 방식 중 대표적인 것이 DTO클래스이다.

프론트에서 값을 입력받아 백엔드로 보낼때나 백엔드에서 프론트로 값을 보내는 과정 중 불필요하게 객체의 정보가 변경이 될 시 불변성을 보장할 수 없게 되어 다른 값이 저장되거나 오류가 발생할 수 있다. 따라서 이를 위해 DTO클래스를 통해 래핑하여 전달하게 된다.

불변성을 수행 과정


1. 모든 필드에 final을 사용하여 명시적으로 정의
2. 필드 값을 모두 포함한 생성자
3. 각 필드에 대한 getter 접근 메소드
4. 모든 필드가 일치할때 동일한 클래스의 객체에 대해 true를 반환하는 equals 메소드
5. 모든 필드가 일치할때 동일한 값을 반환하는 hashCode 메소드
6. 로깅 출력을 제공하기 위한 toString 재정의

일반적은 DTO 클래스를 보게 되면

public class Student{
	private final String name;	// 학생 이름
    private final int number;	// 학급 번호
    
    // 생성자
    public Student(String name, int number){
    	this.name = name;
        this.number = number;
    }
    
    // getter
    public String getName(){
    	return name;
    }
   
	
    // 해시코드
    public int hashCode(){
    	return Objects.hash(name,address);
    }
    
    // 객체 비교
    public boolean equals(Object obj){
    	if(this == obj){
        	return true;
        }else if(!(obj instanceof Student)){
        	return false;
        }else{
        	Student stu = (Student) obj;
            return Object.equals(name, stu.name) && Object.equals(number,stu.number);
        }
    }
	
    // toString
    public String toString(){
    	return "Student [name="+name+",number="+number+"]";
    }
}

이런식으로 사용하게 되면 2개의 필드만 작성했을에도 불구하고 코드의 양의 너무 많아져서 이해하기가 어려울 수 있으며 클래스의 목적이 애매함(너무 많은 메서드를 사용하고 있기 때문에 클래스의 목적이 정보전달만을 하고 있는건지 알기 어려움)

이처럼 단점들을 보완하기 위해 Lombok을 사용하여 작성할 수 있다.

@EqualsAndHashCode
@ToString
@AllArgsConstructor
@Getter
public class Student{
	private final String name;	// 학생 이름
    private final int number;	// 학급 번호
}

하지만 이것 또한 라이브러리만을 사용하여 boilerplate code를 줄일 수 있지만 클래스만 봤을때는 아직까지 어떤 목적을 가진 클래스인지 확인할 수 없기 때문에 클래스의 목적이 애매하다.

따라서 JAVA 14이후로는 이러한 반복적인 클래스를 record 키워드를 사용하여 클래스의 목적을 구분시키고 있다.

public record Student(String name, int number){}

record를 선언하는 방법은 위와 같다.
1. class 키워드 대신에 record를 사용하여 데이터를 전송하기 위해 사용하는 파일이라는 것을 지정
2. 생성자에 매개변수를 넣는 것처럼 사용할 필드 값들을 클래스명 옆에 선언해준다.

이렇게만 해주면 자동으로 필드값들은 private final키워드로 취급되고 기본 생성자, getter, toString, hashCode, equals를 생성해준다.



2. Record 호출 방식

(1) 생성자

  • 일반적으로 생성자를 호출하여 사용하는 방식과 같다.
public static void main(String[] args) {
    Student stu = new Student("학생1", 1);
}

(2) Getter

  • 기존에는 getName() 처럼 get이 붙어있는 메서드를 통해 필드값을 가져와야 하지만 Record에서는 필드명과 동일한 메소드명으로 호출이 가능하다.
public static void main(String[] args) {
    Student stu = new Student("학생1", 1);
    
    System.out.println(stu.name());		 // 학생1
    System.out.println(stu.number());	 // 1
}

(3) equals

  • 기존과 같이 2개의 값을 비교하여 결과값을 반환해 준다.
public static void main(String[] args) {
    Student stu = new Student("학생1", 1);
    Student stu2 = new Student("학생1", 1);
    Student stu3 = new Student("학생2", 2);
        
    System.out.println(stu.equals(stu2));		// true
    System.out.println(Objects.equals(stu, stu2));		// true
    System.out.println(stu.equals(stu3));		// false
}

(4) hashCode

  • equals의 방식과 유사하게 동작하게 됩니다. 필드의 값이 모두 일치하는 경우 동일한 값을 반환하지만 필드의 값이 1개라도 다를경우 다른 값을 반환합니다.
public static void main(String[] args) {
    Student stu = new Student("학생1", 1);
    Student stu2 = new Student("학생1", 1);
    Student stu3 = new Student("학생2", 2);
        
    System.out.println(stu.hashCode());			// (1)
    System.out.println(stu2.hashCode());		// (1) hashCode 값과 일치
    System.out.println(stu3.hashCode());		// (1) hashCode 값과 불일치
}

(5) toString

  • record 파일의 이름과 내부 필드의 값들을 포함하는 문자열을 반환해 준다.
public static void main(String[] args) {
    Student stu = new Student("학생1", 1);
        
    System.out.println(stu);		// Student[name=학생, number=1]
    System.out.println(stu.toString());		// Student[name=학생, number=1]
}

profile
Web Developer

0개의 댓글