다중화 서버 구성 전략: 동시성 제어

다중화 구성
다중화란 무엇인가?
다중화는 하나의 시스템이 처리할 수 있는 작업을 여러 대의 서버로 나누어 부하를 분산하고, 장애 발생 시 시스템 안정성을 유지하기 위한 핵심적인 설계 전략이다. 이는 대규모 트래픽을 처리하거나, 높은 가용성을 요구하는 시스템에서 필수적으로 고려되는 기술이다.

실무에서 다중화는 다양한 방식으로 구현될 수 있다. 가장 일반적인 방식은 L4 스위치를 이용한 부하 분산이다. 하지만, 하드웨어 스위치를 사용할 수 없는 환경에서는 소프트웨어 기반으로 작업을 분배하거나, 데이터베이스를 통해 트랜잭션을 조율하는 방법도 존재한다.
이 글에서는 내가 실제로 실무에서 고민하고 적용했던 다중화 구성의 세 가지 방법을 소개하고, 각 방식의 특징, 장단점, 적용 사례를 설명한다

다중화 서버 아키텍처의 세 가지 구성 방식(L4 스위치 기반, Master-Slave 서버 구조, 그리고 DB 기반의 Select for Update 방식)을 시각적으로 나타낸 것이다.
- L4 스위치 기반 다중화: L4 스위치가 클라이언트 요청을 여러 서버(Server A, B, C)로 분배하는 구조.
- Master-Slave 구조: Master 서버가 작업 상태를 관리하고, Slave 서버(Slave A, B, C)에 작업을 분배.
- DB 기반 Select for Update: Shared DB에서 작업을 가져와 각 Worker 서버(Worker A, B, C)가 개별적으로 작업을 수행.
다중화 서버 구성 전략 방안
1. L4 스위치 기반 다중화

L4 스위치란?
L4 스위치는 OSI 7계층 중 4계층(전송 계층)에서 동작하는 네트워크 장비로, 클라이언트의 요청을 서버 풀(Server Pool)로 분배하는 역할을 수행한다.
트래픽 분석은 TCP/UDP 프로토콜 정보를 기반으로 하며, 요청을 분석해 적절한 서버로 전달한다. 주로 로드 밸런싱과 고가용성을 위한 핵심 장비로 사용된다.
구성 방식
- L4 스위치:
- 클라이언트의 요청을 받아 적절한 서버로 전달.
- 라운드 로빈(Round Robin), 최소 연결(Minimum Connection) 등의 부하 분산 알고리즘을 사용.
- 서버 풀(Server Pool):
- 여러 대의 서버로 구성되며, 각 서버가 동일한 작업을 수행할 수 있도록 설정.
- 헬스 체크(Health Check):
- 서버 상태를 주기적으로 모니터링하여 장애 서버를 자동으로 제외.
- 클라이언트 요청이 정상 서버로만 전달되도록 보장.
작동 원리
- 클라이언트가 특정 서비스(예: 웹 애플리케이션)에 접속 요청을 보냄.
- L4 스위치가 요청을 수신하고, 부하 분산 알고리즘에 따라 적절한 서버로 요청을 전달.
- 서버가 요청을 처리하고 결과를 클라이언트에 반환.
장점
- 성능 향상:
- 요청을 서버 간 분산하여 각 서버의 부하를 줄이고, 응답 속도를 개선.
- 안정성:
- 특정 서버에 장애가 발생해도 나머지 서버가 요청을 처리할 수 있음.
- 확장성:
- 서버를 손쉽게 추가하거나 제거할 수 있어 유연한 확장이 가능.
단점
- 하드웨어 의존성:
- L4 스위치 장비에 대한 의존도가 높아 장비가 장애를 일으키면 시스템 전체에 영향을 줄 수 있음.
- 비용 문제:
- 고성능 L4 스위치 장비는 가격이 높으며, 설치 및 유지보수에도 비용이 추가됨.
- 복잡성:
- 초기 설정 및 관리가 복잡하며, 전문 네트워크 엔지니어가 필요.
구성 예시
- L4 스위치 → Server Pool:
- L4 스위치가 모든 트래픽을 수집하고, 이를 서버 A, B, C로 균등하게 분배.
가장 안정적인 다중화 방식은 L4 스위치를 이용한 아키텍처 설계이다. L4 스위치는 하드웨어 기반으로 트래픽을 효율적으로 분배하고, 고가용성을 제공하기 때문에 대규모 시스템에서 널리 사용된다. 그러나 구축 환경의 비용적 제한이나 정책적 제약으로 인해 L4 스위치를 사용하지 못하는 경우도 적지 않다.
이러한 상황에서, L4 스위치를 대체할 수 있는 소프트웨어 기반 다중화 방식을 설계하는 것이 필요했다. 이에 따라, L4 없이도 안정적이고 효율적인 다중화 환경을 구현할 수 있는 다양한 방안을 고민하고 도입하게 되었다.
2. Master-Slave 아키텍처

Master-Slave 아키텍처는 L4 스위치를 사용할 수 없는 환경에서 다중화를 구현하기 위한 소프트웨어 기반 방식이다. 이 구조에서는 Master 서버가 중앙에서 작업을 관리하고, Slave 서버가 실제 작업을 수행하는 역할을 맡는다. 이를 통해 부하를 분산하고 작업을 효율적으로 처리할 수 있다.
Master-Slave 방식에 대한 고민
L4 스위치와 같은 하드웨어 장비가 없는 상황에서, 중앙 제어 방식으로 작업을 분배해야 했다. 이를 해결하기 위해 Master-Slave 구조를 설계하게 되었으며, Master 서버가 작업을 효율적으로 관리하고 Slave 서버가 실제로 작업을 수행하는 체계를 구축하였다.
Master-Slave 아키텍처의 작동 원리
- Master 서버:
- 전체 작업 리스트를 관리하며, 각 Slave 서버의 상태(Idle, Busy 등)를 모니터링한다.
- 대기 상태의 Slave 서버에게 작업을 할당하고, 작업 상태를 지속적으로 업데이트한다.
- Slave 서버:
- Master 서버로부터 작업을 전달받아 처리한다.
- 작업이 완료되면 Master 서버에 상태를 보고하여 새로운 작업을 할당받을 준비를 한다.
구성 요소 및 흐름
- Master 서버의 역할:
- Slave 서버들의 상태를 주기적으로 확인.
- Idle 상태의 Slave 서버에 작업을 분배.
- 작업 진행 상태(진행 중, 완료, 오류)를 기록.
- Slave 서버의 역할:
- 작업을 받아 실제 처리를 수행.
- 작업 완료 후 Master 서버에 완료 상태 보고.
- 작업 상태 관리:
- 작업의 상태를 DB나 캐시를 통해 관리하며, 상태는 주로 다음과 같은 단계로 나뉜다:
- 대기(Idle)
- 진행 중(Running)
- 완료(Complete)
- 작업의 상태를 DB나 캐시를 통해 관리하며, 상태는 주로 다음과 같은 단계로 나뉜다:
장점
- 중앙 집중화 관리:
- Master 서버에서 모든 작업과 상태를 일원화하여 관리할 수 있다.
- 비용 효율성:
- L4 스위치를 사용하지 않아도 소프트웨어 기반으로 다중화를 구현 가능.
- 확장성:
- Slave 서버를 필요에 따라 추가하거나 제거할 수 있어 유연한 확장이 가능하다.
단점
- 병목현상:
- Master 서버가 모든 작업을 제어하기 때문에 병목점(Bottleneck)이 될 가능성이 있다.
- 구현 복잡성:
- Master-Slave 간 통신 로직과 상태 관리 로직이 복잡하며, 잘못 설계되면 성능 저하로 이어질 수 있다.
- 장애 위험:
- Master 서버가 장애를 일으키면 전체 시스템이 작동하지 않을 위험이 있다.
3. Select for Update 기반 작업 분배

Select for Update는 다중 서버 환경에서 데이터베이스를 이용해 작업을 분배하고, 중복 작업을 방지하기 위한 강력한 트랜잭션 제어 메커니즘이다. 이 방식에서는 데이터베이스가 작업 상태를 중앙에서 관리하며, 각 서버(Worker)가 작업을 가져가서 수행한다.
Select for Update 방식에 대한 고민
L4 스위치나 Master 서버를 사용할 수 없는 환경에서, 각 서버가 스스로 작업을 가져가도록 설계해야 했다. 이를 해결하기 위해 데이터베이스의 SELECT FOR UPDATE 기능을 활용하였다. 이를 통해 동일한 작업을 여러 서버가 중복 수행하지 않도록 보장하면서, 데이터베이스가 중앙 관리 역할을 하도록 구현했다.
Select for Update 아키텍처의 작동 원리
- 작업 테이블:
- 작업 상태를 관리하는 테이블로, 각 작업은 고유 ID(PK)를 가진다.
- 작업 상태는 주로 다음과 같은 단계를 가진다:
대기(Pending)
진행 중(Processing)
완료(Completed)
- Worker 서버:
- 각 서버는 작업 테이블에서
SELECT FOR UPDATE
를 통해 하나의 작업을 가져온다. - 락이 걸린 작업은 다른 서버가 접근하지 못한다.
- 각 서버는 작업 테이블에서
- 트랜잭션 제어:
- Worker는 작업 수행 중 데이터베이스와 지속적으로 상태를 동기화한다.
- 작업 완료 후 상태를 업데이트하여 다른 서버가 새로운 작업을 가져갈 수 있도록 한다.
구성 요소 및 흐름
- Shared Database:
- 작업 리스트와 상태 정보를 저장.
- 트랜잭션 기반으로 작업 상태를 업데이트하여 중복 작업 방지.
- Worker 서버들:
- 각각 독립적으로 동작하며, 작업 테이블에서 대기 상태의 작업을 가져와 처리.
- 작업 완료 후 상태를 “완료(Completed)”로 업데이트.
- 작업 상태 관리:
SELECT FOR UPDATE
를 통해 작업에 락을 걸어 중복 처리를 방지.- 상태가 “완료(Completed)”로 업데이트되면 해당 작업은 다른 서버가 접근하지 않음.
작업 흐름
- 작업 가져오기:
- Worker 서버가
SELECT FOR UPDATE
로 작업 테이블에서 대기 상태의 작업을 조회. - 락이 걸린 작업은 다른 Worker가 가져가지 못함.
- Worker 서버가
- 작업 수행:
- Worker는 작업을 처리하며, 작업 중간에 예외가 발생하면 트랜잭션을 롤백.
- 작업 완료:
- Worker는 작업 완료 후 상태를 “완료(Completed)”로 업데이트.
- 다른 Worker가 새로운 작업을 가져갈 수 있도록 상태를 해제.
장점
- 중복 작업 방지:
- 데이터베이스 락을 통해 동일 작업이 여러 서버에서 중복 처리되지 않음.
- 중앙 집중 관리:
- Shared Database가 작업 상태를 중앙에서 관리하므로 단일 장애 지점이 없다.
- L4 스위치나 Master 서버 없이도 구현 가능:
- 하드웨어나 중앙 제어 서버 없이 소프트웨어로 작업 분배를 구현할 수 있다.
단점
- 교착 상태 발생 가능:
- 여러 서버가 동일한 작업을 락하려고 시도하면 Deadlock(교착 상태)이 발생할 수 있다.
- 성능 문제:
- 트랜잭션 충돌이 잦아지면 성능 저하가 발생할 수 있다.
- 복잡성:
- 작업 테이블 설계 및 트랜잭션 관리 로직이 복잡하며, 잘못 설계되면 시스템 안정성이 저하될 수 있다.