Spring
[Spring] Redis 기반 세션 스토리지 구축 (2)- 구현
J_Dev
2024. 11. 1. 15:05
Spring 코드 구현
- 기존의 JDBC와 결합된 코드에서 세션 관리 부분만 Redis로 변경하여 간편하게 Session Storage를 변경하였다.
- 특히 Spring Security 와 통합이 간편하여, 별다른 설정없이 구현이 가능했다.
1. build.gradle
- 라이브러리를 추가해준다.
- 상단은 Redis 연결을 위한 라이브러리, 하단은 Redis를 session storage로 쓰기위한 라이브러리다.
//Redis implementation 'org.springframework.boot:spring-boot-starter-data-redis' //Spring Session Library for Redis implementation 'org.springframework.session:spring-session-data-redis'`
2. application.porperties
- Redis 서버와 연결하기 위한 환경변수를 설정한다.
- Docker Compose로 실행할 예정이므로, 환경 변수로 Redis 서버 호스트를 설정하였다.
# Redis Session Storage
spring.session.store-type=redis
spring.session.redis.host=${REDIS_SESSION_HOST}
spring.session.redis.port=6379
#session limit time
spring.session.timeout=5m
3. Redis Config Class
- Redis 서버와 연결하기 위한 Bean 객체를 생성한다.
- @EnableRedisHttpSession 어노테이션을 사용하여 HTTP Session을 자동으로 Redis에 저장, 관리한다.
- host 와 prot 는 @Value 로 환경변수에 저장하여 propertiy binding 하여 안전하게 관리했다.
- Spring Session이 자동 직렬화 기능을 제공하기 때문에 별도의 RedisTemplate 설정 없이 세션을 Redis에 저장할 수 있다.(캐시로 사용시 필요)
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@Configuration
@EnableRedisHttpSession
public class RedisSessionConfig {
@Value("${spring.session.redis.host}")
private String host;
@Value("${spring.session.redis.port}")
private int port;
@Bean
@Primary
public RedisConnectionFactory redisSessionConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName(host);//host 할당
configuration.setPort(port);//port 할당(기본값 6379)
return new LettuceConnectionFactory(configuration);//redis 연결을 위한 Connection Factory 생성 Bean 으로 관리
}
4. RESTful API
- 기존의 API는 Spring Security와 결합되어 있어 인증 정보가 필요할 때 Authentication 객체를 사용해 유저 정보를 확인하였다.
- 세션 정보 저장시 SecurityContext 도 Redis에 함께 저장되므로 다른 WAS 인스턴스에서도 유저정보에 쉽게 접근, 조회 할 수 있다.
...나머지코드생략
@GetMapping("/members/me/mypage")
@ResponseBody
public ResponseEntity<MemberMyPageDto> showMyPage(
Authentication authentication) {
//유저 인증 정보가 없으면 badRequest 응답, 정보가 있으면 CustomOAuth2User로 타입캐스팅
CustomOAuth2User principal = authenticator.checkAuthenticate(authentication);
//유저 정보 DB에서 찾아 반환, 닉네임, 코인갯수, 이메일 정보 포함
MemberMyPageDto memberMyPageInfo = memberService.getMemberMyPageInfo(principal.getName());
//유저 정보 전
return ResponseEntity.ok(memberMyPageInfo);
}
5. docker-compose.yml
- Docker Compose를 사용해 여러 WAS와 Redis를 연결하였다.
- 서비스가 app-network라는 네트워크를 통해 서로 통신한다.
version: '3.8'
services:
backend:
build:
context: ./netnovel
dockerfile: Dockerfile
container_name: backend
ports:
- "8081:8081" # 애플리케이션 포트 설정
environment:
- SPRING_PROFILES_ACTIVE=prod # 프로덕션 프로파일 활성화
- DB_URL=jdbc:mysql://172.27.32.1:3306/netnovel
- DB_USERNAME=
- DB_PASSWORD=
- REDIS_SESSION_HOST= redis-session # Redis 호스트 이름 설정
networks:
- app-network
redis-session:
image: redis:alpine # Redis 이미지
container_name: redis-session
ports:
- "6379:6379" # Redis 포트 노출
networks:
- app-network
networks:
app-network:
driver: bridge # 각 컨테이너가 통신할 네트워크 설정 bridege 모드는 Docker 기본 네트워크 모드
6. 실행 및 테스트
로그인 테스트
- 정상적으로 로그인이 완료되고 SESSION ID또 발급된것을 확인할 수 있다.
- Redis Insight로 확인하면 다음과 같이 저장된 것을 확인할 수 있다.
결론
- Spring Session과 Redis를 결합하여 간단하게 Redis 기반의 세션 스토리지를 구현할 수 있었다.
- Spring Session과 Spring Security는 자동으로 결합되기 때문에,보안 설정을 수정할 필요 없이 Redis로 세션 스토리지를 전환할 수 있었다.