본문 바로가기
Redis

분산 환경에서 세션 스토어 만들기

by 이상한나라의개발자 2023. 12. 11.

세션 ( Session )

 

세션은 사용자가 웹 브라우저를 통해 웹 서버에 접속한 시점부터 브라우저를 종료하여 연결을 끊을 때 까지의 일련의 과정을 의미합니다.

세션을 통해 웹 서버는 각각의 사용자 정보를 일정 시간 동안 유지할 수 있습니다.

 

주요 특징

  • 네트워크 상에서 두 개 이상의 통신 장치간에 유지되는 상호 연결을 의미
  • 연결된 일정 시간 동안 유지되는 정보를 나타냄
  • 적용 대상에 따라 다른 의미를 가짐
  • 사용자 식별 : 웹은 기본적적으로 상태가 없는 (stateless) 프로토콜 입니다. 즉, 두 개의 페이지 요청 사이에 사용자 정보가 저장되지 않습니다. 세션을 사용하면 사용자마다 고유한 세션ID를 부여하고 사용자를 식별 및 그에 따른 정보를 저장할 수 있습니다.
  • 데이터 저장 : 사용자의 정보, 로그인 상태, 장바구니 내용 등을 일정 시간 동안 유지하고 싶을 때 세션을 사용하여 이러한 데이터를 저장할 수 있습니다.
  • 보안 : 쿠키와 달리 세션 데이터는 서버측에 저장되므로 사용자가 직접 접근하거나 수정하기 어렵습니다. 따라서 로그인 정보와 같은 민감한 데이터를 저장할 때 세션을 사용하면 보안성이 높아집니다.
  • 시간 제한 : 세션에는 일정 시간의 유효기간이 있습니다. 이 시간 동안 사용자가 서버에 새로운 요청을 하지 않으면 세션은 자동으로 만료 됩니다.

 

작동 방식

  • 사용자기 웹 사이트에 처음 접속하면 서버는 고유한 세션 ID를 생성합니다.
    • 세션ID 는 추정 불가능하며, 중복 되지 않는다. -> 예상 불가능한 복잡한 세션ID를 사용합니다.
  • 생성된 세션ID는 쿠키를 통해 사용자의 브라우저에 전달 됩니다.
    • 클라이언트는 요청시 항상 세션ID 쿠키를 전달 합니다.
  • 사용자가 웹 사이트 내에서 다른 페이지로 이동하거나 데이터를 요청할 때마다 세션 ID가 서버에 전달 됩니다.
  • 서버는 세션ID를 기반으로 해당 사용자의 세션 데이터를 찾아 사용합니다.
    • 서버에서는 클라이언트가 전달한 세션ID 정보로 세션 저장소를 조회해서 로그인시 보관한 세션 정보를 사용합니다.
  • 사용자가 로그아웃 하거나 일정 시간 동안 활동이 없으면 세션은 만료 됩니다.

 

세션 작동 방식

 

 

분산 환경에서의 세션 처리

 

  • 서버는 세션 정보를 저장해야 합니다.
  • 서버가 여러 대라면 최초 로그인한 서버가 아닌 서버는 세션 정보를 알지 못합니다.
  • 세션 정보를 서버간에 공유할 방법이 필요 (세션 클러스터링)
  • 요즘 서버는 스케일 아웃이 일반적 입니다

 

 

분산 환경

 

 

RDB 사용

 

  • 관계형 데이터 모델이 필요한가?
  • 영속성이 필요한 데이터인가?
  • 성능 요구사항을 충족하는가?
  • RDB를 사용하면 어느정도 요구사항은 충족 될 수 있지만, 서버에 접속할 때마다 DB를 조회하여 유저 정보를 확인해야 하는 단점이 있다.

 

DB를 사용한 방법

 

 

REDIS 사용

 

  • 세션 데이터는 단순 key-value 구조
  • 세션 데이터는 영속성이 필요 없음
  • 세션 데이터는 변경이 빈번하고 빠른 액세스 속도가 필요

 

Redis를 활용한 세션 클러스터링

 

 

Springboot + Redis를 사용한 세션클러스터링

 

아래 의존성을 추가합니다.

    implementation 'org.springframework.boot:spring-boot-starter-data-redis'
    implementation 'org.springframework.session:spring-session-data-redis'

 

 

application.yml 파일에 아래 내용을 추가합니다.

 

  redis:
    host: 127.0.0.1
    port: 6379
    password:
    lettuce:
      pool:
        max-active: 10
        max-idle: 8
        min-idle: 2

  session:
    store-type: redis
    redis:
      namespace: spring:session:redis
      flush-mode: on_save

server:
  servlet:
    session:
      cookie:
        name: mysessionId  # 쿠키 이름을 선택적으로 설정합니다.
        domain: .application.com  # 주요 도메인 앞에 '.'를 사용하여 서브도메인 간의 쿠키를 공유하게 합니다.
        path: /  # 쿠키의 경로. 일반적으로 루트로 설정됩니다.
        secure: false  # HTTPS를 사용하는 경우에만 쿠키를 전송하려면 이 값을 'true'로 설정
        http-only: true  # JavaScript에서 쿠키에 액세스할 수 없도록 설정합니다. 권장됩니다.

 

 

RedisConfig.java

 

@Configuration
@EnableRedisHttpSession(redisNamespace = "${spring.session.redis.namespace}")
public class RedisConfig {

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory();
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        ObjectMapper om = new ObjectMapper();
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setKeySerializer(new StringRedisSerializer());

        template.afterPropertiesSet();
        return template;
    }
    
    
    // 서버의 메모리가 아니라 , Redis에 저장된 세션 정보를 사용 한다.
    @Bean
    public SpringSessionBackedSessionRegistry<? extends Session> sessionRegistry() {
        return new SpringSessionBackedSessionRegistry<>(this.sessionRepository);
    }
}

 

 

/*
아래 코드는 SpringSession에서 HTTP 쿠키릴 직렬화 역직렬화 하는 역활을 합니다.
SpringSession에서는 세션 정보를 쿠키를 통해 클라이언트에게 전송하고, 이후 요청에서 해당 쿠키를 다시
받아와서 사용자의 사용자의 세션을 식별화 합니다.
*/

@Configuration
public class CookieConfig {

    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        // application.com 및 하위 도메인에서 쿠키를 공유하도록 설정
        serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
        return serializer;
    }
}

 

 

 

위와 같이 설정하게 되면 기본적으로 application.com 도메인을 가진 세션은 공유되게 됩니다. SpringSecurity의 경우 자동으로 세션정보가 redis에 저장되게 됩니다.

 

테스트 방법은 x.application.com:8080 , v.application.com:8081 두개를 띄우고 세션이 공유되는지 확인 합니다.

 

'Redis' 카테고리의 다른 글

Redis 리더보드 만들기  (0) 2023.12.11
서비스 속도를 높이는 캐시 레이어  (0) 2023.12.11
Redis 설치 및 문법  (1) 2023.12.11
RDBMS & NoSQL & Redis  (0) 2023.12.11
Redis 소개와 특징  (0) 2023.12.11