@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로 세션 스토리지를 전환할 수 있었다.