요즘 백엔드 업무도 같이 하고있는데요!! (인수인계가.. 없었음.. 맨땅에 해딩 중..)
AWS 인프라 구조 파악을 하다가 서버 2개가 동시에 돌아가고 있더라구요
이게 로드밸런싱인지, 아니면 웹서버/앱서버 분리 구조인지, 혹은 백업 서버인지 모르겠어서,
실제 AWS 환경에서 이를 구분하는 방법을 단계별로 알아보겠습니다
메인 서버가 2개?!
CloudWatch 모니터링을 보니 메인 서버 두개가 모두 활발하게 트래픽을 처리하고 있었습니다.
이때 가능한 시나리오는 다음과 같습니다.
1. 로드밸런싱
- 두 서버가 동일한 역할을 하며 트래픽을 나눠서 처리
- 성능 향상과 가용성 확보가 목적
2. 웹서버 + 앱서버 분리
- 웹서버: 정적 파일 서빙, 프록시 역할
- 앱서버: 비즈니스 로직 처리, DB 연동
3. 백업 서버 (Standby)
- 평상시에는 메인 서버만 동작
- 장애 시에만 백업 서버가 활성화
모니터링으로 추론하기
먼저 모니터링에 나오는 각 징후들을 보고 추론해볼까요?
로드밸런싱의 징후
서버1: CPU 60%, 메모리 70%, 초당 요청 100개
서버2: CPU 55%, 메모리 65%, 초당 요청 95개
→ 두 서버가 비슷한 수준으로 일하고 있음
웹서버/앱서버 분리 구조의 징후
웹서버: CPU 30%, 메모리 40%, 네트워크 IN 높음, 초당 요청 300개
앱서버: CPU 80%, 메모리 85%, 네트워크 OUT 높음(DB통신), 초당 요청 100개
→ 역할이 다르니까 사용 패턴도 다름
- 웹서버: 많은 요청을 받지만 CPU 사용률은 낮음 (정적 파일, 프록시)
- 앱서버: 적은 요청이지만 CPU 사용률 높음 (복잡한 비즈니스 로직)
- 네트워크 패턴이 다름: 웹서버는 인바운드 위주, 앱서버는 아웃바운드 위주
백업 서버의 징후
본서버: CPU 80%, 메모리 90%, 초당 요청 300개
백업서버: CPU 5%, 메모리 20%, 초당 요청 0개
→ 백업 서버는 대기 상태
저희 회사의 경우에는 두 서버 모두 활발하게 트래픽을 처리하고 있어서 로드밸런싱일 가능성이 높다고 판단했지만, 웹/앱 서버 분리 구조일 가능성도 없진 않으니! 확실하게 확인해봅시다!!!
AWS 콘솔에서 확실하게 확인하기
1. EC2 인스턴스 기본 정보 확인
AWS 콘솔 → EC2 → 인스턴스
우선 아래 항목을 확인합니다
- 인스턴스 이름/태그
- 인스턴스 ID
- 인스턴스 타입
- 프라이빗 IP vs 퍼블릭 IP
- 서브넷 정보
(인스턴스 ID를 기억해주세요!!)
2. 보안 그룹 분석
인스턴스 선택 → 보안 탭
그 후 보안그룹을 확인해봤는데요! 저희 회사는 아래와 같은 특징을 가지고 있었습니다.
- 두 서버 모두 포트 3000 TCP 허용
- 동일한 보안 그룹 사용
- 거의 동일한 인바운드/아웃바운드 규칙
다 동일한거보니 같은 역할을 하는 서버들인 것 같죠?! (로드밸런싱일 확률이 높아진다!!)
이제 로드 밸런서가 있는지 확인해봅시다
3. 로드밸런서 존재 여부 확인
EC2 → 로드 밸런싱 → 로드 밸런서
![]() |
![]() |
일단 존재한다고 치고, A라는 로드밸런서가 있다고 예를 들어볼게요!
그럼 두개의 본 서버가 이 로드밸런서에 묶여있는걸 어떻게 알 수 있을까요??
로드 밸런싱 -> 대상 그룹
로드 밸런싱 아래에 있는 대상 그룹을 눌러줍니다.
대상 그룹에서 로드 밸런서 카테고리를 확인하면 아까봤던 로드밸런스인 A가 있는 것을 볼 수 있습니다.
선택 후, 대상을 누르면 등록된 대상이 나옵니다! 이 목록에서 1번에서 확인했던 본 서버의 인스턴스 ID가 동일한지 확인하면 됩니다!
저희는 동일하더라구요!! 그래서 로드밸런싱 구조로 확정을 했습니다!
최종 아키텍처 파악
실제 구조
사용자(iOS 앱)
↓
Application Load Balancer (ALB)
↓
서버1 + 서버2 (동일한 역할, 트래픽 분산)
실제로는 모놀리식 아키텍처로, 각 서버가 웹 요청 처리부터 비즈니스 로직, DB 연동까지 모든 역할을 담당하고 있었습니다.
모놀리식 아키텍처??? ALB???
모놀리식 아키텍처란?
모든 기능이 하나의 서버/애플리케이션에 다 들어있는 구조를 말 합니다.
하나의 서버에서 아래의 기능을 다 처리해요!
- 웹 요청 처리
- 비즈니스 로직
- 데이터베이스 연결
- 파일 업로드
- 인증/로그인
- 결제 처리
- 이메일 발송
이외에도 마이크로 서비스도 있는데, 마이크로 서비스는 분리된 구조로 기능별로 서버를 나눠서 운영합니다.
아래에서 좀 더 쉽게 이해해봅시다.
실제 구조 비교
모놀리식
iOS 앱 → ALB → 서버1 (모든 기능) + 서버2 (모든 기능)
각 서버가 API부터 DB 연결까지 모든 걸 다 합니다.
마이크로서비스 (분리된 구조)
iOS 앱 → API Gateway →
├─ 사용자 서비스
├─ 주문 서비스
├─ 결제 서비스
└─ 알림 서비스
기능별로 서버를 나눠서 운영합니다.
이렇게 시각적으로 보니까 좀 더 이해가 가죠?! iOS쪽에서는 어떻게 처리할지도 알아볼까요?
iOS 개발자 관점에서
모놀리식에서 API 호출
// 모든 API가 같은 서버
let baseURL = "https://api.yourservice.com"
let userAPI = "\(baseURL)/users" // 사용자 정보
let orderAPI = "\(baseURL)/orders" // 주문 정보
let paymentAPI = "\(baseURL)/payment" // 결제 처리
마이크로서비스에서 API 호출
// 서비스별로 다른 서버
let userAPI = "https://user-service.com/users"
let orderAPI = "https://order-service.com/orders"
let paymentAPI = "https://payment-service.com/payment"
이제 장단점과 언제 모놀리식을 사용하는지 알아봅시다!
장단점
구조 | 장점 | 단점 |
모놀리식 |
|
|
마이크로 서비스 |
|
|
그러면 각자 언제 사용할까?
구조 | 적합한 경우 | 분리를 고려할 때 |
모놀리식 |
|
|
마이크로 서비스 |
|
|
중소규모 서비스인 저희 회사에는 모놀리식 서비스가 안정성과 단순함을 동시에 확보한 합리적이고 적합한 방식인 것 같네요!
ALB 란?
Application Load Balancer는 이름 그대로 애플리케이션 계층에서 동작하는 로드밸런스 입니다.
왜 ALB를 쓸까요?
일반적인 로드밸런서는 그냥 "요청 왔네? 서버1으로 보내자, 다음 요청은 서버2로!" 이런 식이라면, ALB는 요청 내용을 보고 판단해요.
/api/users → API 서버로
/static/images → 정적 파일 서버로
/admin → 관리자 서버로
이런 식으로 경로별로 다른 서버로 보낼 수 있어요!
지금은 모놀리식이라 같은 서버들이지만, 나중에 서비스가 커지면 이런 식으로 확장할 수 있습니다.
ALB의 특별한 기능들
- HTTPS 처리: SSL 인증서를 ALB에서 관리하니까 서버는 HTTP만 신경쓰면 됨
- Health Check: 단순히 "살아있나?" 가 아니라 "제대로 응답하나?" 까지 체크
- Sticky Session: 필요하면 같은 사용자를 계속 같은 서버로 보낼 수도 있음
다른 로드밸런서 타입들
- Network Load Balancer (NLB): TCP/UDP 초고성능용, 게임서버/실시간 통신
- Classic Load Balancer (CLB): 구세대, 레거시 시스템용
저희 서비스에서는
- iOS 앱에서 주로 HTTP/HTTPS API 호출을 한다
- URL 경로별 라우팅이 필요할 수 있다 (/api/v1, /api/v2)
- SSL 인증서 관리를 ALB에서 처리하면 서버 부하가 줄어든다
이러한 이유로인해 ALB가 제일 적절한 선택같네요! (아..마요.. 공부하다가 아닌 것 같으면 다시 수정하러 올게요!)
지금은 단순하게 트래픽만 분산하고 있지만, 나중에 큰 서비스를 다루게된다면 다른 로드밸런서 타입들도 사용해볼 수 있겠져..?
운영하면서 주의해야 할 것들
로드밸런싱 환경에서 주의할 점들이 있는데, 그 내용을 간단히 정리해봤습니다!
세션 관리
로드밸런서가 있으면 사용자 요청이 서버1에 갔다가 다음 요청은 서버2로 갈 수 있어요. 그런데 세션 정보를 서버 메모리에 저장하면?
1. 사용자가 로그인 → 서버1에 세션 저장
2. 다음 API 요청 → 서버2로 이동
3. 서버2에는 세션 정보 없음 → 로그인 안된 것으로 인식!
문제가 될 수 있는 코드
app.use(session({
store: new MemoryStore(),
}));
이렇게 하면 메모리에 세션 저장하는데 서버별로 세션이 다르기때문에 정보를 가져올 수 없습니다.
그렇다면 어떻게 해야할까요?!
// 1. Redis로 세션 공유 (추천!)
app.use(session({
store: new RedisStore({
host: 'elasticache-cluster.xxx.amazonaws.com',
port: 6379
})
}));
// 2. JWT 토큰 사용 (Stateless)
// 토큰에 모든 정보를 담아서 서버에 저장하지 않음
const token = jwt.sign({ userId: user.id }, 'secret');
Redis를 사용하면 되는데요!
이렇게 하면 모든 서버가 같은 Redis에 접속해서 세션 정보를 공유하기때문에 어느 서버로 요청이 가도 로그인 상태를 유지할 수 있습니다ㅎㅎ
iOS 개발자가 고려해야 할 점들
iOS앱에서도 신경써야 할 부분들이 있겠죠?
재시도 로직 구현
다른 환경에서도 재시도 로직은 구현해야하지만 로드밸런서 환경에서는 서버가 여러대라서 서버 중 하나가 일시적으로 문제가 생길 수 있는 확률도 있기때문에 더!! 중요합니다!!!
// URLSession 기본 설정
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 30
config.waitsForConnectivity = true // 네트워크 연결 기다림
// 서버 에러 시 재시도 로직
func apiRequest(retryCount: Int = 3) {
// 502(Bad Gateway), 503(Service Unavailable), 504(Gateway Timeout)
// 이런 에러들은 일시적인 서버 문제일 수 있어서 재시도해볼 만해요
if let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode >= 502 && httpResponse.statusCode <= 504,
retryCount > 0 {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.apiRequest(retryCount: retryCount - 1)
}
}
}
중복 요청 방지
결제 버튼을 연타하거나 네트워크 오류로 재시도할 때 같은 결제가 여러 번 처리되는 걸 방지해야 하는데요!
단일 서버일 때는 서버 메모리에 "이 요청 처리 중이야" 라고 기록해둘 수 있지만
로드밸런서 환경일 때는 재시도 요청이 다른 서버로 가면 그 서버는 "어? 이 요청 처음 보는데?" 하고 또 처리해버릴 수 있기때문입니다!
// POST 요청할 때만 Idempotency Key 추가
func makePayment(amount: Int) {
var request = URLRequest(url: paymentURL)
request.httpMethod = "POST"
// 고유한 키를 헤더에 추가 - 서버가 중복 요청인지 판단
request.setValue(UUID().uuidString, forHTTPHeaderField: "Idempotency-Key")
URLSession.shared.dataTask(with: request) { data, response, error in
// 응답 처리
}.resume()
}
그래서 로드밸런서 환경에서는 Idempotency Key로 서버끼리 "아, 이 요청 이미 처리했구나" 하고 알 수 있게 해주는 게 정말 중요합니다!
꼭 봐야 할 모니터링 지표들
ALB 관련:
- TargetResponseTime: 각 서버 응답 시간이 비슷한가?
- HealthyHostCount: 정상 서버가 몇 개인가? (2개 모두 정상이어야!)
- RequestCount: 요청이 두 서버에 골고루 분산되는가?
서버별로 확인할 것들:
- CPU/메모리 사용률: 한쪽 서버만 과부하 걸리진 않는가?
- 에러 발생 패턴: 특정 서버에서만 에러가 많이 나는가?
- Connection Pool: DB 연결이 제대로 관리되고 있는가?
이런 지표들을 보면서 "어? 서버1은 괜찮은데 서버2만 CPU 100%네?" 이런 걸 미리 발견할 수 있습니다!
마무리하며..
처음에는 "서버가 2개 돌아가는데 이게 뭐지?"라는 단순한 의문에서 시작했지만, 체계적으로 AWS 콘솔을 확인해보니 잘 구성된 로드밸런싱 환경임을 확인할 수 있었습니다!
핵심 포인트
- 모니터링 패턴으로 추론 → 보안 그룹으로 검증 → 로드밸런서로 확정
- ALB를 통한 효율적인 트래픽 분산
- 고가용성과 성능을 동시에 확보한 안정적인 구조
이런 식으로 단계적으로 접근하면 복잡해 보이는 AWS 인프라도 명확하게 이해할 수 있을 것 같습니다!!
무엇보다 "왜?"라는 질문을 계속 던지며 근거를 찾아가는 과정이 중요하다는 것을 배웠네요!
아주 기본적인 글이지만 이 글이 AWS 인프라 구조를 파악하는 데 도움이 되셨기를 바랍니다. 궁금한 점이 있으시면 언제든 댓글로 남겨주세요! 😊