개발 etc

백엔드 아키텍처 설계 기초

묠니르묘묘 2023. 6. 19. 16:54

 

백엔드 개발자로서 서버 개발을 먼저 학습했지만, 정작 아키텍처 설계를 어떻게 해야하는가에 대한 고민을 많이 하지 않았다. 당연하게  [클라이언트]-[서버]-[데이터베이스] 구조로만 생각했었다. 지금은 MSA와 여러 아키텍처에 대한 학습을 하다보니 어떤 식으로 설계를 해야하는가에 대한 고민이 생겼다.

 

  • 메시지 큐(message queue)는 어느 환경에서 사용해야할까?
  • 트래픽이 증가하면 단일 서버가 장애나지 않을까?
  • 현재 프로젝트를 멀티 서버로 했을 때의 문제점은?
  • DB가 하나일 때 장애가 난다면 서비스를 빠르게 복구하기 힘들지 않은가?
  • DB보다 빠른 캐시 서버의 도입은?
  • MSA에서 각 서비스마다의 통신은 어떻게?
  • 채팅 서비스를 만든다고 했을 때의 아키텍처 설계는 어떻게?

 

위와 같은 여러 의문점들이 많은데 그에 따른 정형화된 패턴이 없다. 왜냐하면 사용자 수, 트래픽, 비용 등 여러 변수들로 각각의 상황마다 전부 다른 아키텍처 설계를 적절히 해야하기 때문이다. 현재 상황보다 이상적인 아키텍처 설계를 한다면 오버 엔지니어링 문제로 비용이 상당히 커질 수도 있다. 그렇다면 어떻게 유연하고 가용성있는 아키텍처 구조를 설계할 수 있을까?

 

가장 단순한 단일 서버에서부터 생각해보자

 

🚀 단일 서버

  • 웹, DB, 캐시 등 모든 것이 서버 한 대에서 실행되는 간단한 구조

단일 서버 아키텍처 구조

  1. 사용자는 웹 브라우저에 URL 입력
  2. URL은 DNS(Domain Name Service)에서 IP 주소로 변환되어 반환
  3. 반환된 IP 주소로 HTTP 요청
  4. 요청 받은 웹 서버는 HTML 또는 JSON 형태의 응답을 반환

 

사용자가 늘어난다면 서버를 여러대 두어야 하나요?

 

 🚀 데이터베이스 분리

  • 웹/모바일 트래픽 처리 서버(웹 계층)와 데이터베이스 서버(데이터 계층)를 분리시킨 구조
  • 용도에 따른 분리로 각각 독립적으로 확장 가능

웹 계층과 데이터 계층 분리 구조

  • 웹 브라우저는 www.naver.com을 요청하여 웹 서버에서 HTML을 반환받음
  • 모바일 앱은 api.naver.com을 요청하여 웹 서버를 거쳐서 데이터베이스에서 데이터를 반환 받음
  • 단순 사용자 증가라면 정적 콘텐츠 반환 트래픽이 증가하니 웹 서버를 증가
  • 사용자가 데이터를 많이 사용한다면 데이터베이스 서버를 증가

 

서버를 증가시키는 방법만 있을까? NO

 

✅ 수직적 규모 확장(scale up)과 수평적 규모 확장(scale out)

  • 수직적 규모 확장
    • 서버의 사양(CPU, RAM 등)을 고사양으로 추가하는 행위
  • 수평적 규모 확장
    • 서버를 추가해서 트래픽을 분산시켜 성능 개선하는 행위

 

위와 같은 방식으로 웹 서버나 데이터베이스 서버의 성능을 개선할 수 있다.

하지만 수직적 규모 확장의 경우 아래와 같은 단점이 있다.

  • 확장의 한계로, 고사양 자원을 무한대로 증설할 방법 X
  • 장애 대응 X, 자동복구나 다중화 방안이 없어서 장애 발생 시 완전 중단

위와 같은 단점으로 대규모 트래픽 서비스같은 경우 수평적 규모 확장법을 사용한다.

 

Scale Out을 한다면 어떻게 요청을 분산시키나요?

 

🚀 로드 밸런서

  • 로드밸런서는 부하 분산 집합(Load Balancing Set)에 속한 웹 서버들에게 트래픽 부하를 고르게 분산시킴
  • 수평적 규모 확장으로 웹 서버 증설 후, 로드밸런서로 트래픽 부하를 분산시키는 구조
    • 하나의 웹 서버에 많은 사용자가 몰릴 때의 문제점을 해결

로드 밸런서 추가

  • 클라이언트는 공개 IP 주소(Public IP Address)로 접속하고, 로드밸런서는 적절히 사설 IP 주소(Private IP Address)를 이용하여 요청 처리함
    • 클라이언트는 사설 IP 주소를 모르기에 보안적인 측면에서도 좋음
    • 또한 사설 IP 주소는 인터넷을 통해 접속 X
  • 서버 1이 장애 시, 모든 트래픽은 서버 2로 처리
  • 트래픽 증가를 처리하려면 웹 서버를 추가하기만 하면 되며, 나머지는 로드밸런서가 처리해줌

 

웹 계층은 트래픽 처리가 되지만 데이터베이스는 어떡하나요?

 

🚀 데이터베이스 다중화

  • 데이터 계층에서 DB 장애 및 부하 문제를 데이터베이스 다중화를 통해 해결할 수 있음
  • 데이터베이스 다중화는 서버 사이에 주(Master)-부(Slave) 관계를 설정하여 데이터 원본은 주 서버, 사본은 부 서버에 저장하는 방식
  • 주 서버(Master)
    • 쓰기 연산(Write Operation)
    • 데이터 원본
  • 부 서버(Slave)
    • 읽기 연산(Read Operation)
    • 데이터 사본
  • 대부분 애플리케이션의 경우에 읽기 연산 비중이 훨씬 높기에 부 서버가 많음
  • 부 서버가 전부 장애 발생 시, 주 서버가 읽기 연산을 처리함
  • 주 서버가 장애 발생 시, 부 서버 중 하나가 새로운 주 서버가 됨
    • 부 서버의 데이터가 최신 상태가 아닐 가능성이 있음
    • 최신 상태가 아니거나 없는 데이터가 있을 시, 복구 스크립트로 추가해야 함
    • 이런 문제를 해결하려면 다중 마스터(Multi-Masters), 원형 다중화(Circular Replication) 방식을 생각할 수 있음

데이터베이스 다중화 구조

  • 성능
    • 데이터 변경 연산은 Master 에만 전달하고, 읽기 연산은 Slave 들로 분산하여 병렬로 처리될 수 있는 질의(Query)의 수가 늘어나므로 성능이 좋아짐
  • 안정성(Reliability)
    • 서버 중 하나가 파괴 및 장애가 나도 데이터 보존 가능
    • 데이터를 지역적으로 떨어진 여러 장소에 다중화 가능하기 때문
  •  가용성(Availability)
    • 데이터를 여러 지역에 복제함으로써, 하나의 DB에 장애 발생하더라도 다른 서버의 데이터를 가져와서 계속 서비스 할 수 있음

 

 

로드밸런서와 데이터베이스 다중화를 고려한 구조는 어떻게 생겼나요?

 

🚀 로드밸런서와 데이터베이스 다중화를 고려한 설계

로드밸런서와 데이터베이스 다중화 아키텍처 구조

  1. 사용자는 DNS로부터 로드밸런서의 공개 IP 주소 받음
  2. 사용자는 해당 IP 주소를 사용하여 로드밸런서 접속
  3. HTTP 요청은 서버 1 or 서버 2로 전달
  4. 웹 서버는 사용자의 데이터를 Slave DB에서 읽고, 데이터 변경 연산은 Master DB로 전달

 

🚀 마무리

지금까지 가장 기본적으로 서버를 유연하고 확장시킬 수 있는 아키텍처 구조를 살펴보았다.

  • 웹 계층과 데이터 계층 분리
  • 각 계층마다 수평적 규모 확장(Scale Out)
  • Scale Out으로 추가된 웹 서버들은 로드밸런서로 트래픽 분산
  • 데이터베이스 다중화로 부하 분산

이러한 구조를 만들려면 클라우드 서비스를 이용하는 것이 가장 좋다.

현재 AWS가 가장 인기있고 점유율이 높다.

 

현재 아키텍처 구조가 가장 이상적인 설계안일까요? NO
응답시간을 개선할 수 있어요!

 

응답시간을 개선하기 위한 방법은 다음 게시글을 통해 알아보자.


가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 알렉스 쉬