Backend 개발 시 HA 구성이나 여러 유관 시스템 연동 시 세션 Clustering을 통해 정보를 공유해야할 경우가 생긴다. 이럴 경우에 Tomcat, Nginx, Jboss 등의 웹 서버 단에서 Sticky Session 설정을 할수도 있으나 Spring framework에서 제공하는 session redis 기능을 활용하면 수월하게 Session Clustering 환경을 구축 할 수 있다.
Spring Session 기능은 아래 공식 문서에서 찾아볼 수 있다.
https://docs.spring.io/spring-session/reference/index.html
중요한 부분은 언급되어 있는 아래 최소 사항 항목이다.
Java 17+ 및 Spring 6.0.x 사항이 언급되어 있다. 나름 최신 사양으로 보인다.
Minimum Requirements
The minimum requirements for Spring Session are:
- Java 17+.
- If you run in a Servlet Container (not required), Servlet 3.1+.
- If you use other Spring libraries (not required), the minimum required version is Spring 6.0.x.
- @EnableRedisHttpSession requires Redis 2.8+. This is necessary to support Session Expiration
- @EnableHazelcastHttpSession requires Hazelcast 3.6+. This is necessary to support FindByIndexNameSessionRepository
현재 필자가 테스트하는 환경은
Spring boot 3.0.2 버전이고 Spring framework web 6.0.4 버전 + java 17을 사용하고 있다. 위 기능을 충족하는 사양이다.
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>3.0.0</version>
</dependency>
레디스에 세션을 적재하므로 redis 관련 라이브러리 및 spring session 라이브러리를 다운 받는다.
RedisConfig.java
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
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.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Profile("!unittest")
@Configuration
public class RedisConfig {
@Value("${spring.data.redis.host}")
private String host;
@Value("${spring.data.redis.port}")
private int port;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
redisConfiguration.setHostName(host);
redisConfiguration.setPort(port);
redisConfiguration.setDatabase(0);
return new LettuceConnectionFactory(redisConfiguration);
}
@Bean
public RedisConnectionFactory redisConnectionFactoryToken() {
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
redisConfiguration.setHostName(host);
redisConfiguration.setPort(port);
redisConfiguration.setDatabase(1);
return new LettuceConnectionFactory(redisConfiguration);
}
@Bean(name = "redisTemplate")
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<?, ?> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
return redisTemplate;
}
@Bean(name = "redisTemplateToken")
public RedisTemplate<?, ?> redisTemplateToken() {
RedisTemplate<?, ?> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactoryToken());
redisTemplate.setDefaultSerializer(new StringRedisSerializer());
return redisTemplate;
}
}
redis 서버를 컨트롤할 드라이버 설정을 한다.
application-local.yml
spring:
application:
name: Test
servlet:
multipart:
enabled: true
mybatis:
common:
config: classpath:mybatis/config/mybatis-config.xml
mapper: classpath*:mybatis/sql/**/*.xml
pops:
mapper: classpath*:mybatis/sql/**/*.xml
data:
redis:
host: 172.30.1.45
port: 49153
위와 같이 redis 서버 정보를 yml에 입력하여 redis session 설정시 참조 하도록 한다.
CommonApplication.java
import lombok.Generated;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;
@EnableConfigurationProperties()
@SpringBootApplication(scanBasePackages = "com")
@EnableRedisHttpSession
public class CommonApplication {
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("TEST_SESSIONID");
serializer.setCookiePath("/");
serializer.setDomainName("test.com");
return serializer;
}
@Generated
public static void main(String[] args) {
SpringApplication.run(CommonApplication.class);
}
}
Spring boot main entry에 위와 같이 @EnableRedisHttpSession 을 추가하면 spring session redis 설정이 진행된다.
이와 함께 세션이 적재될 Cookie의 속성을 변경하고자 한다면 CookieSerializer bean을 추가해 주도록 한다.
serializer.setCookieName("TEST_SESSIONID");
serializer.setCookiePath("/");
serializer.setDomainName("test.com");
setCookieName은 브라우저에 표시될 Cookie key 이름이고 CookiePath는 Cookie가 참조될 request url path, setDomainName은 쿠키를 공유할 서브 도메인을 말한다.
TestController.java
@Tag(name = "테스트", description = "테스트 관련 API")
@RestController
@RequestMapping("/api/v1/iam")
public class TestController {
@Operation(summary = "레디스 세션을 생성한다.", description = "디버깅용 테스트 세션을 생성한다." + "\n\n" +
"필수 파라미터 : ")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Success", content = @Content(schema = @Schema(implementation = ResultDVO.class)))
})
@RequestMapping(value = "/test/session", method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<ResultDVO> createTestSession(HttpServletRequest request) throws Exception{
HttpSession session = request.getSession(true);
session.setAttribute("TEST_DATA", System.currentTimeMillis());
return new ResponseEntity<>(new ResultDVO(), HttpStatus.OK);
}
}
간단하게 세션에 현재 시간을 저장하는 테스트 Rest api를 만들어 본다.
Swagger-UI를 열람하고 테스트 Api를 실행해본다.
브라우저의 Cookie 결과를 보면 설정한대로 Cookie 속성이 설정되어 있음을 볼 수 있다.
P3X REDIS Client tool을 깔고 레디스 내용을 살펴보면 spring -> session 항목에 세션이 생성되어 있음을 볼 수 있고 세션 내용을 열람하면 아래와 같이 테스트 Rest api에서 저장한 TEST_DATA 세션 값이 있음을 볼 수 있다.
-- The End --
'Backend Development > Spring boot' 카테고리의 다른 글
[Spring boot] atomikos 라이브러리 활용 XA 멀티 DBMS Transacaction 구현 (1) | 2023.12.26 |
---|---|
[Spring Boot] Quartz 배치 DisallowConcurrentExecution 설정 (0) | 2023.12.20 |
[Spring boot] RestTemplate 으로 http 통신하기 (0) | 2023.04.29 |
[Spring boot] MultipartFile 파일 업로드 구현 (0) | 2023.04.11 |
[Spring boot] Embedded Tomcat redis session clustering (0) | 2023.02.26 |