소개
이 실습에서는 HAProxy를 사용해 로드 밸런싱의 기본 개념을 배웁니다.
창구 직원이 한 명뿐인 은행을 생각해 보겠습니다. 줄이 매우 길어지고 고객들은 불만을 갖게 됩니다. 이를 해결하기 위해 은행은 여러 개의 창구를 엽니다. 하지만 이제는 입구에서 각 고객을 다음 이용 가능한 창구로 안내할 관리자가 필요합니다.
이 상황에서 각 요소는 다음과 같습니다.
- 은행 관리자는 **로드 밸런서 (HAProxy)**입니다.
- 창구 직원은 백엔드 서버(시뮬레이션한 웹 서버) 입니다.
- 고객은 웹 트래픽입니다.
Linux 에서 이 구성을 직접 만듭니다. 시뮬레이션한 웹 서버 두 개를 만들고, 가장 간단한 부하 분산 알고리즘 중 하나인 **라운드 로빈 (round robin)**을 사용해 HAProxy 가 두 서버로 트래픽을 나누도록 구성합니다.
라운드 로빈은 기본적인 로드 밸런서의 역할을 이해하는 데 유용한 출발점입니다. 정상적으로 동작하는 여러 백엔드에 연속된 요청을 분배하고, 모든 요청을 한 대의 컴퓨터로만 보내지 않기 때문입니다.
이 실습을 마치면 다음 작업을 수행할 수 있습니다.
- 간단한 Python 웹 서버를 실행합니다.
- 트래픽을 수신하는 프런트엔드 (Frontend) 와 서버로 전달하는 백엔드 (Backend) 를 HAProxy 에서 구성합니다.
- 로드 밸런싱이 실제로 동작하는 모습을 확인합니다.
터미널 준비
로드 밸런서를 테스트하려면 먼저 분산할 대상이 필요합니다. 두 개의 독립적인 웹 서버를 동시에 실행해야 합니다. 실행 중인 서버는 터미널을 점유하고 중지할 때까지 계속 실행되므로 같은 창에서 새 명령을 입력할 수 없습니다.
따라서 터미널 탭을 추가로 열어야 합니다. 여러 웹사이트를 동시에 확인하려고 웹 브라우저에서 여러 탭을 여는 것과 같습니다.
이 단계에서는 시스템의 역할을 분리합니다. Python 서버는 애플리케이션 계층을 시뮬레이션하고, 기본 터미널은 로드 밸런서 자체를 구성하는 제어 영역으로 사용합니다.
현재 터미널 (Terminal) 이 하나 열려 있습니다. 터미널을 두 개 더 여세요.
- 터미널 인터페이스에서 +(Plus) 아이콘을 찾습니다.
- + 아이콘을 두 번 클릭해 Terminal 1과 Terminal 2를 엽니다.
각 터미널은 다음과 같이 사용합니다.
- Terminal: 제어 센터 (HAProxy 구성용)
- Terminal 1: Server 1 실행
- Terminal 2: Server 2 실행
Server 1 시작
이제 첫 번째 "창구 직원"(Server 1) 을 시작합니다. 별도의 무거운 웹 서버 소프트웨어를 설치하는 대신, Python 에 기본으로 포함된 편리한 도구를 사용해 임의의 디렉터리를 웹사이트로 제공합니다.
Terminal 1로 전환합니다.
먼저 Server 1 용으로 준비된 디렉터리로 이동합니다.
cd ~/project/server1
이제 서버를 시작합니다. 서버가 포트 8001에서 요청을 수신하도록 지정합니다. 포트는 아파트 번호와 비슷합니다. 컴퓨터가 건물이라면 포트 8001 은 Server 1 이 사용하는 특정 출입문입니다.
python3 -m http.server 8001
Serving HTTP on 0.0.0.0 port 8001이라는 메시지가 표시됩니다. 이 메시지는 서버가 실행 중이며 요청을 기다리고 있다는 뜻입니다. 이제 이 터미널은 사용 중이므로 여기에는 다른 내용을 입력하지 마세요.
Server 2 시작
이제 두 번째 "창구 직원"(Server 2) 을 시작해 작업을 나누도록 합니다.
Terminal 2로 전환합니다.
Server 2 용 디렉터리로 이동합니다.
cd ~/project/server2
이 서버는 다른 포트인 8002에서 시작합니다. Server 1 이 이미 8001 을 사용하고 있으므로 8001 을 다시 사용할 수 없습니다. 두 가족이 같은 8001 번 아파트에 살 수 없는 것과 같습니다.
python3 -m http.server 8002
이제 서로 독립적인 웹 서버 두 개가 실행 중입니다. 하나는 포트 8001 에서 "Response from Server 1"을 반환하고, 다른 하나는 포트 8002 에서 "Response from Server 2"를 반환합니다.
프런트엔드 구성
서버가 준비되었으므로 이제 "은행 관리자"(HAProxy) 가 각 서버로 트래픽을 전달하도록 구성합니다.
여기서 프런트엔드와 백엔드의 역할이 나뉩니다. 프런트엔드는 클라이언트가 HAProxy 에 연결되는 방식을 정의하고, 백엔드는 실제 작업을 처리할 서버 풀을 정의합니다.
Terminal로 다시 전환합니다.
기존 구성 파일을 백업한 뒤 새 구성 파일을 만들어 처음부터 시작합니다.
sudo mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak
sudo nano /etc/haproxy/haproxy.cfg
편집기에 다음 내용을 복사해 붙여 넣습니다. 이 내용은 Frontend를 정의합니다. Frontend 는 로드 밸런서의 공개 접점으로, 고객 (사용자) 이 도착하는 곳입니다.
global
log /dev/log local0
log /dev/log local1 notice
daemon
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http_front
bind *:80
default_backend http_back
이해해야 할 핵심 내용:
bind *:80: HAProxy 가 포트 80에서 요청을 수신하도록 지정합니다. 포트 80 은 웹 트래픽 (HTTP) 에 사용하는 표준 출입구입니다. 포트를 지정하지 않고 웹사이트 이름을 입력하면 브라우저는 포트 80 으로 연결합니다.default_backend http_back: 클라이언트가 이곳에 도착하면http_back이라는 그룹으로 전달하도록 HAProxy 에 지시합니다.
이 이름은 중요합니다. HAProxy 구성은 기본적으로 트래픽 경로를 정의하는 지도와 같습니다. 프런트엔드는 연결을 수신하고, 백엔드는 연결이 전달될 수 있는 대상들을 나타냅니다.
파일을 저장합니다 (Ctrl+O, Enter). 저장한 뒤 계속 열어 두어도 되지만, 진행 상황을 단계별로 확인하려면 저장하고 종료하는 것이 좋습니다 (Ctrl+X).
백엔드 구성
이제 작업을 처리할 서버 그룹인 Backend를 정의합니다.
파일을 닫았다면 다음 명령으로 다시 엽니다.
sudo nano /etc/haproxy/haproxy.cfg
파일 끝에 다음 줄을 추가합니다.
backend http_back
server server1 127.0.0.1:8001 check
server server2 127.0.0.1:8002 check
방금 수행한 작업:
backend http_back:http_back이라는 서버 그룹을 만들었습니다.server server1 ...:127.0.0.1:8001주소 (로컬 호스트의 8001 번 포트) 에 첫 번째 서버 (Server 1) 를 등록했습니다.server server2 ...:127.0.0.1:8002주소에 두 번째 서버 (Server 2) 를 등록했습니다.check: 매우 중요한 설정입니다. HAProxy 가 주기적으로 서버가 실제로 실행 중인지 (정상 상태인지) 확인하도록 합니다. 서버에 장애가 발생하면 HAProxy 는 해당 서버로 트래픽을 보내지 않습니다.
파일을 저장하고 (Ctrl+O, Enter) 종료합니다 (Ctrl+X).
부하 분산 확인
관리자는 다음 고객을 어느 서버로 보낼지 어떻게 결정할까요? 가장 일반적인 방법은 **라운드 로빈 (Round Robin)**입니다. 간단히 말해 차례대로 분배하는 방식입니다.
- 고객 1 -> Server 1
- 고객 2 -> Server 2
- 고객 3 -> Server 1
- ...이 과정을 계속 반복합니다.
구성에 이 정책을 명시적으로 추가합니다. 구성 파일을 마지막으로 한 번 더 엽니다.
sudo nano /etc/haproxy/haproxy.cfg
방금 추가한 backend http_back 섹션을 찾아 balance 지시어를 추가하고 다음과 같이 만듭니다.
backend http_back
balance roundrobin
server server1 127.0.0.1:8001 check
server server2 127.0.0.1:8002 check
참고: 줄 시작 부분의 들여쓰기 (공백) 는 가독성을 위해 중요하지만 HAProxy 는 들여쓰기에 관대합니다. 가능한 한 깔끔하게 정리하세요.
파일을 저장하고 (Ctrl+O, Enter) 종료합니다 (Ctrl+X).
HAProxy 다시 시작 및 테스트
구성은 준비되었지만 HAProxy 는 아직 변경 내용을 적용하지 않았습니다. 변경 사항을 적용하려면 서비스를 다시 시작해야 합니다.
sudo service haproxy restart
이제 실제로 동작하는지 확인합니다. curl이라는 명령을 사용합니다. curl은 그래픽 인터페이스가 없는 웹 브라우저와 같습니다. 웹 페이지를 가져와 화면에 텍스트 내용을 표시합니다.
HAProxy 가 수신 대기 중인 기본 포트 80 에서 localhost(현재 컴퓨터) 에 연결합니다.
다음 명령을 여러 번 실행합니다.
curl localhost
"Response from Server 1"이 표시되어야 합니다. 명령을 다시 실행합니다.
curl localhost
이번에는 "Response from Server 2"가 표시되어야 합니다.
빠르게 확인하려면 다음 반복문을 실행할 수 있습니다. 이 명령은 서버에 연속으로 네 번 요청을 보냅니다.
for i in {1..4}; do
curl localhost
echo
done
출력이 정확히 1, 2, 1, 2 순서로 번갈아 표시되어야 합니다.
이 결과는 로드 밸런서가 정상적으로 동작한다는 뜻입니다. 로드 밸런서가 포트 80 에서 요청을 수신하고, 포트 8001 과 8002 사이에 작업을 공정하게 분배하고 있습니다.
요약
이 실습에서 부하가 분산되는 웹 클러스터를 성공적으로 구축했습니다.
수행한 작업은 다음과 같습니다.
- 백엔드 시뮬레이션: Python 을 사용해 서로 다른 포트 (8001, 8002) 에서 동작하는 웹 서버 두 개를 만들었습니다.
- 프런트엔드 구성: HAProxy 가 표준 웹 포트 (80) 에서 요청을 수신하도록 설정했습니다.
- 백엔드 구성: 두 서버를 작업 서버 그룹에 등록했습니다.
- 라운드 로빈: 트래픽을 차례대로 분배하는 공정한 정책을 설정했습니다.
이는 규모만 작을 뿐, 수백만 명의 사용자를 처리하기 위해 대규모 웹사이트에서 사용하는 것과 동일한 아키텍처입니다.



