앞서 Session의 단점과 단점을 보완할 수 있는 Redis서버에 대해 알아보았습니다.
오늘은 Redis에 Session을 저장하여 서버가 다중화되어도 Session정보를 저장 할 수 있게 리펙토링할 것입니다.
컨테이너 스케일 인, 아웃할때 세션을 공유하여 여러 컨테이너가 필요한 정보들을 추가적인 작업없이 사용 할 수 있습니다.
ex) 서버를 8080, 8081로 띄워놓은 상황에서 8080에서 로그인을 하고 8081로 접속하여도 그대로 로그인이 되어있습니다.
EC2에 띄워놓은 서버에 Redis를 설치해야합니다.
Docker에서 redis의 이미지를 다운받을 수 있습니다.
레디스 이미지 가져오기
docker pull redis
레디스 서버 실행하기
docker run --name myredis -d -p 6379:6379 redis
build.gradle에 redis-starter, redis session라이브러리를 추가하고 빌드
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.session:spring-session-data-redis'
application.yml 에 host 와 port 를 설정
localhost:6379 는 기본값이기 때문에 만약 Redis 를 localhost:6379 로 띄웠다면 따로 설정하지 않아도 연결됩니다
spring:
redis:
host: localhost
port: 6379
Docker의 redis-cli로 접속하기
docker run -it --link myredis:redis --rm redis redis-cli -h redis -p 6379
Redis 사용을 위한 기본 Configuration
application.yml 에 설정한 값을 @Value 어노테이션으로 주입.
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}
}
지금은 사용하지 않지만 나중에 사용할 경우를 대비해 추가했습니다
RedisTemplate 을 사용하면 특정 Entity 뿐만 아니라 여러가지 원하는 타입을 넣을 수 있습니다.
template 을 선언한 후 원하는 타입에 맞는 Operations 을 꺼내서 사용합니다.
@Configuration
@EnableRedisRepositories // redis 활성화
public class RedisConfig {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private int redisPort;
/*
RedisTemplate을 이용한 방식
RedisConnectionFactory 인터페이스를 통해
LettuceConnectionFactory를 생성하여 반환
*/
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(redisHost, redisPort);
}
@Bean
public RedisTemplate<String, String> redisTemplate() {
// redisTemplate를 받아와서 set, get, delete를 사용
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
/**
* setKeySerializer, setValueSerializer 설정
* redis-cli을 통해 직접 데이터를 조회 시 알아볼 수 없는 형태로 출력되는 것을 방지
*/
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(redisConnectionFactory());
return redisTemplate;
}
}
Main메서드에
@EnabledRedisHttpSession
어노테이션으로 Redis 세션 사용을 설정합니다.
@SpringBootApplication
@EnableRedisHttpSession
public class PocoapocoApplication {
public static void main(String[] args) {
SpringApplication.run(PocoapocoApplication.class, args);
}
}
생각보다 너무 간단했습니다.
그럼 바로 테스트를 진행해 보겠습니다.
Docker를 통해 Redis에 접근하여 확인해 보겠습니다.
Docker의 redis-cli로 접속하기
docker run -it --link myredis:redis --rm redis redis-cli -h redis -p 6379
로그인을 하면 redis 서버에 4개의 key가 저장되는것을 확인할 수 있습니다.
1) "spring:session:sessions:expires:$sesssionId (string)
스프링 세션의 만료시간을 관리하는 key입니다.
2) "spring:session:expirations:$expireTime" (set)
스프링 세션의 만료시간입니다.
3) "spring:session:sessions:$sessionId" (hash)
생성된 스프링 세션 데이터입니다.
4) "spring:session:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:$username (set)
username으로 세션을 가져올 수 있도록 저장되는 인덱스입니다.
딱봐도 hash에 세션정보들이 담겨있을것 같다는 생각이 들었습니다.
Hash저장소는 key, get명령어 앞에 h를 붙여 사용할 수 있습니다.
지금 사용할 명령어는 hkeys: 해시 키값을 전부 조회, hgetall: 해시 밸류를 전부 조회
세션 정보에 담겨진 정보를 확인해보겠습니다.
로그인시 넣어두었던 JWT의 키값인 Authorization이 확인이 됩니다.
Redis를 활용해 서버마다 Session을 공유하게 만들었습니다.
생각보다 간단하게 Session을 공유할 수 있어서 좋았습니다.
Redis는 백엔드에서 활용도가 높은것 같아 더 알아보고 공부를 해봐야 할것같습니다.