로드 밸런싱 간 세션 유지

Kevin·2025년 6월 6일

Server

목록 보기
12/14
post-thumbnail

서론

이번에 프로젝트에서 모종의 사유로 인해서 ALB를 통해 로드 밸런싱을 하던 것을 Nginx에서 로드 밸런싱을 하도록 변경 하였다.

이 때 ALB에서 지원하던 Sticky Session을 Nginx에서 동일하게 적용할 필요가 있었다.

Nginx에는 일반적으로 사용하는 리버스 프록시 목적 외에도 여러 기능들이 존재한다.

이번 글에서는 로드 밸런싱간 세션을 유지 해야 하는 이유와 Nginx에서 세션을 유지 하는 방법을 다룰 것이다.


본론

여러 기능들 중 로드 밸런싱이라는 기능이 있다.

로드 밸런싱은 네트워크나 서버 환경에서 발생하는 트래픽을 여러 대의 서버로 특정 알고리즘을 통해 분산 시켜 처리하는 기술을 의미한다.

로드 밸런싱을 통해 서버의 부하를 분산 시켜 가용성을 향상 시킬 수 있다.

https://wikidocs.net/223781

  • 해당 링크를 통해서 다양한 Nginx의 기능들을 살펴볼 수 있다.

Nginx에서는 아래 설정을 통해 로드 밸런싱을 할 수 있다.

http {
    upstream spring_cluster {
        server 192.168.0.10:8080;   # WAS1 
        server 192.168.0.11:8080;   # WAS2
    }

    server {
        listen       80;
        server_name  example.com;    # 실제 도메인 또는 IP

        proxy_set_header   Host              $host;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;

        location / {
            proxy_pass http://spring_cluster;
        }
    }
}

위 upstream에서 로드밸런서 알고리즘 지정이 별도로 없으면 라운드 로빈 방식이다.

이 때 아래의 예시를 통해 질문을 해보자.

A 서버에서 로그인을 하여 세션을 저장 하였다.

그 후 라운드 로빈에 의해서 B 서버로 요청이 핸들링 되면 재 로그인을 해야 하는걸까?

위의 질문은 간단하게 말하면, 로드밸런싱간 세션을 어떻게 유지 할 수 있을 것인가이다.


Sticky Session

이는 Sticky Session으로 가능하다.

Sticky Session은 요청자의 session을 특정 기간 동안 동일한 서버에 계속 요청을 하게 하는 기능을 의미한다.

  • 이 때 특정 기간은 쿠키에 명시 되어 있다.

해당 기능을 통해서 사용자가 최초 요청시 A 서버로 연결을 보내면, 이후 요청도 동일한 사용자는 계속 같은 A 서버로 보내도록 고정 할 수 있다.

Nginx에서는 클라이언트의 IP를 기준으로 일정한 WAS로 연결 하는 ip_hash 방법을 사용 하거나, 특정 쿠키를 기반으로 라우팅 하는 nginx-sticky-module 방법을 쓸 수 있다.

이 방식을 통해 WAS 내부의 메모리 기반 세션(ex: Tomcat의 HttpSession)을 별도 복제 없이 유지할 수 있다.


http {
    upstream spring_cluster {
		    ip_hash;
		    # sticky cookie srv_id expires=1h domain=.example.com path=/;
    
        server 192.168.0.10:8080;   # WAS1 
        server 192.168.0.11:8080;   # WAS2
    }

    server {
        listen       80;
        server_name  example.com;    # 실제 도메인 또는 IP

        proxy_set_header   Host              $host;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;

        location / {
            proxy_pass http://spring_cluster;
        }
    }
}

위 설정을 통해서 간단하게 클라이언트 식별 방식을 선택 할 수 있다.

단 쿠키 기반 방식을 사용 하기 위해서는 Nginx 오픈소스용 nginx-sticky-module(Third-Party Module)이나, Nginx Plus의 sticky 지시어를 사용해야 한다.

/usr/local/src/nginx-sticky-module-ng \
    --add-module=/path/to/nginx-sticky-module-ng

위와 같이 컴파일 해서 설치한 뒤 사용할 수 있다.


외부 세션 저장소 사용

위와 같이 Nginx를 통해 클라이언트를 식별 해 세션을 유지 하는 방법 외에 Redis와 같은 외부 세션 저장소를 사용하여 세션을 유지 하는 방법도 존재한다.

이 때 일반적으로 Redis와 같은 별도 저장소가 설치 및 실행 되어있어야 하고, 추가 설정이 있어 구현 난이도는 더 높다.

그러나 전자는 WAS 장애 발생시 해당 WAS의 세션이 전부 유실 된다는 것과 오토 스케일링 환경에서 유연성이 부족하다는 문제등이 있다.

아래는 Spring boot를 사용하는 가정 하에 Redis에서 세션을 유지 하는 방법에 대해서 다룬다.




1. Spring Session Data Redis 와 Spring Data Redis 의존성을 설치한다.

```groovy
dependencies {
    // Spring Data Redis (Lettuce 기반)
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'

    // Spring Session Data Redis
    implementation 'org.springframework.session:spring-session-data-redis'
}
```

2. application.yml에서 세션 저장소를 redis로 사용하겠다 명시한다.
spring:
  redis:
    host: 127.0.0.1
    port: 6379

  session:
    store-type: redis      # Redis를 세션 저장소로 사용
    timeout: 1800          # 예: 1800초 = 30분
profile
Hello, World! \n

0개의 댓글