오늘 한 것 + 오늘 배운 것
1. 스프링 캐시 추가
기존 코드: 사용자가 /accounts 엔드 포인트에 접근할때마다 사용자 정보를 조회하는 select 쿼리문이 날아갔다. 정보를 따로 저장해놓지 않았기 때문이다. 불필요한 select문이 반복되는걸 해결하기 위해서 스프링 캐시 기능을 추가했다.
@ModelAttribute("userDTO")
@Cacheable(value = "userDTO", key = "#session.getAttribute('user').email")
public UserDTO getUserDTO(HttpSession session) {
SessionUser user = (SessionUser) session.getAttribute("user");
return userService.getUserByEmail(user.getEmail());
}
@Cacheable 어노테이션을 통해 메서드가 반환하는 UserDTO 객체를 캐시에 저장하도록 했다.
캐시의 value는 userDTO이며, 캐시의 키는 세션에 저장된 사용자의 이메일 주소이다.
여기서 value는 캐시의 이름을 나타낸다. 캐시에 저장할 대상을 구분하는 "이름"이기 때문에 실제 저장되는 객체의 클래스와 다른 이름을 가질 수 있다.
key 속성은 캐시에서 특정 항목을 식별하는 데 사용된다. 키로는 @Cacheable 어노테이션이 붙은 메서드의 매개변수를 사용할 수 있다. 나는 세션에 저장되어 있는 사용자 정보를 사용하기 때문에 session.getAttribute()를 통하여 사용자의 이메일을 가져와서 키로 지정했다.
이 키를 통해 UserDTO 객체를 찾을 수 있다.
정리하자면, 사용자의 이메일을 키로 사용하여 UserDTO 객체를 "UserDTO"라는 이름의 캐시에 저장하고 있다. 이렇게 하면 동일한 이메일로 getUserDTO() 메서드를 호출할 때마다 DB에서 사용자 정보를 가져오지 않고, 캐시에서 빠르게 정보를 가져올 수 있다.
2. 역직렬화 에러 -> Redis 저장을 위한 userDTO 직렬화
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.ohouse.ohouse.domain.UserDTO]] with root cause
UserDTO를 캐시에 저장하려고 하니까 위와 같은 에러가 발생했다.
Redis에 UserDTO를 저장하려 했으나 UserDTO 객체가 Serializable 인터페이스를 구현하고 있지 않아 직렬화할 수 없다는 뜻이다.
나는 레디스를 캐시 저장소로 설정한 적이 없는데?! 알아보니 Spring Data Redis를 사용하면 스프링 부트가 자동으로 RedisCacheManager를 설정해준다고 한다.
Redis는 데이터를 byte 배열 형태로 저장하기 때문에, Java 객체를 Redis에 저장하기 위해서는 해당 객체를 byte 배열로 변환(직렬화)할 수 있어야 한다.
Redis는 직렬화된 바이트 배열을 사용하여 데이터를 저장하고, 이를 역직렬화하여 원래의 Java 객체로 변환합니다. 하지만, 객체가 Serializable 인터페이스를 구현하지 않으면, 이 변환 과정이 불가능합니다.
그렇기 때문에 UserDTO가 Serializable 인터페이스를 구현하도록 하면 해결이 된다.
3. 직렬화 <-> 역직렬화 + serialVersionUID?
[Java] 자바 직렬화, serialVersionUID
직렬화란? 글에 이어 부족한 부분을 추가하려한다. serialVersionUID 클래스를 역직렬화 할 때, 멤버 변수가 새로 추가 되었다면 예외가 발생한다. java.io.InvalidClassException local class incompatible: stream class
n1tjrgns.tistory.com
아직 이해 중... 추후에 추가하기