e-commerce 대용량 서버 프로젝트에서 session storage로 redis를 적용하였습니다. redis session을 적용한 이후로는 redis로 들어가 조회할 일이 거의 없기 때문에 session이 어떻게 저장되고 삭제되는지 확인해보려고 합니다.
해당 프로젝트는 다음 github에서 확인 가능합니다.
https://github.com/f-lab-edu/online-marketplace
@Override
public void login(SignInRequestDto dto){
...
// 이메일이 존재하고 패스워드가 일치하면 세션에 데이터 저장
httpSession.setAttribute(SessionKey.LOGIN_USER_ID, user.get().getId());
}
@Override
public void logout(){
// 세션에 해당 세션키에 대한 데이터 삭제
httpSession.removeAttribute(SessionKey.LOGIN_USER_ID);
}
public class SessionKey {
public static final String LOGIN_USER_ID = "USER_ID";
}
@EnableRedisHttpSession
@Configuration
public class RedisConfig {
@Value("${spring.redis.session.host}")
private String redisHost;
@Value("${spring.redis.session.port}")
private int redisPort;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(new RedisStandaloneConfiguration(redisHost, redisPort));
}
}
Postman으로 localhost:8080/users/login에 POST요청을 한 후, redis-cli로 확인하면 다음과 같이 데이터가 저장된 것을 확인할 수 있습니다.
세션을 저장하면 3가지의 데이터를 조회할 수 있습니다.
spring:session:sessions:(session id)
spring:session:sessions:expires:(session id)
spring:session:expirations:(expire time)
spring:session:sessions:expires
의 세팅 과정과 세션 만료시간을 키로 지정하는 이유를 공식문서에서 찾을 수 있었습니다.
세션 키 자체로 만료시간을 추적하여 데이터를 조회할 수 없어서 만료시간 키가 사용됩니다.
세션 정보가 spring:session:sessions에 저장되어 있는지 확인해보았습니다.
spring:session:sessions에는 다음과 같이 저장되어 있었습니다.
creationTime
세션 생성시간lastAccessedTime
마지막 세션 조회 시간sessionAttr
세션에 저장한 데이터maxInactiveInterval
만료시간sessionAttr
에서는 저희가 setAttribute()
메소드를 사용하여 저장한 세션키 USER_ID
가 들어있습니다.
저장된 데이터 USER_ID
의 값을 조회해보겠습니다.
사용자의 id가 알아보기 힘든 형태로 출력되었습니다. 공식 문서에는 다음과 같이 알려줍니다.
즉, RedisTemplate으로 객체와 Redis의 기본 이진 데이터간의 데이터 직렬화/역직렬화를 하는데 사용되는 방식이 Jdk 직렬화 방식(JdkSerializationRedisSerializer)이기 때문이라고 합니다.
localhost:8080/users/logout에 GET요청을 하면 해당 데이터가 제대로 삭제되는지 확인해보겠습니다.
❓ 세션이 사라지지 않았습니다
세션이 남아있다
와 세션 안에 있는 데이터를 지웠다
는 다른 것이기 때문입니다.
세션은 저장소일 뿐이라 그 안의 추가적인 데이터와는 다릅니다. 따라서 세션 저장소가 남아 있을수도 있지만 그 안에 있는 사용자의 이메일 데이터는 날아갔을 것입니다.
확인해보니 USER_ID
키의 데이터는 잘 삭제되었습니다.
세션이 로그인에만 쓰이는 것이 아니기 때문에, 로그아웃을 할 시에 내부에 있는 데이터를 다 날리는 것보다는 저장했던 키와 관련된 데이터만 지우는 것도 하나의 방법이 될 수 있습니다.
처음에 만료시간 이후 데이터가 제대로 삭제되는지 확인하기 위해 앱단에@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 60)
으로 지정한 후 테스트해보았습니다.
1분이 지나도 spring:session:sessions
가 남아있었습니다. 그 이유를 스프링 공식문서에서 발견할 수 있었습니다.
즉, 코드상으로 만료시간을 60초로 지정하면 spring:session:sessions:expires
에는 60초로 설정되고, spring:session:sessions
에는 5분을 더한 6분이 만료시간으로 설정됩니다. 그 이유는 세션 세부 데이터가 세션 만료시간(1분)에 삭제되는 순간에도 필요하기 때문에 5분의 시간이 더 주어지는 것입니다.
6분 후에 해당 세션 데이터가 삭제된 것을 확인하였습니다.
처음에 keys * 명령어로만 정보를 확인하였기 때문에 데이터가 지워지지 않은줄 알았지만, 아니었습니다. redis에 세션데이터가 어떻게 저장되는지 확인해보면서 저장소에 대한 개념을 다시 확인할 수 있었고, 어떤 데이터가 저장되는지 알 수 있어서 이후 다른 필요한 데이터도 사용할 수 있을 것입니다.
https://redis.io/commands
https://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/RedisTemplate.html
https://docs.spring.io/spring-session/docs/2.2.x/reference/html/api.html
프로젝트에 많은 도움이 되었습니다 감사합니다!