📢 공지합니다
이 게시글은 메인 페이지에 항상 고정되어 표시됩니다.
로드밸런싱은 현대 웹 서비스 아키텍처에서 가장 중요한 요소 중 하나입니다. 특히 트래픽이 많은 서비스를 안정적으로 운영하기 위해서는 필수적인 기술입니다. 이 글에서는 로드밸런싱의 개념부터 구현 방법까지 상세히 알아보겠습니다.
로드밸런서는 여러 서버에 네트워크 트래픽을 분산시키는 장치 또는 기술을 말합니다. 서비스에 접속하는 클라이언트의 요청을 여러 서버에 효율적으로 분배하여 서버의 부하를 분산시키고, 전체 시스템의 가용성과 응답 속도를 향상시키는 역할을 합니다.
즉, 로드밸런싱은 작업이나 기술을 의미하며, 로드밸런서는 그 작업을 수행하는 구체적인 도구나 시스템입니다. 당신의 예시에서는 NGINX가 로드밸런서이고, NGINX가 트래픽을 세 개의 애플리케이션 서버에 분산시키는 과정이 로드밸런싱입니다.
로드밸런싱은 구현 방식과 동작 계층에 따라 여러 유형으로 나뉩니다.
L4 로드밸런서는 네트워크 계층(IP)과 전송 계층(TCP/UDP)의 정보를 바탕으로 트래픽을 분산합니다.
L7 로드밸런서는 애플리케이션 계층의 정보(HTTP, HTTPS, FTP 등)를 기반으로 트래픽을 분산합니다.
DNS 서버가 도메인에 대한 요청을 여러 IP 주소로 분산시키는 방식입니다.
로드밸런서가 요청을 분산하는 방식은 여러 알고리즘을 통해 구현됩니다.
요청을 순차적으로 각 서버에 분배하는 방식입니다.
서버의 처리 능력에 따라 가중치를 부여하여 요청을 분배합니다.
현재 연결이 가장 적은 서버에 요청을 분배합니다.
클라이언트의 IP 주소를 해시하여 특정 서버에 요청을 지속적으로 연결합니다.
응답 시간이 가장 빠른 서버에 요청을 분배합니다.
로드밸런싱 환경을 구축하는 방법은 다양합니다. 필요에 따라 적절한 방법을 선택할 수 있습니다.
AWS ELB(Elastic Load Balancer), Google Cloud Load Balancing, Azure Load Balancer 등의 클라우드 서비스를 활용하면 쉽게 로드밸런싱 환경을 구축할 수 있습니다.
NGINX는 웹 서버이자 리버스 프록시로, 로드밸런서 역할을 할 수 있습니다.
HAProxy는 고성능 TCP/HTTP 로드밸런서로, 대규모 트래픽 처리에 적합합니다.
Docker와 Docker Compose를 활용하면 컨테이너 기반의 로드밸런싱 환경을 쉽게 구축할 수 있습니다.
그럼 이젠 Docker Compose로 3개의 애플리케이션 컨테이너를 띄우고, Nginx를 이용해 가장 기본적인 L7 로드밸런싱 방식과 Round-Robin 기법으로 트래픽을 분산하는 로드밸서 환경을 구축해보겠습니다.
본 프로젝트의 시스템 아키텍처는 위와 같다. 서버는 AWS EC2를 활용했으며, 특히 인스턴스는 프리 티어 t2.micro가 아닌, 관련 업체로부터 지원받아 t3.large를 사용하였다. 확실히 서버 스펙이 크니 성능이 훨씬 뛰어났다. 참고로 t2.micro로 서버 3대 띄우면 렉걸린다....
version: '3.8'
services:
app1:
image: chltmdgh522/stdev:latest
container_name: app1
ports:
- "8081:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- REDIS_HOST=redis
- REDIS_PORT=6379
- REDIS_PASSWORD=${REDIS_PASSWORD}
depends_on:
- redis
app2:
image: chltmdgh522/stdev:latest
container_name: app2
ports:
- "8082:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- REDIS_HOST=redis
- REDIS_PORT=6379
- REDIS_PASSWORD=${REDIS_PASSWORD}
depends_on:
- redis
app3:
image: chltmdgh522/stdev:latest
container_name: app3
ports:
- "8083:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- REDIS_HOST=redis
- REDIS_PORT=6379
- REDIS_PASSWORD=${REDIS_PASSWORD}
depends_on:
- redis
redis:
image: redis
container_name: redis
command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}"]
ports:
- "6379:6379"
environment:
- REDIS_PASSWORD=${REDIS_PASSWORD}
위와 같이 포트번호를 달리해서 3개를 띄었다.
upstream backend {
server localhost:8081 max_fails=3 fail_timeout=30s;
server localhost:8082 max_fails=3 fail_timeout=30s;
server localhost:8083 max_fails=3 fail_timeout=30s;
}
server {
server_name dream.anja.p-e.kr;
location / {
proxy_pass http://backend;
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;
# 연결 유지 설정
proxy_http_version 1.1;
proxy_set_header Connection "";
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/dream.anja.p-e.kr/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/dream.anja.p-e.kr/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = dream.anja.p-e.kr) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name dream.anja.p-e.kr;
return 404; # managed by Certbot
}
그리고 위와 같이 nginx 구성 파일에 upstream backend 블록에서 3개 서버를 묶어서 로드밸런싱 그룹을 만들었고, proxy_pass http://backend 로 요청을 넘기도록 설정했다. 무엇보다 SSL 인증서(Certbot) 설정도 깔끔하게 처리도 했다.
이때 backend_servers라는 업스트림 그룹을 정의한다. (upstream이란 강의 상류를 뜻한다. 즉 위에서 아래로 '뿌려주는' 것이다.)
요청은 backend의 8080 포트로 보내고, max_fails는 최대 실패 횟수를 정의하는 것으로 여기서는 3번 연속 요청 실패 시 해당 서버를 사용하지 않도록 한다. fail_timeouts는 서버 실패 판정 후 쿨타임으로, 30초 동안 해당 서버로 요청을 보내지 않도록 한다.(헬스 체크)
Nginx 로드밸런서를 활용해 keepalive로 연결을 재활용하거나, least_conn, ip_hash 같은 분산 방식을 추가할 수 있다. 또한 SSL 트래픽을 Nginx에서 처리하거나, 보안 강화를 위해 WAF 같은 모듈을 연동하는 것도 가능하다.
docker-compose logs -f app1 app2 app3
이거는 각각의 서버 로그를 터미널에 실시간 출력하여 볼 수 있습니다.
curl -k https://도메인주소
이걸 여러 번 반복해서 치면 요청이 8081 → 8082 → 8083 이렇게 돌아가는 걸 확인할 수 있습니다.
추가로 JMeter를 활용해 다수의 동시 요청을 보내 로드밸런싱이 정상적으로 동작하는지 검증하였다. 이를 통해 서버 간 트래픽 분산이 제대로 이루어지는 것을 확인할 수 있었다.
Docker에 관해 (0) | 2025.05.09 |
---|---|
Spring vs Spring Boot (0) | 2025.05.07 |
자바의 실행 환경 (1) | 2025.05.06 |
쿠키 VS 세션 (1) | 2025.05.04 |
AccessToken과 RefreshToken 인증 방식 (1) | 2025.04.05 |