![[가상 면접 사례로 배우는 대규모 시스템 설계 기초] 1장 사용자 수에 따른 규모 확장성](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqW1S9%2FbtsKI4jhkii%2FnS3M692ixr8Kt8JINXjVxk%2Fimg.png)
1장. 사용자 수에 따른 규모 확장성
단일 서버

- 사용자는 도메인 이름을 이용하여 웹사이트에 접속한다.
이 접속을 위해서는 도메인 이름을 도메인 이름 서비스에 질의하여 IP 주소로 변환하는 과정이 필요하다. - DNS 조회로 웹 서버의 IP 주소가 반환된다.
- 해당 IP 주소로 HTTP 요청이 전달된다.
- 요청을 받은 웹 서버는 HTML 페이지나 JSON 형태의 응답을 반환한다.
데이터베이스
사용자가 늘면 서버 하나로는 충분하지 않아서 여러 서버를 두어야 한다.
하나는 웹/모바일 트래픽 처리 용도고, 다른 하나는 데이터베이스용이다.

데이터베이스는 크게 RDBMS, NoSQL 2가지로 나눌 수 있다. 대체적으로는 RDBMS로 해결할 수 있고 적절한 상황이지만, 아래와 같은 경우에는 NoSQL이 적절한 선택일 수 있다.
- 아주 낮은 응답 지연시간이 요구됨
- 다루는 데이터가 비정형이라 관계형 데이터가 아님
- 데이터를 직렬화하거나 역직렬화할 수 있기만 하면 됨
- 아주 많은 양의 데이터를 저장할 필요가 있음
수직적 규모 확장 vs 수평적 규모 확장
스케일 업(scale up) : 수직적 규모 확장은 서버에 고사양 자원(더 좋은 CPU, 더 많은 RAM)을 추가하는 것
스케일 아웃(scale out) : 수평적 규모 확장은 더 많은 서버를 추가하여 성능을 개선하는 행위
무엇이 더 적절할까?
서버로 유입되는 트래픽의 양이 적을 때는 수직적 확장이 좋은 선택이며, 이 방법의 가장 큰 장점은 단순함이다.
그러나 스케일 업에는 심각한 단점이 존재한다.
- 한 대의 서버에 CPU나 메모리를 무한대로 증성할 방법은 없다.
- 장애에 대한 자동복구(failover) 방안이나 다중화 방안을 제시하지 않는다.
서버에 장애가 발생하면 웹사이트/앱은 완전히 중단된다.
위와 같은 단점 때문에, 대규모 애플리케이션을 지원하는 데는 수평적 규모 확장법이 보다 적절하다.
로드밸런서

사용자는 로드밸런서의 공개 IP 주소(Public IP)로 접속한다. 서버 간 통신에는 Private IP가 이용된다. 위처럼 스케일 아웃을 통해서 서버를 여러 대로 늘리게 되면 장애를 자동복구하지 못하는 문제(no failover)도 해소할 수 있고, 웹 계층의 가용성(availability)은 향상된다.
데이터베이스 다중화
데이터베이스를 Master-Slave로 나누는데 쓰기 연산은 Master에서만 지원하고, 읽기 연산은 Slave에서만 지원한다.
대부분의 애플리케이션에서는 쓰기 작업 보다는 읽기 작업이 훨씬 많기 때문에 Slave 데이터베이스가 훨씬 많다.

예를 들면,
- select 은 slaveDB
- update 는 master DB
데이터베이스 다중화의 장점
- 더 나은 성능 : 모든 데이터 변경 연산은 Master 서버로만 전달되는 반면 읽기 연산은 Slave 데이터베이스 서버들로 분산된다. 병렬로 처리될 수 있는 쿼리의 수가 늘어나므로 성능이 좋아진다.
- 안전성: 데이터베이스 서버 가운데 일부가 파괴되어도 데이터는 보존될 것이다. 데이터를 지역적으로 떨어진 여러 장소에 다중화 시켜놓을 수 있기 때문이다.
- 가용성: 데이터를 여러 지역에 복제해 둠으로써, 하나의 데이터베이스 서버에 장애가 발생하더라도 다른 서버에 있는 데이터를 가져와 계속 서비스할 수 있게 된다.

- 사용자는 DNS로부터 로드밸런서의 공개 IP 주소를 받는다.
- 사용자는 해당 IP 주소를 사용해 로드밸런서에 접속한다.
- HTTP 요청은 서버 1이나 서버 2로 전송된다.
- 웹 서버는 사용자의 데이터를 부 데이터베이스 서버에서 읽는다.
- 웹 서버는 데이터 변경 연산은 주 데이터베이스로 전달한다.
캐시
캐시는 값 비싼 연산 결과 또는 자주 참조되는 데이터를 메모리 안에 두고, 뒤이은 요청이 보다 빨리 처리될 수 있도록 하는 저장소이다. 애플리케이션의 성능은 데이터베이스를 얼마나 자주 호출하느냐에 크게 좌우되는데, 캐시는 그런 문제를 완화할 수 있다.
캐시 계층
캐시 계층은 데이터가 잠시 보관되는 곳으로 데이터베이스보다 훨씬 빠르다.

- 요청을 받은 웹 서버는 캐시에 응답이 저장되어 있는지를 확인한다.
- 만일 저장되어 있다면 해당 데이터를 클라이언트에 반환한다.
- 없는 경우에는 데이터베이스 쿼리를 통해 데이터를 찾아 캐시에 저장한 뒤 클라이언트에 반환한다.
캐시 사용 시 유의할 점
- 캐시는 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어난다면 고려해볼만 하다.
- 영속적으로 보관할 데이터를 캐시에 두는 것은 바람직하지 않다.
- 캐시는 데이터를 휘발성 메모리에 두기 때문에, 캐시 서버가 재시작되면 모든 데이터는 사라진다.
- 만료된 데이터는 캐시에서 삭제되어야 한다.
- 만료 기한에 대한 정책을 마련하는 것이 좋다.
- 만료 기한이 너무 짧으면, 데이터베이스를 너무 자주 읽게 되며, 너무 길면 원본과 차이가 날 가능성이 높아진다.
- 데이터 저장소의 원본과 캐시 내의 사본 일관성을 확인해야 한다.
- 캐시 서버를 한 대만 두는 경우 해당 서버는 단일 장애 지점(SPOF)이 되어 버릴 수 있다.
- 캐시 메모리 크기는 너무 크지도 작지도 않게 적절하게 잡아야 한다.
- 캐시가 꽉 차버리면 LRU, LFU, FIFO 같은 정책들을 사용해서 사용해야 한다.
콘텐츠 전송 네트워크(CDN)
CDN은 정적 콘텐츠를 전송하는 데 쓰이는, 지리적으로 분산된 서버의 네트워크이다. 이미지, 비디오, CSS, JavaScript 파일 등을 캐시할 수 있다.


- 사용자 A가 이미지 URL을 이용해 image.png에 접근한다.
- CDN 서버의 캐시에 해당 이미지가 없는 경우, 서버는 원본 서버에 요청하여 파일을 가져온다.
- 원본 서버가 파일을 CDN 서버에 반환한다.
- CDN 서버는 파일을 캐시하고 사용자 A에게 반환한다.
- 사용자 B가 같은 이미지에 대한 요청을 CDN 서버에 전송한다.
- 만료되지 않은 이미지에 대한 요청은 캐시를 통해 처리된다.

- 정적 컨텐츠(JS, CSS, 이미지 등)는 더 이상 웹 서버를 통해 서비스하지 않으며, CDN을 통해 제공하여 더 나은 성능을 보장한다.
- 캐시가 데이터베이스 부하를 줄여준다.
무상태(Stateless) 웹 계층
이제는 웹 계층을 수평적으로 확장하는 방법을 고민해본다.
이를 위해서는 상태 정보(사용자 세션 데이터 등)를 웹 계층에서 제거해야한다. 바람직한 전략은 상태 정보를 관계형 데이터베이스나 NoSQL 같은 지속성 저장소에 보관하고 필요할 때 가져오도록 하는 것이다. 이렇게 구성된 웹 계층을 무상태 웹 계층이라고 부른다.
무상태 아키텍처

이 구조에서 사용자로부터의 HTTP 요청은 어떤 웹 서버로도 전달될 수 있다.
웹 서버는 상태 정보가 필요할 경우, 공유 젖아소로부터 데이터를 가져온다. 따라서 상태 정보는 웹 서버로부터 물리적으로 분리되어 있다. 이런 구조는 단순하고, 안정적이며, 규모 확장이 쉽다.
데이터 센터
장애가 없는 상황에서 사용자는 가장 가까운 데이터 센터로 안내되는데, 통상 이 절차를 지리적 라우팅이라고 부른다.

만약 데이터 센터 중 하나에 심각한 장애가 발생하면 모든 트래픽은 장애가 없는 데이터 센터로 전송된다.
다중 데이터센터를 만들기 위해서 고려해야 할 조건
- 트래픽 우회: 올바른 데이터 센터로 트래픽을 보내는 효과적인 방법을 찾아야 한다.
- 데이터 동기화: 데이터 센터마다 별도의 데이터베이스를 다중화한다.
- 테스트와 배포: 여러 위치에서 애플리케이션을 테스트 해보고, 자동화 배포가 모든 데이터 센터에 동일하게 설치되도록 하는 것이 중요하다.
메세지 큐

메세지 큐는 메세지의 무손실, 즉 메세지 큐에 일단 보관된 메세지는 소비자가 꺼낼 떄까지 안전히 보관된다는 특성을 보장하는 비동기 통신을 지원하는 컴포넌트이다. Publish/Producer는 메세지 큐에 발행한다. 큐에는 보통 Consumer/Subscribe가 메세지를 꺼내서 동작을 수행한다.
메세지 큐를 이용하면 서비스 또는 서버 간 결합이 느슨해져서, 규모 확장성이 보장되어야 하는 안정적 애플리케이션을 구성하기 좋다.

로그, 메트릭 그리고 자동화
비지니스의 규모가 커지면 로그, 매트릭, 자동화 도구에 필수적으로 투자해야한다.
- 로그 : 에러 로그를 모니터링하는 것은 중요. 시스템의 오류와 문제들을 보다 쉽게 찾아낼 수 있도록 하기 때문이다.
- 메트릭 : 메트릭을 잘 수 집하면 사업 현황에 관한 유용한 정보를 얻을 수 있고, 시스템의 현재 상태를 파악할 수 있다.
- 자동화 : 시스템이 크고 복잡해지면 생산성을 높이기 위해 자동화 도구를 활용해야 한다.
데이터베이스의 규모 확장
저장할 데이터가 많아지면 데이터베이스에 대한 부하도 증가한다.
이 때도 애플리케이션 서버처럼 스케일 업, 스케일 아웃 두 가지 방법이 존재한다.

데이터베이스에도 수직적 확장보다는 수평적 확장이 더 적절하다. 수평적 확장에 대표적으로는 샤딩이 있다.
샤딩은 대규모 데이터베이스를 샤드라고 부르는 작은 단위로 분할하는 기술을 말한다.
샤딩 전략을 구현할 때 중요한 것은 샤딩 키 이다. 샤딩 키에 따라서 한 곳으로만 부하가 집중될 수 있고 여러 곳으로 적절히 잘 분산될 수도 있다.
샤딩을 위해서 고려해야 할 조건
- 데이터의 재 샤딩
- 데이터가 너무 많아져서 하나의 샤드로는 더 이상 감당하기 어려울 때
- 샤드 간 데이터 분포가 균등하지 못하여 어떤 샤드에 할당된 공간 소모가 다른 샤드에 비해 빨리 진행될 때
- 유명 인사: 핫스팟 키 문제라고도 부르는데, 특정 샤드에 쿼리가 집중되어 서버에 과부하가 걸리는 문제
- 조인과 비정규화
일단 하나의 데이터베이스를 여러 샤드 서버로 쪼개고 나면, 여러 샤드에 걸친 데이터를 조인하기가 힘들어진다. 이를 해결하는 한 가지 방법은 데이터베이스를 비정규화하여 하나의 테이블에서 쿼리가 수행될 수 있도록 하는 것이다.
Reference
[가상 면접 사례로 배우는 대규모 시스템 설계 기초] 1장 사용자 수에 따른 규모 확장성
1\. 사용자는 도메인 이름을 이용하여 웹사이트에 접속한다. 이 접속을 위해서는 도메인 이름을 도메인 이름 서비스에 질의하여 IP 주소로 변환하는 과정이 필요하다.2\. DNS 조회로 웹 서버의 IP
velog.io
'Study > 대규모 시스템 설계 기초' 카테고리의 다른 글
[가상 면접 사례로 배우는 대규모 시스템 설계 기초] 4장 개략적인 규모 측정 (1) | 2024.11.14 |
---|---|
[가상 면접 사례로 배우는 대규모 시스템 설계 기초] 3장 시스템 설계 면접 공략법 (1) | 2024.11.14 |
[가상 면접 사례로 배우는 대규모 시스템 설계 기초] 2장 개략적인 규모 측정 (0) | 2024.11.14 |
대규모 시스템 설계 기초 스터디 (0) | 2024.11.14 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!