Spring API에 Spring session redis 적용하기

0

프로젝트

목록 보기
14/14

들어가기에 앞서

Spring session을 사용한 이유는 로드 밸런싱을 위해서 여러 개의 백엔드 컨테이너를 띄웠는데, 각각의 컨테이너 별로 세션을 가지고 있으면, 로드 밸런싱을 최초에 접속한 컨테이너로 사용자가 계속 접근하도록 설정을 해야한다. 이것은 Sticky session 이라고도 하는데, 이 경우 로드 밸런싱이 이루어지기는 하지만 특정 컨테이너로 트래픽이 몰릴 수 있고, 한쪽 컨테이너에서만 사용자들이 활발한 활동을 하는 경우 결국 부하가 발생하여 요청에 대한 응답이 지연될 수 있다.

따라서, 나는 마이크로서비스 아키텍처를 공부하면서 얼핏 봤었던 세션 클러스터링을 직접 구현하고자 했고 이전 게시글에서 알 수 있듯이 Spring-session-jdbc 를 사용하여 MySQL을 세션 저장소로 사용했다.

그러나 조금만 서칭을 해봐도 알 수 있는데, jdbc의 경우 I/O가 많아지면 많아질수록 리소스를 많이 잡아먹기 때문에 대부분 세션 클러스터링을 하는 경우 인메모리 저장소를 사용하는 redis를 사용한다.
redis의 경우 어떤 스키마가 필요 없이 키, 밸류로 저장되기 때문에 jdbc를 사용하는 경우보다 간단하다. 그리고 인메모리에 저장되기 때문에 접근이 빠르다.

의존성 관리

Spring boot가 아니기 때문에 starter 라이브러리를 사용하지 않고, 직접 추가했다.
아래와 같은 라이브러리 의존성이 필요하다.

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

<dependency>
  <groupId>io.lettuce</groupId>
  <artifactId>lettuce-core</artifactId>
  <version>6.1.8.RELEASE</version>
</dependency>

Config 클래스

사실 설명이라고 할 것 없이 너무 간단한데,
어노테이션 하나면 설정이 전부 끝나기 때문에 필요한 빈들을 등록만 해주면 된다.

나같은 경우, 자꾸 빈 에러가 떠서 곤혹을 겪었는데 빈 하나를 덜 생성해서 였다;;

@Configuration
@EnableRedisHttpSession
public class RedisSessionConfig {
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        LettuceConnectionFactory factory = new LettuceConnectionFactory("localhost", 6379));
        return factory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        return redisTemplate;
    }

    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();

        // 쿠키 설정
        cookieSerializer.setCookiePath("/");
        cookieSerializer.setCookieName("SESSION");
        cookieSerializer.setUseSecureCookie(true);
        cookieSerializer.setUseHttpOnlyCookie(true);
        cookieSerializer.setSameSite("None");

        return cookieSerializer;
    }
}

아 중요한건 RedisTemplate이다.
이건 키, 밸류의 데이터 타입을 설정하는 템플릿인데
키와 밸류의 타입을 지정해야한다.
나의 경우에는 세션에 사용자 객체를 시큐리티를 통해서 담을 것인데 밸류에는 사용자 객체 외에도 다른 것들을 담을 수 있으므로 Object 형태로 지정해주었다.

또, 직렬화에 사용되는 Serializer를 지원해주기 때문에 코드에 나와 있는 기본 Serializer를 사용하면 된다.

마지막은 쿠키에 관한 설정인데
Session에서 발급하는 쿠키가 어떤 타입일지 지정한다.
여기서 쿠키 이름을 수정할 수 있다!

특히 API가 배포된 상태에서 localhost 개발을 위해서는 Same-site를 None로 이로 인해서 Secure는 true로 설정해주어야만 한다. 명심하쟈!

마지막으로 내가 빼먹었던 빈이 하나 있는데, 이건 applicationContext.xml에 등록해두었다.
이 녀석 역시 메소드 형태로 Bean을 정의해도 상관없다.

<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration" />

이건 Spring에서 @EnableRedisHttpSession을 사용할 수 있도록 해준다.

진짜 진짜 마지막으로는 Spring session jdbc에서 했던 것과 마찬가지로
이니셜라이저 클래스를 생성해두어야 한다.

클래스 안에 내용은 공백인데, 위에서 설정했던 빈들을 아래의 클래스에 담아도 상관없다.

public class Initializer extends AbstractHttpSessionApplicationInitializer {
}

세션 저장소 확인

redis를 설치하고 나면 명령 프롬포트 창에서

redis-cli

를 통해서 접속할 수 있다.

나도 깊게는 알지 못하지만, 저장된 값들을 보려면

keys *

명령어를 통해서 볼 수 있다.

그리고 세션이 한번 생성되면 총 네 개의 키, 밸류 쌍이 만들어진다.
이상하게 많이 생성된다고 걱정하지 않아도 된다.

소감

갈수록 Spring 설정에 익숙해지는 것 같다.
이제는 시간이 그렇게 오래 걸리지 않는다.
원래 다음 글은 nginx 로드 밸런싱 관련 글이었는데, 본 내용이 짧아서 먼저 업로드하게 되었다.

profile
최악의 환경에서 최선을 다하기

0개의 댓글