스프링

redis

sdafdq 2023. 12. 11. 09:32

redis는 우선, 깔려 있어야 쓸 수 있다.

아마도 배포할 때 그 환경에도 깔아야 할 것이다.

 

spring:


  data:
    redis:
      host: localhost
      port: 6379

 

 

설정은 이렇게

 

 

@Configuration
public class RedisConfig {
    @Value("${spring.data.redis.host}")
    private String host;

    @Value("${spring.data.redis.port}")
    private int port;

    @Bean
    public RedisConnectionFactory redisConnectionFactory(){
        return new LettuceConnectionFactory(host, port);
    }

    @Bean
    public RedisTemplate<String, LoginMember> redisTemplate(){
//        https://developer-nyong.tistory.com/21#article-2-1--refreshtoken
        RedisTemplate<String, LoginMember> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());

        Jackson2JsonRedisSerializer<LoginMember> serializer = new Jackson2JsonRedisSerializer<>(LoginMember.class);

        redisTemplate.setDefaultSerializer(serializer);
        redisTemplate.setKeySerializer(serializer);
        redisTemplate.setValueSerializer(serializer);

        return redisTemplate;
    }
}

환경도 구성 해 주고,

 

레디스 커넥션 팩토리 저게 커넥션 풀 같은건가 보다.

 

저 serializer는 직렬화인데, 저렇게 해야 쓸 수 있나보다.

뭔가 오브젝트 그 자체로 저장한다기 보다는,

 

redis가 in memory db인데, 저렇게 뭔가 String 같이 직렬화 해서 써야 하나 보다.

 

저렇게 대충 셋팅 해 주고,

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@RedisHash
public class LoginMember implements Serializable {
    @Id
    private String sessionId;

    private MemberInfoDto memberInfoDto;

    @TimeToLive
    private long ttl;

    public LoginMember(String sessionId,MemberInfoDto memberInfoDto, long ttl) {
        this.sessionId = sessionId;
        this.memberInfoDto = memberInfoDto;
        this.ttl = ttl;
    }
}

 

이렇게 @RedisHash 붙이고 in memory db 답게 JpaRepository 처럼 쓸 수 있다.

 

@Id가 그 id이다.

 

@TimeToLive가 살아있을 수 있는 시간이다.

그런데 이거는 처음 들어간 값만 적용이 된다. 딱 그상태로 구워진 다고 생각하면 된다. 

 

@Id 이거는 생성자 저기에 값이 들어오면 그 들어온 값으로 쓰고, 안 들어오면 알아서 지정을 해 주는 것 같다.

 

public interface LoginMemberRepository extends CrudRepository<LoginMember, String> {
    Optional<LoginMember> findBySessionId(String sessionId);
}

 

이거는 JpaRepository 말고 CrudRepository. 

JpaRepository는 저걸 상속받은 거임.

 

여튼 저거 쓰면, JpaRepository처럼 사용이 가능함.

 

@Service
@Slf4j
public class LoginMemberService {
    private final LoginMemberRepository loginMemberRepository;

    public static final String SESSION_COOKIE_NAME = "sessionId";
    private static final int SESSION_EXPIRATION_TIME = 1800;

    public LoginMemberService(LoginMemberRepository loginMemberRepository) {
        this.loginMemberRepository = loginMemberRepository;
    }


    public LoginSessionDto createSession(MemberInfoDto memberInfoDto, HttpServletResponse response){
        String sessionId = UUID.randomUUID().toString();
        LoginMember loginMember = new LoginMember(sessionId, memberInfoDto, SESSION_EXPIRATION_TIME);
        loginMemberRepository.save(loginMember);

        ResponseCookie.ResponseCookieBuilder cookieBuilder = from(SESSION_COOKIE_NAME, sessionId);
        cookieBuilder.maxAge(SESSION_EXPIRATION_TIME);
        cookieBuilder.secure(true);
        cookieBuilder.sameSite("None");
        cookieBuilder.path("/");
        cookieBuilder.domain("127.0.0.1");

        log.info("쿠키생성");
        response.addHeader("Set-Cookie", cookieBuilder.build().toString());
        log.info("cookie: {}",cookieBuilder.build().toString());
        return new LoginSessionDto(sessionId, true);
    }

    public Optional<MemberInfoDto> getMemberInfoBySessionId(String sessionId, HttpServletResponse response){
        Optional<LoginMember> findLoginMember = loginMemberRepository.findById(sessionId);

        if(findLoginMember.isPresent()){
            LoginMember extractLoginMember = findLoginMember.get();
            LoginMember newLoginMember = new LoginMember(extractLoginMember.getSessionId(), extractLoginMember.getMemberInfoDto(), SESSION_EXPIRATION_TIME);
            expire(extractLoginMember.getSessionId());
            loginMemberRepository.save(newLoginMember);
            updateCookieTime(sessionId, SESSION_EXPIRATION_TIME, response);
            return Optional.of(findLoginMember.get().getMemberInfoDto());
        }
        return Optional.empty();
    }

    public void expireAll(String sessionId, HttpServletResponse response){
        if(sessionId == null) return;
        loginMemberRepository.deleteById(sessionId);
        expireCookie(response, sessionId);
    }

    private void expire(String sessionId){
        loginMemberRepository.deleteById(sessionId);
    }

    private void expireCookie(HttpServletResponse response, String sessionId){
        updateCookieTime(sessionId, 0, response);
    }

    private static void updateCookieTime(String sessionId, int maxAgeSeconds, HttpServletResponse response) {
        ResponseCookie.ResponseCookieBuilder cookieBuilder = from(SESSION_COOKIE_NAME, sessionId);
        cookieBuilder.maxAge(maxAgeSeconds);
        cookieBuilder.secure(true);
        cookieBuilder.sameSite("None");
        cookieBuilder.path("/");
        response.addHeader("Set-Cookie", cookieBuilder.build().toString());
    }
}

 

보면 JpaRepository 쓰듯이 자동으로 만들어 진 것을 쓰고 있다. 그걸로 잘 하면 된다.

 

 

 

 

 

'스프링' 카테고리의 다른 글

AWS 스프링  (0) 2023.12.11