사용자 수에 따른 규모 확장성

나무나무·2025년 9월 23일
post-thumbnail

이 글은 "가상 면접 사례로 배우는 대규모 시스템 설계 기초" 를 읽고 정리한 글입니다.
https://product.kyobobook.co.kr/detail/S000001033116


| 서버

웹 애플리케이션

  • 비즈니스 로직 + 데이터 처리 등을 위한 서버 구현용 언어 사용(Java, Python)
  • 프레젠테이션 용으로 클라이언트 구현용 언어(HTML, JavaScript) 사용

모바일 앱

  • 모바일 앱 ↔ 웹 서버
    • HTTP 프로토콜 이용 → 반환 응답 데이터는 JSON 형태


| 데이터베이스

  • 웹 계층(웹/모바일 트래픽 처리)
  • 데이터 계층(데이터베이스 서버)

어떤 데이터 베이스 사용?

⇒ 관계형 데이터베이스

  • MySQL, Oracle, PostgreSQL
  • 자료를 테이블, 열, 칼럼으로 표현
  • 테이블 관계 JOIN가능

⇒ 비-관계형 데이터베이스(NoSQL)

  • CouchDB, Neo4j, Cassandra, Amazon DynamoDB
  • 일반적으로 JOIN 연산은 지원 x

분류

  • Key-value 저장소
  • 그래프 저장소
  • 칼럼 저장소
  • 문서 저장소

💡 아래의 경우 비-관계형 데이터베이스가 더 좋음

  • 응답 지연 시간이 낮아야할 때
  • 데이터가 비정형인 경우
  • 데이터를 직렬화 하거나 역직렬화할 수 있기만 하면 됨
  • 아주 많은 양의 데이터를 저장해야 함

💡데이터 직렬화
- 객체, 자료구조, 메모리에 있는 데이터를 하나의 바이트 스트림(문자열, JSON, BSON 등)으로 변환하는 과정
- ex) 자바 객체 → JSON 문자열

💡데이터 역직렬화
- 직렬화된 데이터를 다시 원래의 객체나 자료구조 형태로 복원
- ex) JSON 문자열 → 자바 객체



| 수직적 규모 확장 vs 수평적 규모 확장

수직적 규모 확장

  • 서버에 고사양 자원(CPU, 더 많은 RAM)을 추가
  • 서버에 들어오는 트래픽이 적을 때 좋은 선택

단점

  • 한 대의 서버에 CPU나 메모리를 무한대로 증설할 수는 없음
  • 장애 자동 복구나 다중화 방안을 제시하지 않음 → 서버 장애 시 웹/앱은 완전히 중단됨

수평적 규모 확장

  • 더 많은 서버를 추가하여 성능 개선
  • 대규모 애플리케이션 지원에 적절
  • 대규모 사용자접속 → 부하 분산기, 로드 밸런서 도입이 최선

로드 밸런서

  • 부하 분산 집합에 속한 웹 서버들에게 트래픽 부하를 고르게 분산하는 역할
  • 사용자가 로드밸런서의 공개 IP로 접속 → 웹 서버는 클라이언트 접속을 직접 처리하지 않음
  • 서버간 통신에는 private IP 주소(같은 네트워크 내에 속한 서버 사이 통신에만 사용할 수 있는 IP 주소) 사용, 인터넷 접속 불가
  • 웹 계층 가용성 향상

데이터베이스 다중화

  • master-slave 구조
    • MasterDB - 쓰기 연산만 지원 (insert, delete, update 등)
    • SlaveDB - 읽기 연산만 지원
  • 대부분의 DB는 쓰기 연산보다 읽기 연산이 더 많음 → 일반적으로 SlaveDB가 MasterDB보다 수가 더 많음
  • 성능 향상 / 안정성 - 서버 일부 파괴 시에도 데이터 보존 / 가용성 - 한 서버의 장애에도 서비스 지속 가능

| 캐시

  • 값 비싼 연산 결과나 자주 참조되는 데이터를 메모리 안에 두고 빨리 처리될 수 있도록 하는 저장소
  • 웹 페이지의 새로 고침 → 매 번 데이터베이스 호출이 발생 → 애플리케이션 성능은 데이터 베이스를 얼마나 자주 호출하는지에 따라 크게 좌우됨

캐시 계층

  • 데이터가 잠시 보관되는 곳 - DB 보다 훨씬 빠름
  • ex) 웹 서버 ↔ 캐시 ↔ 데이터베이스
    • 요청 받은 웹 서버가 캐시에 응답을 찾음 → 저장되어 있으면 그대로 반환
    • 없으면 DB에 가서 응답을 찾아서 반환
      ⇒ 읽기 주도형 캐시 전략(read-through caching strategy)
  • 캐시 데이터 종류, 크기, 액세스 패턴에 맞는 캐시 전략을 선택해 사용하면 됨

캐시 사용 시 주의할 점

  • 캐시 서버는 일반적으로 프로그래밍 언어로 API를 제공
  • 데이터 갱신이 자주 일어나지 않지만 참조가 빈번하게 일어나는 경우
  • 영속적으로 보관할 데이터는 캐시에 두지 않는 편이 나음. → 캐시는 휘발성 저장소이기 때문
  • 캐시 데이터의 만료 정책도 마련해야 함. → 너무 짧으면 성능이 떨어지고 너무 길면 원본이랑 차이 나겠지
  • 데이터 원본과 캐시 사본이 동일한지도 확인해야 함 → 여러 지역에 걸쳐 시스템을 확장할 경우 캐시와 저장소 사이 일관성 유지는 매우 어려움
  • 캐시 서버의 장애에는 어떻게 대처할건지? → 서버가 한 대 있는 경우는 단일 장애 지점(Single Point of Failure, SPOF)가 될 수 있음
  • 캐시 메모리를 얼마나 크게 잡을지? → 너무 작으면 데이터가 캐시에서 밀려날 수도 있음 → 캐시 메모리의 과할당하면 됨
    무조건적인 과할당은 운영 비용적인 문제나 캐시 만료에 있어 불필요한 오버헤드 발생 가능성이 있음
    예상되는 워크로드 + 캐시 정책 + 모니터링으로 안정적으로 커버될 정도로만 크면 됨
  • 캐시가 가득 차면 기존 캐시 데이터를 방출해야 함 → 뭘 내보낼건지?
    • LRU - 마지막으로 사용된 시점이 가장 오래된 데이터
    • LFU - 사용 빈도가 가장 낮은 데이터
    • FIFO - 가장 먼저 들어온 애 내보내기


| 컨텐츠 전송 네트워크(CDN)

  • 정적 컨텐츠 전송에 쓰이는 지리적으로 분산된 서버의 네트워크
  • 이미지, 비디오, CSS, JavaScript 파일 캐시 가능

동작 과정

  1. 사용자가 CDN이 제공하는 URL로 이미지에 접근
  2. 이미지가 CDN에 없으면 CDN이 원본 서버에 요청
  3. 원본 서버 응답의 HTTP 헤더에 TTL(만료 기한) 값이 들어 있음
  4. CDN 서버가 파일을 캐시하고 사용자에게 반환

CDN 사용 시 고려할 점

  • 비용 → CDN으로 들오가고 나가는 데이터 전송 양에 따라 요금을 냄. 자주 사용되지 않는 컨텐츠는 캐싱하지 않는 편이 비용적으로 이득
  • 적절한 만료 기간 설정
    • 너무 짧으면 자주 원본 서버에 요청해야 함
    • 너무 길면 컨텐츠 신선도 저하
  • CDN 장애 발생
    • CDN 서버 장애 발생 시 → 문제 감지 후 원본 서버로 직접 컨텐츠를 가져오도록 클라이언트 구성이 필요
  • 컨텐츠 무효화
    • CDN 사업자 제공 API를 이용한 컨텐츠 무효화
    • 새로운 버전을 서비스 하도록 오브젝트 버저닝(Object Versioning) 이용
  • 캐시 = 데이터 접근 속도를 올리기 위한 임시 저장소
  • CDN = 지리적 분산을 통해 정적 컨텐츠를 빠르게 전달하는 시스템 (결과적으로 캐시를 활용함)
    ⇒ CDN도 캐시를 사용하지만, 단순 캐시보다 범위가 넓고 지리적 분산이 있다는 점이 핵심 차이


| 무상태 웹 계층

  • 웹 계층의 수평적 확장 방법 → 더 많은 웹 서버 증설
  • 상태 정보(사용자 세션 데이터)를 웹 계층에서 제거해야 함. → 상태 정보를 관계형 DB나 NoSQl 등의 지속성 저장소에 보관하고 필요할 때 가져오는 것
    • 상태 정보가 한 서버에만 묶여 있으면 서버 증설 의미가 없음 → 한 서버에 묶여 있으면 서버를 늘려도 정보가 저장되어 있는 서버로만 접속해야 하잖아
  • 사용자의 HTTP 요청은 어떤 웹 서버로도 전송 가능하게 만들고, → 이걸 공유 저장소에서 데이터를 가져오도록 설정함
  • 세션 데이터를 noSQL이나 캐시 시스템 등으로 분리 → 트래픽 양에 따라 웹 서버를 자동으로 추가하거나 삭제

세션 = 사용자 정보 파일을 서버에서 관리
쿠키 = 클라이언트에 저장되는 Key-Value 데이터



| 데이터 센터

  • 서버, 스토리지, 네트워크 장비, 보안 시스템 등
  • IT 시스템을 집중적으로 배치하고 운영하는 시설

지리적 라우팅

  • 장애가 없는 상황에서 가장 가까운 데이터 센터로 안내됨
  • geoDNS - 사용자 위치에 따라 도메인명을 어떤 IP로 변환할지 결정하도록 돕는 DNS
  • 데이터 센터 장애 발생 시 → 장애가 없는 다른 데이터 센터로 전송

다중 데이터 센터 아키텍처

  • 트래픽 우회
    • 올바른 데이터 센터로 트래픽을 전송하는 효과적인 방법을 찾아야 함
    • geoDNS는 사용자의 가장 가까운 데이터 센터로 트래픽을 보낼 수 있도록 함
  • 데이터 동기화
    • 데이터를 여러 데이터 센터에 걸쳐 다중화
  • 테스트와 배포
    • 여러 데이터센터를 사용하도록 시스템이 구성되었다면 → 여러 위치에서 테스트해 보는 것이 중요
    • 자동화 배포 도구는 모든 데이터 센터에 동일한 서비스가 설치되도록 해야함

→ 시스템의 확장을 위해서는 시스템을 컴포넌트로 분리 → 각각이 독립적으로 확장될 수 있도록 해야 함.

→ 메시지 큐는 실제 분산 시스템의 핵심 전략 중 하나



| 메시지 큐

  • 비동기 통신을 지원하는 컴포넌트
    • 메시지 무손실 - 메시지 큐에 보관된 메시지는 소비자가 꺼내기 전까지 안전함
  • 비동기적으로 전송
  • 기본 아키텍처
    • 생산자(입력 서비스) → 메시지 생성, 메시지 큐에 발행
    • 소비자(구독자) → 메시지를 받아 그에 맞는 동작을 수행
  • 서비스 또는 서버 간 결합이 느슨해짐
    • 생산자 다운 → 소비자는 메시지 수신 가능
    • 소비자 다운 → 메시지 발행 가능
  • 요청을 받는 웹서버, 받은 요청을 작업하는 작업 서버 두 개로 물리적으로 나누고, 그 사이에서 연결 역할을 함. 일종의 편지함/대기열


| 로그, 메트릭, 자동화

로그

  • 에러 로그 모니터링
  • 서버 단위 / 서비스 단위

메트릭

시스템 상태를 수치화한 데이터

  • 호스트 단위 메트릭 - CPU, 메모리, 디스크 I/O에 관한 메트릭
  • 종합 메트릭 - 데이터 베이스 계층 성능, 캐시 계층의 성능
  • 핵심 비즈니스 메트릭 - 일별 능동 사용자, 수익, 재방문 등

자동화

  • 생산성을 높이기 위한 자동화 도구 활용
  • CI 도구 → 검증 절차 자동 / 빌드, 테스트, 배포 등 절차 자동화 가능


| 데이터 베이스 규모 확장

수직적 확장(Scale-up)

  • 고성능 자원증설(CPU, RAM, 디스크 등)

약점

  • 서버 HW는 한계가 있음 → CPU, RAM의 무한 증설 x
  • SPOF로 인한 위험성 증가
  • 비용이 많이 듦

수평적 확장(Sharding)

  • 서버 증설
  • 대규모 DB를 Shard라는 작은 단위로 분할하는 기술

샤드(Shard)

  • 샤드는 같은 스키마를 사용하지만, 보관되는 데이터 사이에는 중복이 없음
    • ex) user_id 를 4로 나눈 나머지가 0이면 0번 샤드에, 1이면 1번 샤드에 …
  • 샤딩 키 전략(Sharding Key)
    • = partition key
    • 데이터 분산 전략을 정하는 하나 이상의 칼럼(ex. user_id 등)

샤딩 문제점

  • 데이터 재 샤딩(Resharding)
    • 하나의 샤드로 감당이 안될 때
    • 샤드 간 데이터 불균형(샤드 소진 속도가 다른 경우)
  • 유명 인사 문제(Celebrity, hotspot key)
    • 특정샤드에 질의가 집중되어 서버에 과부하가 걸리는 문제
  • 조인과 비정규화
    • 한 DB를 여러 샤드로 나누면 여러 샤드에 걸친 데이터를 조인하기 힘들 수 있음
    • 데이터베이스 비정규화 → 한 테이블에서 질의가 수행되도록 해야 함


| 사용자 규모 확장

  • 시스템 규모 확장은 지속적이고 반복적
  • 정리
    • 웹 계층은 무상태
    • 모든 계층의 다중화
    • 가능한 한 많은 데이터 캐시
    • 여러 데이터 센터 지원
    • 정적 컨텐츠는 CDN을 통해 서비스
    • 데이터 계층은 샤딩을 통한 규모 확장
    • 계층은 독립적 서비스로분할
    • 시스템의 지속적 모니터링, 자동화 도구 활용


| 개략적 규모 추정

  • 얼마나 많은 요청을 처리해야 하는지, 얼마나 데이터를 저장해야 하는지, 얼마나 많은 서버가 필요한지를 개략적으로 추정하는 것 ⇒ 시스템 용량이나 성능 요구 사항을 개략적으로 추정
  • 초기 설계 단계에서 과부하 방지, 비용 효율적 설계, 확장성 확보를 위해 수행 → 완벽한 값이 아닌 근사치 구하는게 목적
  • 개략적인 규모 추정은 보편적으로 통용되는 성능 수치에서 사고 실험을 행해 추정치를 계산 ⇒ 어떤 설계가 요구사항에 부합할지 보기 위한 것

주요 지표

  • QPS (Queries Per Second)
    • 초당 요청 수
  • 저장소 요구량
    • 한 사용자당 데이터 크기 x 사용자 수 +(로그, 이미지, 백업 등 고려하여 여유율 추가)
  • 캐시 요구량
    • 전체 데이터 중 얼마나 자주 조회될지
  • 서버 수
    • 서버 수 = (최대 QPS / 서버 1대 처리 능력) × 여유율

2의 제곱수

  • 데이터 볼륨의 단위를 2의 제곱수로 표현할 경우
  • 2의 x 제곱근사치이름축약형
    101,000(천)1킬로바이트1KB
    201000,000(백만)1메가바이트1MB
    301000,000,000(10억)1기가바이트1GB
    401조1테라바이드1TB
    501000조1페타바이트1PB


| 시스템 설계

요구사항 이해

  • 구체적으로 어떤 기능을 만들어야 하는지?
  • 제품 사용자 수가 얼마나 되는지?
  • 회사 규모는 얼마나 빨리 커질지 예상하는지? 이후의 규모가 어떻게 될지 어떻게 예상하는지?
  • 회사가 주로 사용하는 기술 스택은 무엇인지?
  • 설계 단순화를 위해 활용할 수 있는 기존 서비스는 어떤 것들이 있는지?

profile
백엔드 개발자 나무입니다

0개의 댓글