본문 바로가기
Backend/Spring

Spring : Record 클래스 사용하기

by 코딩쥐 2024. 10. 27.

Java의 Recod 클래스는 생성자, getter 메서드, toString메서드 등이 메서드들이 자동으로 생성되어 기존 클래스를 작성할 때보다 간결하게 객체를 생성할 수 있다. Record 클래스는 final로 상속이 불가능하며, 필드는 암묵적으로 final이다.

 

스프링에서 Record 클래스 사용하기

1. Record 클래스로 DTO를 생성한다. 

Record 클래스로 생성하면 @Getter, @AllArgsConstructor, @ToString, @EqualsAndHashCode 어노테이션이 기본값으로 설정된다. 자동으로 제공되기 때문에 별도로 어노테이션을 추가할 필요가 없다. 아래 에제는 사용자ID, 장바구니 물건리스트, 장바구니 총합계에 대한 정보를 가지고 있는 CartDTO 클래스 이다. 

package com.example.project.dto;

import java.util.List;

public record CartDTO<T>(String userID, List<T> productList, Integer totalCost) {
}

 

2. Controller 클래스를 생성하여 DTO를 활용한다. 

package com.example.project.controller;

import com.example.project.dto.CartDTO;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.Arrays;

@Controller
public class CartController {
    @RequestMapping(value = "/cart", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<CartDTO> cartfn() {
        CartDTO cart = new CartDTO(
                "ak10d",
                // 리스트를 쉽게 생성하는 방법
                new ArrayList<>(Arrays.asList("사과", "양파", "사이다")),
                15000
        );

        // 헤더 설정
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-type", "application/json");
        headers.add("Accept-Charset", "UTF8");

        return new ResponseEntity<>(cart, headers, HttpStatus.OK);
    }
}

 

참고로 Record 클래스의  @EqualsAndHashCode 어노테이션은 데이터의 값이 같을 경우에는 같은 hashCode를 반환한다. 따라서 아래와 같이 hashCode가 동일할 경우에만 cartList에 추가하도록 로직을 작성하면, cart1만 cartlist에 삽입된 것을 확인할 수 있다. 

package com.example.project.controller;

import com.example.project.dto.CartDTO;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Controller
public class CartController {
    @RequestMapping(value = "/cart", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<List<CartDTO>> cartfn() {
        CartDTO cart1 = new CartDTO(
                "ak10d",
                new ArrayList<>(Arrays.asList("사과", "양파", "사이다")),
                15000
        );

        CartDTO cart2 = new CartDTO(
                "ak10d",
                new ArrayList<>(Arrays.asList("사과", "양파", "사이다")),
                15000
        );

        List<CartDTO> cartlist = new ArrayList<>();

        // 만약 hashcode가 같지 않아야 cartlist에 cart2 추가
        cartlist.add(cart1);
        if(cart1.hashCode() != cart2.hashCode()){
            cartlist.add(cart2);
        }

        System.out.println(cart1.hashCode());
        System.out.println(cart2.hashCode());

        //헤더 설정
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-type", "application/json");
        headers.add("Accept-Charset", "UTF8");

        return new ResponseEntity<>(cartlist, headers, HttpStatus.OK);
    }
}

 

이렇게 Record 클래스를 활용하면 DTO를 보다 간결하게 작성할 수 있으며,  Record클래스는 불변성을 가지므로 데이터의 일관성을 유지하는데 유리하다. 또한 hashCode를 통해 데이터 중복을 효율적으로 관리할 수 있다. 단, Record 클래스는 상속이 불가능하고 복잡한 로직이나 상태를 가지지 않는 단순한 데이터 구조에서 사용할 수 있다.