본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 5. · 18 Views
가용성과 이중화 완벽 가이드
서비스가 절대 멈추지 않게 하는 비밀, 가용성과 이중화에 대해 알아봅니다. 로드 밸런싱부터 프록시, 고가용성 구성까지 초급 개발자를 위해 쉽게 설명합니다.
목차
1. 가용성이란
김개발 씨가 운영하는 쇼핑몰 서비스가 갑자기 다운되었습니다. 고객 문의가 빗발치고, 매출 손실이 눈덩이처럼 불어납니다.
"서비스가 왜 이렇게 자주 죽는 거죠?" 이 질문에 대한 답이 바로 가용성입니다.
**가용성(Availability)**이란 시스템이 정상적으로 사용 가능한 시간의 비율을 의미합니다. 마치 24시간 편의점처럼 언제든 문을 열고 있어야 고객이 찾아올 수 있는 것과 같습니다.
가용성이 높을수록 서비스 중단 시간이 짧아지고, 사용자 신뢰도가 높아집니다.
다음 코드를 살펴봅시다.
// 가용성 계산 예제
const totalTime = 365 * 24 * 60; // 1년을 분 단위로
const downtimeMinutes = 52.56; // 연간 허용 다운타임
// 가용성 계산 함수
function calculateAvailability(uptime, total) {
const availability = (uptime / total) * 100;
return availability.toFixed(4);
}
// 99.99% 가용성 = Four Nines
const uptime = totalTime - downtimeMinutes;
const availability = calculateAvailability(uptime, totalTime);
console.log(`가용성: ${availability}%`); // 99.99%
김개발 씨는 스타트업에서 백엔드 개발자로 일하고 있습니다. 어느 날 새벽 3시, 갑자기 휴대폰이 울렸습니다.
서비스 장애 알림이었습니다. 부랴부랴 일어나 문제를 해결했지만, 이미 많은 사용자들이 불편을 겪은 후였습니다.
다음 날 출근한 김개발 씨에게 CTO 박시니어 씨가 물었습니다. "우리 서비스의 가용성이 몇 퍼센트인지 알아요?" 김개발 씨는 가용성이라는 단어를 처음 들어보았습니다.
그렇다면 가용성이란 정확히 무엇일까요? 쉽게 비유하자면, 가용성은 마치 병원 응급실과 같습니다.
응급실은 365일 24시간 문을 열어야 합니다. 환자가 새벽에 오든, 명절에 오든 언제나 진료를 받을 수 있어야 합니다.
이처럼 웹 서비스도 사용자가 언제 접속하든 정상적으로 동작해야 합니다. 가용성은 보통 퍼센트로 표현합니다.
99%라고 하면 높아 보이지만, 실제로 계산해보면 연간 약 3.65일, 즉 87시간이나 서비스가 중단될 수 있다는 뜻입니다. 이 시간 동안 얼마나 많은 고객을 잃을지 상상해 보세요.
업계에서는 **나인(Nine)**이라는 표현을 씁니다. 99.9%는 Three Nines, 99.99%는 Four Nines라고 부릅니다.
Four Nines를 달성하면 연간 다운타임이 약 52분에 불과합니다. 대형 서비스들은 보통 이 수준을 목표로 합니다.
그런데 왜 100%가 아닌 99.99%일까요? 완벽한 가용성은 현실적으로 불가능하기 때문입니다.
서버 점검, 소프트웨어 업데이트, 예기치 못한 장애 등 다운타임은 피할 수 없습니다. 중요한 것은 이 시간을 최소화하는 것입니다.
가용성을 높이기 위해서는 여러 가지 전략이 필요합니다. 서버를 여러 대 준비하거나, 자동으로 장애를 감지하고 복구하는 시스템을 구축해야 합니다.
이런 기술들을 통틀어 고가용성(High Availability) 아키텍처라고 부릅니다. 위 코드를 살펴보면, 1년을 분 단위로 환산한 후 다운타임을 빼서 가용성을 계산합니다.
이렇게 수치화하면 서비스 품질을 객관적으로 측정할 수 있습니다. 많은 기업들이 SLA(Service Level Agreement)에 가용성 수치를 명시합니다.
다시 김개발 씨 이야기로 돌아가 봅시다. 박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다.
"아, 그래서 서버를 여러 대 두는 거군요!" 가용성을 이해하면 왜 이중화가 필요한지 자연스럽게 알게 됩니다.
실전 팁
💡 - SLA 계약 시 가용성 수치를 반드시 확인하고, 위반 시 보상 조건도 명시하세요
- 가용성 목표는 비즈니스 요구사항에 맞게 설정하되, 비용 대비 효과를 고려하세요
2. 이중화 기술
김개발 씨가 서버 한 대로 서비스를 운영하다가 하드디스크가 고장났습니다. 백업도 없어서 데이터를 모두 잃어버렸습니다.
"서버가 하나뿐이면 이렇게 위험한 거였어요?" 이때 필요한 것이 바로 이중화입니다.
**이중화(Redundancy)**란 시스템의 핵심 구성 요소를 두 개 이상 준비해두는 것입니다. 마치 자동차에 스페어 타이어를 싣고 다니는 것처럼, 하나가 고장 나도 다른 하나가 역할을 대신합니다.
이를 통해 단일 장애점(Single Point of Failure)을 제거할 수 있습니다.
다음 코드를 살펴봅시다.
// 이중화된 데이터베이스 연결 예제
const databases = {
primary: { host: 'db-primary.example.com', port: 5432 },
secondary: { host: 'db-secondary.example.com', port: 5432 }
};
async function connectDatabase() {
try {
// 주 데이터베이스 연결 시도
const conn = await connect(databases.primary);
console.log('Primary DB 연결 성공');
return conn;
} catch (error) {
// 주 DB 실패 시 보조 DB로 전환
console.log('Primary DB 실패, Secondary로 전환');
return await connect(databases.secondary);
}
}
김개발 씨는 서버 장애로 큰 손실을 겪은 후, 박시니어 씨에게 조언을 구했습니다. "어떻게 하면 이런 일을 막을 수 있을까요?" 박시니어 씨가 대답했습니다.
"계란을 한 바구니에 담지 말라는 속담 알죠? 서버도 마찬가지예요.
이중화를 해야 합니다." 이중화란 무엇일까요? 쉽게 말해 백업 시스템을 항상 준비해두는 것입니다.
비행기를 생각해 보세요. 비행기에는 엔진이 여러 개 달려 있습니다.
하나의 엔진이 고장 나도 나머지 엔진으로 비행을 계속할 수 있습니다. 이것이 바로 이중화의 핵심 개념입니다.
이중화에는 크게 두 가지 방식이 있습니다. 첫 번째는 Active-Standby 방식입니다.
평소에는 주(Primary) 서버만 일하고, 보조(Secondary) 서버는 대기합니다. 주 서버가 죽으면 보조 서버가 즉시 업무를 이어받습니다.
두 번째는 Active-Active 방식입니다. 두 서버가 동시에 일합니다.
부하를 나눠서 처리하므로 성능도 좋아지고, 하나가 죽어도 나머지가 계속 일할 수 있습니다. 다만 데이터 동기화가 복잡해지는 단점이 있습니다.
이중화의 핵심은 **단일 장애점(SPOF, Single Point of Failure)**을 제거하는 것입니다. 단일 장애점이란 그것이 고장 나면 전체 시스템이 멈추는 지점을 말합니다.
서버가 하나뿐이라면 그 서버가 바로 단일 장애점입니다. 위 코드를 보면, 데이터베이스 연결 시 먼저 주 데이터베이스를 시도합니다.
연결에 실패하면 자동으로 보조 데이터베이스로 전환합니다. 이렇게 페일오버(Failover) 로직을 구현하면 장애 상황에서도 서비스를 유지할 수 있습니다.
실제 현업에서는 서버뿐 아니라 네트워크 장비, 스토리지, 전원 공급 장치까지 모두 이중화합니다. 데이터센터 자체를 두 곳에 두는 경우도 있습니다.
이를 **지리적 이중화(Geo-Redundancy)**라고 합니다. 주의할 점도 있습니다.
이중화는 비용이 많이 듭니다. 서버를 두 배로 준비해야 하니까요.
따라서 비즈니스 중요도에 따라 이중화 수준을 결정해야 합니다. 모든 시스템을 무조건 이중화하는 것은 낭비일 수 있습니다.
김개발 씨는 이제 서버 두 대를 준비하고, 자동 페일오버 시스템을 구축했습니다. 더 이상 새벽에 장애 알림으로 잠을 깨지 않아도 됩니다.
이중화는 개발자의 수면권을 지켜주는 기술이기도 합니다.
실전 팁
💡 - 이중화 시스템은 정기적으로 페일오버 테스트를 수행하여 실제로 작동하는지 확인하세요
- Active-Active 구성 시 데이터 정합성 관리에 특히 주의를 기울이세요
3. 로드 밸런싱 개념과 알고리즘
김개발 씨의 서비스가 인기를 끌면서 사용자가 급증했습니다. 서버 한 대로는 감당이 안 됩니다.
"서버를 늘리면 되지 않을까요?" 맞습니다. 하지만 여러 대의 서버에 요청을 어떻게 분배할까요?
이때 등장하는 것이 로드 밸런싱입니다.
**로드 밸런싱(Load Balancing)**은 들어오는 트래픽을 여러 서버에 분산시키는 기술입니다. 마치 놀이공원 입구에서 줄을 여러 갈래로 나누어 대기 시간을 줄이는 것과 같습니다.
이를 통해 특정 서버에 부하가 집중되는 것을 방지하고, 전체 시스템의 처리 능력을 높일 수 있습니다.
다음 코드를 살펴봅시다.
// 로드 밸런싱 알고리즘 구현 예제
const servers = ['server1', 'server2', 'server3'];
let currentIndex = 0;
// 라운드 로빈 방식
function roundRobin() {
const server = servers[currentIndex];
currentIndex = (currentIndex + 1) % servers.length;
return server;
}
// 가중치 기반 방식 (서버 성능에 따라 가중치 부여)
const weights = { server1: 5, server2: 3, server3: 2 };
function weightedRandom() {
const totalWeight = Object.values(weights).reduce((a, b) => a + b);
let random = Math.random() * totalWeight;
for (const [server, weight] of Object.entries(weights)) {
random -= weight;
if (random <= 0) return server;
}
}
김개발 씨의 쇼핑몰이 TV에 소개되면서 접속자가 폭발적으로 늘었습니다. 서버 CPU 사용률이 100%를 찍고, 응답 속도가 느려지기 시작했습니다.
급하게 서버를 두 대 더 추가했지만, 모든 요청이 여전히 첫 번째 서버로만 들어옵니다. 박시니어 씨가 다가와 말했습니다.
"서버만 늘리면 뭐해요. 로드 밸런서를 붙여야죠." 로드 밸런서는 교통 경찰과 같습니다.
교통 경찰이 차량을 여러 차선으로 유도하듯, 로드 밸런서는 사용자 요청을 여러 서버로 분배합니다. 특정 서버에 차가 몰리지 않도록 조절하는 것이죠.
로드 밸런싱에는 여러 가지 알고리즘이 있습니다. 가장 단순한 것이 라운드 로빈(Round Robin) 방식입니다.
순서대로 돌아가며 서버에 요청을 배분합니다. 서버1, 서버2, 서버3, 다시 서버1...
이런 식으로요. 구현이 간단하고 공평합니다.
하지만 서버마다 성능이 다르다면 어떨까요? 성능이 좋은 서버에 더 많은 요청을 보내는 것이 효율적입니다.
이때 사용하는 것이 가중치 기반(Weighted) 방식입니다. 성능에 따라 가중치를 부여하고, 그 비율대로 요청을 분배합니다.
최소 연결(Least Connection) 방식도 있습니다. 현재 연결이 가장 적은 서버로 요청을 보냅니다.
처리 시간이 긴 요청이 섞여 있을 때 유용합니다. 바쁜 서버에 일을 더 주지 않으니까요.
IP 해시(IP Hash) 방식은 클라이언트 IP 주소를 기준으로 서버를 결정합니다. 같은 사용자는 항상 같은 서버로 연결됩니다.
세션 유지가 필요한 경우에 유용하지만, 특정 서버에 부하가 몰릴 수 있다는 단점이 있습니다. 위 코드에서 라운드 로빈 함수는 currentIndex를 사용해 서버를 순환합니다.
모듈로 연산을 통해 인덱스가 배열 길이를 넘어가면 다시 0부터 시작합니다. 가중치 방식은 난수를 이용해 가중치에 비례한 확률로 서버를 선택합니다.
실무에서는 AWS의 ELB, Nginx, HAProxy 같은 전문 로드 밸런서를 사용합니다. 이들은 서버 상태를 주기적으로 확인하는 헬스 체크(Health Check) 기능도 제공합니다.
죽은 서버에는 요청을 보내지 않습니다. 김개발 씨는 Nginx를 설치하고 로드 밸런싱을 설정했습니다.
이제 세 대의 서버가 사이좋게 일을 나눠서 처리합니다. 트래픽이 몰려도 끄떡없는 시스템이 완성되었습니다.
실전 팁
💡 - 헬스 체크 주기와 타임아웃 설정을 서비스 특성에 맞게 조정하세요
- 세션 기반 서비스라면 스티키 세션 또는 세션 클러스터링을 고려하세요
4. L4와 L7 로드 밸런서 차이
김개발 씨가 로드 밸런서를 알아보다가 L4, L7이라는 용어를 발견했습니다. "L4랑 L7이 뭐가 다른 거예요?" 박시니어 씨가 웃으며 대답합니다.
"OSI 7계층 기억나요? 거기서 나온 개념이에요."
L4 로드 밸런서는 전송 계층(4계층)에서 동작하며 IP 주소와 포트 번호를 기준으로 트래픽을 분산합니다. L7 로드 밸런서는 응용 계층(7계층)에서 동작하며 HTTP 헤더, URL, 쿠키 등 애플리케이션 수준의 정보를 활용합니다.
L7이 더 똑똑하지만, L4가 더 빠릅니다.
다음 코드를 살펴봅시다.
// L4 로드 밸런서 - IP와 포트 기반 라우팅
const l4Rules = {
'80': ['web-server-1', 'web-server-2'],
'3000': ['api-server-1', 'api-server-2']
};
function l4Route(port) {
const servers = l4Rules[port];
return servers[Math.floor(Math.random() * servers.length)];
}
// L7 로드 밸런서 - URL 경로 기반 라우팅
function l7Route(request) {
const { path, headers } = request;
if (path.startsWith('/api')) return 'api-cluster';
if (path.startsWith('/static')) return 'cdn-cluster';
if (headers['X-Mobile-App']) return 'mobile-cluster';
return 'web-cluster';
}
김개발 씨는 네트워크 시간에 배운 OSI 7계층이 가물가물합니다. 박시니어 씨가 간단히 설명해 주었습니다.
"간단히 말해서, L4는 편지 봉투만 보고, L7은 편지 내용까지 읽는 거예요." L4 로드 밸런서는 전송 계층에서 동작합니다. 패킷의 헤더에 있는 IP 주소와 포트 번호만 확인합니다.
내용물은 보지 않습니다. 마치 우체부가 봉투의 주소만 보고 배달하는 것과 같습니다.
그래서 속도가 빠릅니다. 반면 L7 로드 밸런서는 응용 계층에서 동작합니다.
HTTP 요청의 모든 것을 들여다봅니다. URL 경로, 헤더, 쿠키, 심지어 요청 본문까지 분석할 수 있습니다.
더 똑똑한 라우팅이 가능하지만, 그만큼 처리 시간이 더 걸립니다. 언제 L4를 쓰고, 언제 L7을 쓸까요?
단순히 여러 서버에 트래픽을 분산하기만 하면 된다면 L4로 충분합니다. TCP/UDP 수준에서 빠르게 처리합니다.
게임 서버나 실시간 통신 서비스에서 많이 사용합니다. 하지만 /api 경로는 API 서버로, /images 경로는 이미지 서버로 보내고 싶다면 L7이 필요합니다.
모바일 앱에서 온 요청은 모바일 전용 서버로, 웹 브라우저 요청은 웹 서버로 분기하는 것도 L7에서만 가능합니다. L7 로드 밸런서의 또 다른 장점은 **SSL 종료(SSL Termination)**입니다.
HTTPS 암호화를 로드 밸런서에서 해제하고, 백엔드 서버에는 일반 HTTP로 전달합니다. 서버의 암호화 부담을 줄여줍니다.
위 코드에서 l4Route 함수는 포트 번호만 보고 서버를 선택합니다. 반면 l7Route 함수는 요청 경로와 헤더를 분석합니다.
/api로 시작하면 API 클러스터로, 모바일 앱 헤더가 있으면 모바일 클러스터로 보냅니다. 실무에서 AWS ALB(Application Load Balancer)는 L7, NLB(Network Load Balancer)는 L4입니다.
Nginx도 설정에 따라 L4와 L7 모두 가능합니다. 보통 L7을 앞에 두고, 필요하면 그 뒤에 L4를 배치하기도 합니다.
김개발 씨는 쇼핑몰에 L7 로드 밸런서를 적용했습니다. 상품 이미지 요청은 CDN으로, API 요청은 백엔드 서버로, 관리자 페이지 요청은 별도 서버로 라우팅합니다.
각 서버가 자기 역할에 집중할 수 있게 되었습니다.
실전 팁
💡 - 단순 분산이 목적이면 L4, 콘텐츠 기반 라우팅이 필요하면 L7을 선택하세요
- L7은 WAF(Web Application Firewall) 기능과 함께 사용하면 보안도 강화됩니다
5. 포워드 프록시
김개발 씨가 회사에서 특정 사이트에 접속하려는데 차단되어 있습니다. "왜 이 사이트가 안 열리죠?" 옆자리 동료가 대답합니다.
"회사에서 프록시 서버를 쓰거든요. 거기서 막히는 거예요." 프록시란 도대체 무엇일까요?
**포워드 프록시(Forward Proxy)**는 클라이언트와 인터넷 사이에 위치하여 클라이언트를 대신해 요청을 보내는 중간 서버입니다. 마치 비서가 사장님 대신 전화를 거는 것처럼, 클라이언트의 신원을 숨기고 요청을 대리합니다.
접근 제어, 캐싱, 익명성 확보 등에 활용됩니다.
다음 코드를 살펴봅시다.
// 포워드 프록시 개념 시뮬레이션
class ForwardProxy {
constructor() {
this.cache = new Map();
this.blockedSites = ['blocked-site.com'];
}
request(clientIP, targetURL) {
// 접근 제어: 차단된 사이트 확인
if (this.blockedSites.some(site => targetURL.includes(site))) {
return { status: 403, message: '접근 차단됨' };
}
// 캐시 확인
if (this.cache.has(targetURL)) {
return { status: 200, data: this.cache.get(targetURL), cached: true };
}
// 실제 요청 (클라이언트 IP는 숨겨짐)
const response = this.fetchFromInternet(targetURL);
this.cache.set(targetURL, response);
return { status: 200, data: response, cached: false };
}
}
김개발 씨가 회사에서 인터넷을 사용할 때, 모든 요청은 회사의 프록시 서버를 거쳐 나갑니다. 왜 이런 구조를 사용하는 걸까요?
포워드 프록시를 이해하려면 대리인을 떠올리면 됩니다. 연예인이 직접 식당에 전화하지 않고 매니저를 통하는 것처럼, 클라이언트가 직접 인터넷에 접속하지 않고 프록시를 통합니다.
외부에서는 연예인이 아닌 매니저의 번호만 보입니다. 포워드 프록시의 첫 번째 역할은 접근 제어입니다.
회사나 학교에서 특정 사이트 접속을 막을 수 있습니다. 게임 사이트, SNS, 성인 사이트 등을 차단하여 업무나 학습에 집중하게 합니다.
반대로 허용 목록을 만들어 특정 사이트만 접속 가능하게 할 수도 있습니다. 두 번째 역할은 익명성 확보입니다.
외부 서버에서 보기에 요청자는 프록시 서버입니다. 실제 클라이언트의 IP 주소는 드러나지 않습니다.
VPN도 비슷한 원리로 작동합니다. 해외 서비스에서 국가 제한을 우회하는 데 사용되기도 합니다.
세 번째 역할은 캐싱입니다. 자주 요청되는 콘텐츠를 프록시 서버에 저장해둡니다.
다른 사용자가 같은 콘텐츠를 요청하면 인터넷까지 가지 않고 프록시에서 바로 응답합니다. 대역폭을 절약하고 응답 속도도 빨라집니다.
위 코드를 보면, ForwardProxy 클래스가 세 가지 기능을 모두 수행합니다. 먼저 차단 목록을 확인하고, 캐시에 있는지 확인한 후, 없으면 인터넷에서 가져옵니다.
클라이언트 IP는 외부로 전달되지 않습니다. 기업 환경에서는 Squid, BlueCoat 같은 엔터프라이즈 프록시를 사용합니다.
개인적으로는 브라우저 설정에서 프록시 서버를 지정하거나, 시스템 전체에 프록시를 설정할 수 있습니다. 주의할 점이 있습니다.
프록시를 거치면 모든 트래픽이 프록시 서버를 통과합니다. 신뢰할 수 없는 프록시를 사용하면 개인정보가 유출될 수 있습니다.
무료 프록시 서비스는 특히 조심해야 합니다. 김개발 씨는 이제 회사 프록시가 왜 필요한지 이해했습니다.
불편하기도 하지만, 보안과 효율성을 위해 필요한 장치임을 알게 되었습니다.
실전 팁
💡 - 기업 환경에서는 프록시 로그를 통해 보안 위협을 모니터링할 수 있습니다
- HTTPS 트래픽 검사를 위해서는 SSL 인터셉션 설정이 필요합니다
6. 리버스 프록시
김개발 씨가 Nginx를 설정하다가 proxy_pass 설정을 발견했습니다. "이게 프록시인 건 알겠는데, 포워드 프록시랑 뭐가 다른 거죠?" 박시니어 씨가 설명합니다.
"방향이 반대예요. 리버스 프록시는 서버 앞에 서는 거예요."
**리버스 프록시(Reverse Proxy)**는 서버와 인터넷 사이에 위치하여 서버를 대신해 요청을 받는 중간 서버입니다. 포워드 프록시가 클라이언트를 숨긴다면, 리버스 프록시는 서버를 숨깁니다.
로드 밸런싱, SSL 종료, 캐싱, 보안 강화 등 다양한 역할을 수행합니다.
다음 코드를 살펴봅시다.
// Nginx 리버스 프록시 설정 예시 (nginx.conf)
// server {
// listen 80;
// server_name example.com;
//
// location /api {
// proxy_pass http://backend-api:3000;
// proxy_set_header Host $host;
// proxy_set_header X-Real-IP $remote_addr;
// }
//
// location /static {
// proxy_pass http://cdn-server;
// proxy_cache my_cache;
// proxy_cache_valid 200 1d;
// }
// }
// Node.js로 리버스 프록시 구현
const http = require('http');
const httpProxy = require('http-proxy');
const proxy = httpProxy.createProxyServer({});
http.createServer((req, res) => {
const target = req.url.startsWith('/api')
? 'http://api-server:3000'
: 'http://web-server:8080';
proxy.web(req, res, { target });
}).listen(80);
김개발 씨가 서비스 아키텍처를 보니, 사용자 요청이 직접 애플리케이션 서버로 가지 않고 Nginx를 먼저 거칩니다. 이 Nginx가 바로 리버스 프록시입니다.
리버스 프록시와 포워드 프록시는 방향이 다릅니다. 포워드 프록시가 클라이언트의 비서라면, 리버스 프록시는 서버의 비서입니다.
클라이언트는 리버스 프록시와 대화하고, 실제 서버의 존재는 모릅니다. 왜 서버 앞에 리버스 프록시를 두는 걸까요?
첫 번째 이유는 보안입니다. 실제 서버의 IP 주소와 구조가 외부에 노출되지 않습니다.
공격자가 서버를 직접 공격하기 어려워집니다. DDoS 공격도 리버스 프록시에서 1차 방어할 수 있습니다.
두 번째 이유는 SSL 종료입니다. HTTPS 암호화와 복호화는 CPU를 많이 사용합니다.
이 작업을 리버스 프록시에서 처리하면 백엔드 서버는 암호화 부담 없이 본연의 업무에 집중할 수 있습니다. 세 번째 이유는 캐싱입니다.
자주 요청되는 정적 콘텐츠를 리버스 프록시에서 캐시합니다. 이미지, CSS, JavaScript 파일 등을 백엔드까지 가지 않고 바로 응답합니다.
서버 부하가 크게 줄어듭니다. 네 번째 이유는 로드 밸런싱입니다.
앞서 배운 로드 밸런싱을 리버스 프록시에서 수행합니다. Nginx, HAProxy 같은 소프트웨어가 리버스 프록시이자 로드 밸런서로 동작합니다.
위 코드에서 Nginx 설정을 보면, /api 경로는 백엔드 API 서버로, /static 경로는 CDN 서버로 전달합니다. 또한 X-Real-IP 헤더를 설정하여 원래 클라이언트 IP를 백엔드에 전달합니다.
리버스 프록시를 거치면 클라이언트 IP가 프록시 IP로 바뀌기 때문입니다. 실무에서 Nginx는 가장 많이 사용되는 리버스 프록시입니다.
가볍고 빠르며 설정이 간단합니다. 대규모 서비스에서는 AWS CloudFront, Cloudflare 같은 CDN이 리버스 프록시 역할을 하기도 합니다.
김개발 씨는 이제 포워드 프록시와 리버스 프록시의 차이를 명확히 알게 되었습니다. "클라이언트 앞에 있으면 포워드, 서버 앞에 있으면 리버스!" 간단한 구분법이지만 핵심을 찌릅니다.
실전 팁
💡 - 리버스 프록시 설정 시 X-Forwarded-For 헤더를 올바르게 전달하여 실제 클라이언트 IP를 보존하세요
- 캐시 무효화 전략을 미리 수립하여 콘텐츠 업데이트 시 문제가 없도록 하세요
7. 고가용성 구성 사례
김개발 씨가 드디어 프로덕션 환경을 구축합니다. "지금까지 배운 가용성, 이중화, 로드 밸런싱, 프록시를 어떻게 조합해야 할까요?" 박시니어 씨가 화이트보드에 아키텍처를 그리기 시작합니다.
실제 고가용성 시스템은 이렇게 구성됩니다.
고가용성(HA, High Availability) 구성은 앞서 배운 모든 기술을 조합하여 장애에 강한 시스템을 만드는 것입니다. 로드 밸런서 이중화, 서버 클러스터링, 데이터베이스 레플리케이션, 모니터링과 자동 복구까지 포함합니다.
실제 운영 환경에서 99.99% 가용성을 달성하기 위한 종합 설계입니다.
다음 코드를 살펴봅시다.
// 고가용성 아키텍처 구성 예시 (Infrastructure as Code 스타일)
const haArchitecture = {
// 로드 밸런서 이중화
loadBalancers: {
primary: { ip: '10.0.1.10', status: 'active' },
secondary: { ip: '10.0.1.11', status: 'standby' },
virtualIP: '10.0.1.1', // 부동 IP (Floating IP)
healthCheck: { interval: 5000, timeout: 3000 }
},
// 애플리케이션 서버 클러스터
appServers: [
{ id: 'app-1', zone: 'az-1', ip: '10.0.2.10' },
{ id: 'app-2', zone: 'az-1', ip: '10.0.2.11' },
{ id: 'app-3', zone: 'az-2', ip: '10.0.3.10' },
{ id: 'app-4', zone: 'az-2', ip: '10.0.3.11' }
],
// 데이터베이스 이중화
database: {
primary: { host: 'db-primary', zone: 'az-1' },
replica: { host: 'db-replica', zone: 'az-2' },
failover: 'automatic'
}
};
김개발 씨가 화이트보드 앞에 섰습니다. 박시니어 씨가 그려준 고가용성 아키텍처를 이해하려고 노력합니다.
"왜 이렇게 복잡한 거죠?" "단일 장애점을 모두 제거하기 위해서예요." 박시니어 씨가 대답합니다. "어느 한 곳이 죽어도 서비스가 계속 돌아가야 하니까요." 먼저 로드 밸런서 이중화입니다.
로드 밸런서가 하나뿐이면, 그것이 죽으면 끝입니다. 그래서 Active-Standby로 두 대를 준비합니다.
**부동 IP(Floating IP)**를 사용하여, 주 로드 밸런서가 죽으면 보조가 같은 IP를 이어받습니다. 클라이언트는 변화를 느끼지 못합니다.
다음은 다중 가용 영역(Multi-AZ) 배치입니다. AWS에서 가용 영역(AZ)은 물리적으로 분리된 데이터센터입니다.
서버를 여러 AZ에 분산 배치하면, 한 데이터센터에 화재가 나거나 정전이 되어도 다른 데이터센터가 서비스를 유지합니다. 위 코드에서 appServers를 보면, app-1과 app-2는 az-1에, app-3과 app-4는 az-2에 있습니다.
az-1 전체가 다운되어도 az-2의 서버들이 요청을 처리합니다. 데이터베이스 이중화도 중요합니다.
Primary-Replica 구조에서 Primary가 쓰기를 담당하고, Replica가 읽기를 분산 처리합니다. Primary가 죽으면 Replica가 새로운 Primary로 승격됩니다.
이를 **페일오버(Failover)**라고 합니다. 자동 페일오버를 위해서는 모니터링과 오케스트레이션이 필요합니다.
각 구성요소의 상태를 실시간으로 체크하고, 문제가 감지되면 자동으로 대응합니다. Kubernetes, AWS Auto Scaling 같은 도구가 이 역할을 합니다.
세션 관리도 고려해야 합니다. 서버가 여러 대면 사용자 세션을 어디에 저장할까요?
Redis 같은 외부 세션 스토어를 사용하거나, JWT처럼 무상태(Stateless) 인증을 채택합니다. 그래야 어느 서버에 연결되어도 동일한 경험을 제공합니다.
마지막으로 정기 점검과 카오스 엔지니어링입니다. 시스템이 정말 장애에 강한지 테스트해야 합니다.
Netflix의 Chaos Monkey처럼 일부러 서버를 죽여보며 복구가 잘 되는지 확인합니다. 예상치 못한 장애에도 대응할 수 있는 자신감이 생깁니다.
김개발 씨는 아키텍처를 그리고 나서 감탄했습니다. "이래서 대형 서비스가 안 죽는 거군요!" 물론 비용도 그만큼 듭니다.
서비스 규모와 중요도에 맞게 적절한 수준의 고가용성을 설계하는 것이 핵심입니다.
실전 팁
💡 - 고가용성 구성 후 반드시 장애 시뮬레이션을 수행하여 페일오버가 정상 작동하는지 검증하세요
- 비용과 가용성은 트레이드오프 관계이므로, 비즈니스 요구사항에 맞는 적정선을 찾으세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
서비스 메시 완벽 가이드
마이크로서비스 간 통신을 안전하고 효율적으로 관리하는 서비스 메시의 핵심 개념부터 실전 도입까지, 초급 개발자를 위한 완벽한 입문서입니다. Istio와 Linkerd 비교, 사이드카 패턴, 실무 적용 노하우를 담았습니다.
EFK 스택 로깅 완벽 가이드
마이크로서비스 환경에서 로그를 효과적으로 수집하고 분석하는 EFK 스택(Elasticsearch, Fluentd, Kibana)의 핵심 개념과 실전 활용법을 초급 개발자도 쉽게 이해할 수 있도록 정리한 가이드입니다.
Grafana 대시보드 완벽 가이드
실시간 모니터링의 핵심, Grafana 대시보드를 처음부터 끝까지 배워봅니다. Prometheus 연동부터 알람 설정까지, 초급 개발자도 쉽게 따라할 수 있는 실전 가이드입니다.
분산 추적 완벽 가이드
마이크로서비스 환경에서 요청의 전체 흐름을 추적하는 분산 추적 시스템의 핵심 개념을 배웁니다. Trace, Span, Trace ID 전파, 샘플링 전략까지 실무에 필요한 모든 것을 다룹니다.
CloudFront CDN 완벽 가이드
AWS CloudFront를 활용한 콘텐츠 배포 최적화 방법을 실무 관점에서 다룹니다. 배포 생성부터 캐시 설정, HTTPS 적용까지 단계별로 알아봅니다.