
1장에서는 한 명의 사용자를 지원하는 시스템부터 최종적으로는 몇백만 사용자를 지원하는 시스템으로 발전하는 과정을 담고 있습니다. 발전해 나가는 과정을 보며, 규모 확장성과 관련된 설계 문제를 푸는데 유용한 지식들을 얻어갈 수 있는 챕터입니다.
우선, 가장 간단한 단일 서버를 설계하는 과정에서 시작합니다. 일반적으로 다음 그림과 같이 하나의 서버에서 웹 서버, 데이터베이스, 캐시 등 전부 실행됩니다.

위 그림을 이해하기 위해선 사용자 요청이 처리되는 과정과 요청을 만드는 단말에 대한 이해가 필요합니다. 사용자 요청이 어떻게 처리되는지 흐름을 살펴보도록 하겠습니다.

이 접속을 위해서는 도메인 이름을 DNS에 질의하여 IP 주소로 변환하는 과정이 필요합니다. DNS는 보통 서드 파티가 제공하는 유료 서비스를 이용하게 되므로, 시스템의 일부는 아닙니다.

해당 그림에서는 134.231.23.45라고 되어있습니다. 이 주소는 웹 서버의 주소를 의미합니다.


사용자가 증가하면 서버 하나로는 충분하지 않아서 여러 서버를 두어야 합니다. 하나는 웹/모바일 트래픽 처리 용도로, 다른 하나는 데이터베이스 처리 용도로 사용합니다.

이렇게 웹 계층과 데이터 계층으로 서버를 분리하면 그 각각을 독립적으로 확장해 나갈 수 있습니다.
데이터베이스는 크게 관계형과 비-관계형으로 구분됩니다. 차이는 다음과 같습니다.
종류는 MySQL, Oracle, PostgreSQL 등이 있으며, 데이터를 테이블과 열, 컬럼으로 표현합니다. SQL을 사용하면 여러 테이블에 있는 데이터를 그 관계에 따라 Join하여 합칠 수 있습니다.
종류는 CouchDB, Cassandra, DynamoDB 등이 있습니다. NoSQL의 경우 다시 네 부류로 나눌 수 있는데 키-값 저장소, 그래프 저장소, 컬럼 저장소, 문서 저장소입니다. 이러한 NoSQL은 일반적으로 Join 연산은 지원하지 않습니다.
일반적으로 RDB를 선택해 사용하지만, 다음과 같은 경우 NoSQL 사용을 고려해 볼 수 있습니다.
Scale Up은 수직적 규모 확장으로 서버의 HW(CPU, RAM)을 업그레이드 하는 것을 말하고, Scale Out은 수평적 확장으로 더 많은 서버를 추가하여 성능을 분산하는 것을 말합니다.
서버로 유입되는 트래픽 양이 적을 때는 Scale Up이 가장 단순하기에 좋은 방법이지만, 다음과 같은 심각한 단점이 있습니다.
이러한 단점 때문에, 대규모 애플리케이션을 지원하는 데는 Scale Out을 사용하는 것이 적절합니다.
현재까지 설명하고 있었던 설계의 경우 사용자는 웹 서버에 바로 연결됩니다. 웹 서버가 다운되면 사용자는 접속할 수 없습니다. 또한, 너무 많은 사용자가 접속하여 웹 서버의 한계 상황에 도달 시 응답 속도가 느려지거나 서버 접속이 불가능해 질 수 있습니다. 이러한 문제를 해결하는 데는 부하 분산기 또는 로드밸런서를 도입하는 것이 최선입니다.
로드밸런서는 부하 분산 집합에 속한 웹 서버들에게 트래픽 부하를 고르게 분산하는 역할을 수행합니다. 다음 그림을 참고하면 좋을 것 같습니다.

사용자는 우선 공개 IP 주소로 접속하게 되어, 웹 서버는 클라이언트의 접속을 직접 처리하지 않습니다. 더 나은 보안을 위해, 서버 간 통신에는 사설 IP 주소가 이용됩니다.
사설 IP 주소란?
같은 네트워크에 속한 서버 사이의 통신에만 쓰일 수 있는 IP 주소로, 인터넷을 통해서는 접속이 불가합니다. 로드밸런서는 웹 서버와 통신하기 위해 바로 이 사설 IP 주소를 이용합니다.
이와 같이 서버를 구성하면 장애를 자동 복구하지 못하는 문제는 해소되며, 웹 계층의 가용성은 향상됩니다. 이에 대해 더 구체적으로 살펴보면 다음과 같습니다.
로드밸런서를 추가함으로써 웹 계층에서의 부하는 해결한 것 같습니다. 하지만, 데이터 계층은 여전히 고가용성을 가지고 있다고 보기엔 어렵습니다. 이를 해결하기 위해, 데이터베이스에 대한 다중화도 필요합니다.
데이터베이스의 경우 데이터 원본은 Master 서버에, 사본은 Slave 서버에 저장하는 방식인 Master-Slave 구조를 지원합니다. 이때, Master 서버는 쓰기 연산만 수행하게 되고, Slave는 Master로 부터 받은 사본을 전달 받아 읽기 연산만을 수행합니다. 이를 그림으로 표현하면 다음과 같습니다.

이러한 구성은 다음과 같은 이점을 가져옵니다.
로드밸런서와 데이터베이스 다중화를 고려한 설계는 다음과 같이 동작합니다.



