본문 바로가기
Web/Spring

[Spring] Spring session을 Redis에 저장했을 때 어떻게 저장될까?

by EricJeong 2020. 1. 3.

개요

 

Spring에서 Global session전략을 사용할 때 일반적으로 redis를 사용합니다. Spring redis session을 적용한 이후 실제로 redis에 접속하여 값을 조회할 일은 거의 없습니다. 그렇기 때문에 세션 정보가 redis에 어떤 자료구조로 어떻게 저장되는지 한번 확인해보겠습니다.

 

 

간단하게 세션에 값을 저장하는 예제를 만들어 보겠습니다. STS에서 Spring boot starter를 사용하여 간편하게 만들 수 있습니다.

 

 

Spring code

 

해당 프로젝트의 코드는 github에서 모두 확인하실 수 있습니다.

https://github.com/yyy9942/spring-redis-session-exam

 

yyy9942/spring-redis-session-exam

Contribute to yyy9942/spring-redis-session-exam development by creating an account on GitHub.

github.com

 

 

pom.xml

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
</dependencies>

Session data를 redis에 저장하기 위해서는 spring session data redis 의존성을 추가해주어야 합니다.

또한 웹으로 접속하여 session정보를 받을 것이기 때문에 spring boot starter web 의존성도 추가해주세요.

 

application.properties

spring.session.store-type=redis
spring.redis.host=localhost
spring.redis.password=
spring.redis.port=6379

 

RedisSessionExamApplication.class

package com.deveric;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@SpringBootApplication
@EnableRedisHttpSession
public class RedisSessionExamApplication {

	public static void main(String[] args) {
		SpringApplication.run(RedisSessionExamApplication.class, args);
	}

}

Redis에 세션 데이터를 저장하기 위해 어노테이션 @EnableRedisHttpSession을 추가해주어야 합니다. 

 

RedisConfig.class

package com.deveric.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

@Configuration
public class RedisConfig {
  
  @Value("${spring.redis.password}")
  private String redisPwd;
  
  @Bean
  public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    mapper.registerModules(new JavaTimeModule(), new Jdk8Module());
    return mapper;
  }
  
  @Bean
  public RedisConnectionFactory redisConnectionFactory() {
    RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
    redisStandaloneConfiguration.setPassword(redisPwd);
    LettuceConnectionFactory lettuceConnectionFactory =
        new LettuceConnectionFactory(redisStandaloneConfiguration);
    return lettuceConnectionFactory;
  }
}

 

HelloController.class

package com.deveric.controller;

import javax.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
  
  @GetMapping("hello")
  public String hello(HttpSession session) {
    session.setAttribute("hello", "eric");
    return "hello eric!";
  }
}

 

redis에서 데이터 조회

 

Postman으로 http://localhost/hello URL을 테스트 했을 때 redis에 다음과 같이 저장됩니다.

 

 

해당 데이터의 타입은 각각 다음과 같습니다.

 

 

 

각각 string, set, hash로 하나에 세션은 총 3가지의 데이터 타입으로 저장됩니다.

이 각 데이터는 어떤 것을 의미할까요? 

 

Spring redis session에 세션을 저장하면 조회할 수 있는 데이터

1. spring:session:sessions:expires (string)

2. spring:session:expirations (set)

3. spring:session:sessions (hash)

 

일단 세션에 저장한 데이터는 어디에 있을지 유추할 수 있습니다. session은 map을 저장소로 사용하기 때문에 hash에 있을 것이라 판단했습니다. 실제로 데이터가 hash타입 spring:session:sessions에 저장되어 있는지 확인해보았습니다.

 

 

실재 hello 정보가 저장되어있는 것을 확인할 수 있었습니다. 데이터를 조회해보겠습니다.

"eric" 이라는 데이터가 저장되어 있는 것을 확인할 수 있었습니다. 나머지 두 가지 데이터는 어떤 데이터를 저장할까요? 공식 문서를 참고하여 어떤 데이터를 저장하는지 참조해보았습니다.

 

저장 형식 자료형 역할

spring:session:sessions:expires:(session id)

string 해당 세션의 만료 키로 사용합니다.
spring:session:expirations:(expire time) set expire time에 삭제될 세션 정보들을 담고있습니다. 해당 time이 되면 저장된 데이터를 조회하여 해당 세션을 모두 삭제합니다.
spring:session:sessions:(session id) hash 세션의 생성 시간, 마지막 세션 조회 시간, 최대 타임아웃 허용 시간과 해당 세션에 저장한 데이터를 저장합니다.

spring:session:sessions:expires:(session id) 같은 경우는 세션의 만료를 키 자체에서 추적하게 되면 조회가 불가능하기 때문에 사용한다고 합니다. Spring 공식 doc에서는 다음과 같이 설명하고 있습니다.

 

 

후기

 

Spring boot에서 간편하게 설정할 수 있는 redis session이지만 실제 어떻게 저장되는지 확인할 수 있었습니다. 어떤 key에 어떤 데이터가 저장되는지 알았으니 이제 사용자가 언제 접속했는지, 언제 마지막으로 세션이 끝났는지, 어떤 데이터를 저장했는지 더 명시적으로 확인할 수 있을 것입니다.

 

References

https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-redis.html

https://docs.spring.io/spring-session/docs/current/reference/html5/

댓글