[header section]
해당 프로젝트는 위와 같은 요구사항이 있다고 가정한 뒤 해당 작업을 진행하였습니다.
Spring Data Redis provides support for various Redis data structures, allowing you to interact with Redis in a more convenient way. Here are the main Redis data structures supported by Spring Data Redis:
- String Redis Template (
RedisTemplate<String, String>
):
- Represents the simplest data structure in Redis.
- Allows you to store and retrieve simple key-value pairs (strings).
- List Redis Template (
ListOperations<String, String>
):
- Represents Redis Lists.
- Allows you to store and manipulate lists of strings.
- Provides operations like
leftPush
,rightPush
,leftPop
,rightPop
, etc.
- Set Redis Template (
SetOperations<String, String>
):
- Represents Redis Sets.
- Allows you to store and manipulate sets of strings.
- Provides operations like
add
,remove
,intersect
,union
, etc.
- Hash Redis Template (
HashOperations<String, String, String>
):
- Represents Redis Hashes.
- Allows you to store and retrieve maps of key-value pairs.
- Provides operations like
put
,get
,delete
,entries
, etc.
- ZSet Redis Template (
ZSetOperations<String, String>
):
- Represents Redis Sorted Sets (ZSets).
- Allows you to store elements with associated scores, sorted by the scores.
- Provides operations like
add
,remove
,range
,rank
, etc.
- Value Redis Template (
ValueOperations<String, String>
):
- Represents an abstraction for common Redis operations using String keys and String values.
- Provides simple methods like
set
,get
,increment
, etc.
[쿠키를 사용해서 회원 여부 확인, 장바구니에 담긴 상품이 있는지 확인]
public String addToCart(@CookieValue(name = "CART_NO") Cookie cookie,
@CookieValue(name = "HEADER_UUID") Cookie member,
HttpServletResponse response,
@RequestBody request){
// HEADER_UUID라는 쿠키가 있으면 로그인한 회원으로 인식하여 loginId를 쿠키 값으로 넣어준 뒤 쿠키 생성을 하고 응답 객체에 보낸다.
if(Objects.nonNull(member)){
String loginId = SecurityContextHolder.getContext().getAuthentication().getName();
cookie = cookieUtils.createCookie("CART_NO", loginId,60*60*24*30);
response.addCookie(cookie);
}
// 비회원이면서 장바구니에 어떤 상품도 담겨있지 않은 상태라면 비회원용 장바구니 UUID를 발급해서 넣어준다.
if(Objects.isNull(cookie)){
String uuid = String.valueOf(UUID.randomUUID());
cookie = cookieUtils.createCookie("CART_NO", uuid, 60 * 60 * 24 * 3);
response.addCookie(cookie);
}
}
[RedisTemplate을 사용해 해당 장바구니에 담고자 한 정보를 저장하기]
redisTemplate.opsForHash().put(cookie.getValue(), request.getProductId(), quantity);
if(Objects.isNull(member)){
// 비회원의 경우 3일 뒤 쿠키 만료 -> redis 데이터도 3일뒤 삭제
redisTemplate.expire(cookie.getValue(), 3, TimeUnit.DAYS);
} else{
//회원의 경우 30일 뒤 장바구니 쿠키 삭제 -> redis에 저장된 데이터도 삭제
redisTemplate.expire(cookie.getValue(), 30, TimeUnit.DAYS);
}
Cookie.setMaxAge()
)redisTemplate.opsForHash().put(cookie.getValue(), request.getProductId(), quantity);
package org.springframework.data.redis.core;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.lang.Nullable;
public interface HashOperations<H, HK, HV> {
Long delete(H key, Object... hashKeys);
Boolean hasKey(H key, Object hashKey);
@Nullable
HV get(H key, Object hashKey);
List<HV> multiGet(H key, Collection<HK> hashKeys);
Long increment(H key, HK hashKey, long delta);
Double increment(H key, HK hashKey, double delta);
@Nullable
HK randomKey(H key);
@Nullable
Map.Entry<HK, HV> randomEntry(H key);
@Nullable
List<HK> randomKeys(H key, long count);
@Nullable
Map<HK, HV> randomEntries(H key, long count);
Set<HK> keys(H key);
@Nullable
Long lengthOfValue(H key, HK hashKey);
Long size(H key);
void putAll(H key, Map<? extends HK, ? extends HV> m);
void put(H key, HK hashKey, HV value);
Boolean putIfAbsent(H key, HK hashKey, HV value);
List<HV> values(H key);
Map<HK, HV> entries(H key);
Cursor<Map.Entry<HK, HV>> scan(H key, ScanOptions options);
RedisOperations<H, ?> getOperations();
}
AbstractDialect
를 상속받아 구현한 클래스에 AbstractAttributeTagProcessor
를 상속 받은 클래스를 추가해서 사용하라는데 자료가 많이 없어서 뭔 말인지 모르고 따라하다 안 되어서 다른 방법을 강구했다.@ModelAttribute
라는 방법이 있었고 처음엔 메서드 단에 해당 애너테이션을 붙인 메서드를 필요 컨틀롤러마다 복붙 해줬다.import com.yaloostore.front.auth.exception.InvalidHttpHeaderException;
import com.yaloostore.front.common.exception.*;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import java.util.Map;
import java.util.Objects;
/**
* 에러를 공통으로 처리하기 위해 사용되는 어드바이스 클래스입니다.
* */
@ControllerAdvice
@Slf4j
@RequiredArgsConstructor
public class WebControllerAdvice {
private final RedisTemplate redisTemplate;
/**
* 장바구니에 담긴 상품의 개수를 처리할 때 사용하는 메서드입니다.
* 이는 ControllerAdvice 클래스 하위에 두어 필요한 곳에서 사용할 수 있게 하였습니다.
*
* @param cartNo redis에 저장한 key를 가지고 있는 쿠키입니다.(회원의 경우 로그인 아이디, 비회원의 경우 랜덤 발급한 uuid
* @return 회원 장바구니에 담긴 상품의 개수
* */
@ModelAttribute(name = "cartProductCounting")
public int setViewHeaderFrag(@CookieValue(required = false, value = "CART_NO") Cookie cartNo){
//장바구니가 비어 있는 경우라면?
if (Objects.isNull(cartNo)){
return 0;
}
if (Objects.nonNull(cartNo)){
String uuid = cartNo.getValue();
log.info("uuid = {}", uuid);
Map<String, String> o = redisTemplate.opsForHash().entries(uuid);
log.info("size??!?! {}", o.size());
return o.size();
}
return 0;
}
}
medis
라는 프로그램이다.