요즘 IT 기업의 면접을 계속 보는 중입니다. 면접 때마다 제가 공통적으로 대답을 잘 하지 못한 분야가 있는데, 그건 시스템 설계와 관련된 부분들이었습니다.
관련 지식들을 인터넷으로 학습하려고 했으나, 너무 단편적인 부분들만 알게 된다고 느껴졌습니다.
그래서 일종의 입문서를 통해서 어느정도 머릿속에 관련 지식과 키워드를 인덱싱을 해두고, 보다 깊은 개념들은 인터넷을 통해 알아보고자 합니다.
입문서로는 ‘가상 면접 사례로 배우는 대규모 시스템 설계 기초 (알렉스 쉬)’를 선택했습니다. 리뷰가 괜찮더라구요.
이번 포스팅에서는 확장 가능한 시스템을 설계할 때, 필요한 기본적인 지식들에 대해 정리하겠습니다.
많은 키워드와 기술이 등장할 예정이며, 각 내용에 대해 자세히 다루지는 못했습니다. 다만, 시스템 설계를 학습할 때 필요한 기본적인 내용을 정리한다는 목적으로 글을 읽어주시면 감사하겠습니다.
이 글은 인사이트 출판사의 ‘가상 면접 사례로 배우는 대규모 시스템 설계 기초 (알렉스 쉬)’ 교재를 토대로 정리한 내용을 담고 있습니다.
단일 서버
이번 포스팅에서는 교재와 마찬가지로, 시스템을 한단계씩 개선해보면서 등장하는 각 기술들에 대해 정리하겠습니다.
가장 먼저 기본 구조부터 만들어보겠습니다.
이 구조에서는 하나의 Web Server가 모든 역할을 수행하게 됩니다. 즉, 한 개의 서버가 웹앱·DB·캐시 등을 모두 담당해서 처리하게 되는 것이죠.
위 시스템의 전체적인 흐름을 간략히 살펴보면 아래와 같습니다.
- 사용자가 DNS 서버에 질의해서 서버의 IP 주소를 얻어옵니다.
- 사용자가 해당 IP 주소로 HTTP 요청을 보내고, 웹서버가 HTTP 응답을 합니다.
그럼 이번에는 웹서버에서 DB를 분리해서 좀 더 나은 구조로 만들어보겠습니다.
DB
기존에는 하나의 서버가 애플리케이션 역할과 DB 역할을 모두 수행했습니다. 이 경우, 사용자가 조금만 더 증가하더라도 서버측 부담이 커지겠죠?
가장 큰 문제는 저장·조회되는 데이터가 증가하는 경우에도, 웹서버 자체의 성능을 높혀야한다는 것입니다.
이를 개선해보면 아래와 같습니다.
위처럼 Web Layer
와 Data Layer
를 분리하면, 아래와 같은 장점을 갖을 수 있습니다.
- 모든 것을 처리하던 웹서버의 부담을 줄일 수 있다.
- 트래픽 처리 서버 (
Web Layer
) 와 DB 서버 (Data Layer
) 를 각각 독립적으로 확장할 수 있다.
그렇다면 어떤 DB를 사용하는 것이 좋을까?
위와 같이 시스템을 구성하기로 결정했다면, 우리는 한가지를 더 선택해야 합니다.
DB로 RDBMS를 사용할 것인지, NoSQL을 사용할 것인지를 결정해야 합니다.
아래 표는 각 DB가 무엇이고, 어떤 특징을 가지고 있는지 나타냅니다.
종류 | 목적 | 데이터 특성 | 데이터 표현 | 특징 |
---|---|---|---|---|
RDBMS | 데이터 무결성 | 정형 데이터 | 테이블, 칼럼, 열 | - 엄격한 스키마를 통해, 데이터 중복을 최소화하는 것에 초점 - 데이터 중복 최소화로 데이터 무결성 유지 - 서로 다른 테이블의 데이터는 Join 연산으로 함께 조회 가능 |
NoSQL | DB 확장성 | 비정형 데이터 | Key-Value, Graph, Column, Document | - 유연한 스키마를 가짐 - 데이터 무결성보단, DB의 확장성에 초점 - 일반적으로 Join 연산 미지원 |
RDBMS가 나은 경우
- 데이터 정합성이 중요한 서비스인 경우
- 엄격한 스키마를 통해, 데이터 중복을 최소화할 수 있다. 따라서 데이터 무결성 유지에 유리하다.
- 조회보다 업데이트가 많은 서비스인 경우
- 중복된 데이터가 최소화되어, 함께 수정해야하는 데이터가 적기 때문에 성능적으로 유리하다.
- 정규화된 여러 테이블의 데이터를 함께 조회하는 경우
Join
연산을 사용하기 때문에,Join
연산을 사용하지 않는 NoSQL보다 성능이 낮다.
NoSQL이 나은 경우
- 아주 낮은 응답 지연시간이 요구되는 경우
- 서로 다른 객체간의 중복된 필드가 존재할 수 있기 때문에,
Join
연산이 필요하지 않아 성능적으로 유리 - 예시)
User(name, gender)
,Photo(data, user_pk)
객체가 있고, ‘성별이 여성인 사용자의 사진을 조회’ 작업을 수행해야 경우- 먼저
User(gender=female)
을 조회한 뒤, 그 결과를 활용해서Photo(user_pk IN 여성유저)
처럼 조회해야함. - 두 번 조회를 해야하기 때문에, 비효율적임. NoSQL의 특성을 잘 살려서, 아래와 같이 해결할 수 있음.
- 먼저
- 예시)
User(name, gender)
,Photo(data, gender)
객체가 있고, ‘성별이 여성인 사용자의 사진을 조회’ 작업을 수행해야 경우gender
필드가User
,Photo
객체에 모두 중복되어 존재함.- 따라서
User
를 조회할 필요없이,Photo(gender=female)
을 조회하면 됨.
- 서로 다른 객체간의 중복된 필드가 존재할 수 있기 때문에,
- 다루는 데이터가 비정형이기 때문에, 관계형 데이터가 아닌 경우
- 비정형 데이터 : 소셜 데이터의 텍스트, 이미지, 영상, 워드나 PDF 문서와 같은 멀티미디어 데이터
- 데이터를 직렬화하거나 역직렬화할 수 있기만 하면 되는 경우
- 아주 많은 양의 데이터를 저장해야 하는 경우
스케일업 vs 스케일아웃
이번에는 서버를 확장할 때 선택할 수 있는 방법 두가지, 스케일업·스케일아웃에 대해 알아보겠습니다.
먼저 스케일업은 ’서버에 고사양 자원을 추가하는 행위’ 를 의미합니다. 반면에 스케일아웃은 ‘더 많은 서버를 추가하여 성능을 개선하는 행위’ 를 말합니다.
스케일업의 가장 큰 장점은 단순함이지만, 단점이 많습니다. 이는 아래와 같습니다.
- 한 대의 서버에 CPU나 메모리를 무한대로 증설할 방법은 없다.
- 장애에 대한 자동복구나 다중화를 제공하지 않는다. 즉 가용성을 확보하기 어렵다.
이런 단점때문에, 보통 스케일아웃을 많이 사용합니다.
로드밸런서
스케일아웃을 하기 위해 필요한 것은 서버 앞단에서 부하를 각 서버에 고르게 분산시켜주는 로드밸런서입니다.
로드밸런서를 포함한 시스템은 아래와 같이 구성됩니다.
로드밸런서를 시스템에 두었을 경우, 가장 먼저 사용자는 로드밸런서의 공개 IP 주소로 접속합니다. 따라서 웹 서버는 클라이언트의 접속을 직접 처리하지 않습니다.
그리고 서버 간 통신(로드밸런서 ↔ 서버)에는 사설 IP 주소를 사용하게 됩니다.
[Public IP와 Private IP]
- Public IP : 인터넷 상에 공개된 IP주소를 의미하며, 이를 통해 외부 인터넷과 통신할 수 있다.
- Private IP : 내부망(Subnet)에서만 사용되는 IP주소를 의미하며, 외부 인터넷과는 통신할 수 없다. 이를 통해, 보안성을 높일 수 있다. (직접 외부에서 서버에 접근할 수 없기 때문에)
스케일 아웃(with Load Balancer)의 장점
위 그림처럼 서버를 하나 더 추가한 것을 스케일 아웃이라고 합니다. 로드밸런서를 통한 스케일 아웃의 장점은 아래와 같습니다.
- 장애를 자동복구하지 못하는 문제 해결해, 웹 계층의 가용성 확보
- 서버1이 다운되면, 로드밸런서가 모든 트래픽을 서버2로 전송한다.
따라서 웹사이트 전체가 다운되는 일을 방지할 수 있다.
- 서버1이 다운되면, 로드밸런서가 모든 트래픽을 서버2로 전송한다.
- 유연한 확장성 확보
- 만약 현재의 서버 개수로 트래픽을 감당하기 어렵다면, 단순히 서버를 하나 더 추가하고 로드밸런서에 등록하기만 하면 된다.
DB 다중화 (Main-Replica 모델)
지금까지 웹계층에서의 스케일아웃에 대해 알아봤습니다. 그렇다면 데이터계층 즉, DB는 어떻게 확장해야 할까요? 지금부터 알아봅시다.
보통 DB는 Main-Replica 모델로 다중화를 지원합니다. 각각의 역할은 아래와 같습니다.
Main (Master) | Replica (Slave) |
---|---|
Write 작업 수행 | Read 작업 수행 |
원본 데이터를 가지고 있음 | Main으로부터 데이터 사본을 전달받음 |
대부분의 서비스에서는 읽기 연산의 비중이 쓰기 연산보다 훨씬 높기 때문에, 통상적으로 Replica DB서버의 수가 더 많습니다.
아래 그림은 DB를 스케일아웃하여, Main-Replica 모델을 적용한 시스템 구성도입니다.
위 그림은 아래와 같이 동작하게 됩니다.
- 사용자가 DNS로부터 로드밸런서의 공개 IP 주소를 받습니다.
- 사용자가 해당 IP 주소를 통해서 로드밸런서에 접속합니다.
- HTTP 요청은 서버 1이나 서버 2로 전달됩니다.
- 웹 서버는 사용자의 데이터를 Replica DB에서 읽습니다.
- 웹 서버는 데이터 변경 작업을 Main DB에 전달합니다.
Main-Replica 모델의 장점
- 더 나은 성능
- 모든 데이터 변경 작업은 Main DB에서 수행되고, 모든 데이터 읽기 작업은 Replica DB에서 수행됨.
그렇기 때문에 동시에(병렬로) 처리될 수 있는 작업의 수가 늘어나기 때문에, 성능이 좋아짐.
- 모든 데이터 변경 작업은 Main DB에서 수행되고, 모든 데이터 읽기 작업은 Replica DB에서 수행됨.
- 안정성 확보
- 데이터 복제본이 여러 서버에 존재하기 때문에, 한 서버에 문제가 발생하더라도 데이터를 복구할 수 있음.
- 가용성 확보
- 데이터 복제본이 여러 서버에 존재하기 때문에, 한 서버에 문제가 발생하더라도 서비스를 계속 유지할 수 있음.
Main-Replica 모델에서 가용성을 확보하는 방법
기존 웹계층에서는 로드밸런서를 통해 유효한 서버에 트래픽을 보내서 가용성을 확보했습니다.
그렇다면 DB에서는 어떻게 가용성을 확보해야할까요? 발생한 문제 상황에 따라 살펴봅시다.
- 문제 1) Replica 서버가 1 대이며, 해당 Replica 서버가 다운된 경우
- 모든 읽기 작업이 한시적으로 Main 서버에서 수행됨.
- 그리고 새로운 Replica 서버를 만들어, 기존의 Replica 서버를 대체함.
- 문제 2) Replica 서버가 여러 대이며, 특정 Replica 서버가 다운된 경우
- 읽기 작업을 나머지 유효한 Replica 서버에서 수행함.
- 새로운 Replica 서버를 만들어, 문제가 발생한 Replica 서버를 대체함.
- 문제 3) Replica 서버가 1 대이며, Main 서버가 다운된 경우
- Replica 서버를 즉시 새로운 Main 서버로 변경하고, 모든 쓰기·읽기 작업을 새로운 Main 서버에서 진행함.
- 새로운 Replica 서버를 만들음.
캐시
캐시는 ‘오래 걸리는 연산 결과’나 ‘자주 참조되는 데이터’를 메인 메모리에 적재하고, 뒤이은 요청이 빨리 처리될 수 있도록 하는 저장소입니다.
즉, DB 조회나 연산 작업 없이 빠르게 메모리 상에서 원하는 데이터를 찾을 수 있도록 하는 역할을 수행합니다.
아래 그림은 대표적인 캐시 전략인 Read-Through
를 적용한 것을 나타냅니다.
- HTTP 요청을 받은 웹 서버가 캐시에 데이터를 요청한다.
- 만약 데이터가 캐시에 저장되어 있다면(Cache Hit), DB를 조회하지 않는다. 만약 데이터가 캐시에 저장되어 있지 않다면(Cache Miss), 캐시가 데이터를 DB에서 조회해온 뒤 저장한다.
- 캐시가 데이터를 웹서버에 반환한다.
캐시의 장점
- 메인 메모리 기반으로 동작하기 때문에, 직접 디스크 I/O를 수행하는 DB보다 빠르게 동작
- DB 대신 데이터 작업을 수행하기 때문에, DB 부하 감소
- 캐시 계층의 규모를 독립적으로 확장시키는 것이 가능
캐시 사용시 유의 사항
캐시를 사용해서 성능을 개선하고, DB의 부하를 줄일 수 있지만 아래 사항들을 충분히 고려해봐야 합니다.
- 캐시가 적합한 경우
- 데이터 갱신은 자주 일어나지 않고, 참조는 빈번하게 일어나는 경우 적합
- 데이터 갱신이 자주 일어나는 경우, 캐시의 데이터를 최신 상태로 유지하기 어렵기 때문
- 데이터
- 캐시는 데이터를 메인 메모리에서 관리하기 때문에, 데이터가 휘발될 수 있음
- 따라서 중요한 데이터를 캐시에서만 관리하는 것은 바람직하지 않음
- 데이터 만료기한 설정
- 캐싱된 데이터가 만료될 시간을 어떻게 설정할 것인지에 대한 고민이 필요
- 만료 기한이 너무 짧다면: DB 조회가 빈번해짐
- 만료 기한이 너무 길다면: 데이터의 최신 상태 유지 어려움
- 일관성 유지
- DB에 저장된 데이터와 캐싱된 데이터의 버전이 같음을 어떻게 유지할 것인지
- 만약 데이터 쓰기 작업시, 하나의 트랜잭션으로 ‘캐시 데이터 업데이트’와 ‘DB 데이터 업데이트’를 함께 수행하도록 하면, 일관성은 유지됨.
하지만 그만큼 오버헤드가 증가하게 됨.
- 장애 대처
- 캐시 서버를 하나만 두는 경우 해당 서버가 단일 장애 지점(SPOF)이 될 수 있음.
- 따라서 여러 캐시 서버를 두어야 함.
- 캐시 메모리 크기
- 캐시 메모리가 너무 작으면, 데이터 교체가 빈번하게 발생하여 성능이 저하됨.
- 데이터 교체 알고리즘
- FIFO, LRU, LFU 와 같은 데이터 교체 알고리즘으로 무엇을 사용할 것인지
- FIFO : 가장 오래된 데이터를 교체
- LRU : 가장 읽은지 오래된 데이터를 교체
- LFU : 가장 사용빈도가 낮은 데이터를 교체
컨텐츠 전송 네트워크 (CDN)
CDN은 Contents Delivery Network의 약자로, 정적 컨텐츠를 효율적으로 전송하기 위해, 지리적으로 분산된 네트워크를 의미합니다.
즉, HTML·CSS·JS·이미지 등의 정적 리소스를 빠르게 전달하기 위해 전세계에 위치한 서버에 캐싱을 해두는 것을 말합니다.
어떤 사용자가 웹사이트를 방문하면, 그 사용자에게 가장 가까운 CDN 서버가 정적 컨텐츠를 전달해줍니다.
CDN 동작 절차
- 사용자 A가 이미지 URL을 이용해서 image.jpg에 접근한다.
이때 URL의 도메인은 CDN의 도메인이다. - CDN 서버에 해당 이미지가 없는 경우, 원본 서버에 요청해서 파일을 가져온다.
원본 서버가 파일을 응답해줄 때,HTTP 응답 헤더의 TTL
값으로 해당 파일이 CDN에 얼마나 캐싱되어 있을지 결정해준다. - CDN 서버가 2번 절차에서 전달받은 파일을 저장하고, 사용자 A에게 전달한다.
- 사용자 B가 동일한 이미지 파일에 접근한다.
- 이미 캐싱된 파일이 만료되지 않았다면, 즉시 사용자 B에게 해당 파일을 전달한다.
CDN 사용 시 고려사항
- 비용
- 적절한 만료시한 설정
- 시의성(실시간 업데이트성)이 중요한 컨텐츠를 캐싱한다면, 만료 시한을 잘 설정해야함.
- CDN 장애에 대한 대처 방안
- CDN 자체가 죽었을 경우 서비스가 중단되지 않도록, 원본 서버에서 클라이언트가 파일을 가져갈 수 있도록 전략을 구성해야함.
캐시와 CDN이 적용된 시스템 구성도
캐시와 CDN을 기존 시스템에 적용하면, 아래와 같이 구성됩니다.
- 정적 컨텐츠는 이제 CDN으로부터 제공받게 됩니다.
사용자가 정적 컨텐츠를 받기 위해 Web Server에 접근하는 일은 더이상 없습니다. - 캐시를 통해, DB 부하를 감소시키고, 더 빠르게 응답합니다.
무상태 웹 계층
웹 계층의 스케일 아웃에 대해서 설명했었습니다. 이때 중요한 것이 바로, 서버가 무상태성을 갖도록 하는 것입니다.
무상태성이란, 웹 계층에서 상태 정보를 갖지 않도록 하는 것을 말합니다. 즉, 세션 데이터 등을 웹 서버가 갖지 않도록 해야 합니다.
이렇게 구성된 웹 계층을 무상태 웹 계층이라고 합니다.
바로 무상태 웹 계층을 만들기 위해서, RDBMS나 NoSQL 같은 지속성 저장소에 상태 정보를 보관하고, 필요할때마다 접근하여 사용하도록 시스템을 구성합니다.
상태 정보에 의존적인 웹 계층
그렇다면, 왜 웹 계층이 상태 정보를 가지고 있으면 안되는 것일까요? 아래와 같이 상태 정보를 가지고 있는 경우에 대해 알아보면서, 발생할 수 있는 문제에 대해 설명하겠습니다.
각 서버가 서로 다른 사용자에 대한 상태 정보 (세션 데이터) 를 가지고 있습니다. 즉, 웹 계층이 상태 정보를 가지고 있는 것이죠.
이 상태에서, 로드밸런서에 의해서 아래와 같이 요청이 분산되었다고 해보겠습니다.
위 그림에서 사용자들이 어떤 서버에 연결되었는지를 정리해보면 아래와 같습니다.
- 사용자 A → Server 3
- 사용자 B → Server 2
- 사용자 C → Server 1
이 경우엔, 사용자 B는 자신의 세션 정보가 존재하는 서버에 접속했기 때문에, 정상적으로 서비스를 사용할 수 있게 됩니다. (로그인 정보를 세션으로 관리한다면, 로그인된 사용자로 서버가 인식 가능)
하지만 사용자 A와 사용자 B는 자신의 세션 정보가 존재하지 않는 서버로 각각 접속되었기 때문에, 서비스 사용에 문제가 발생합니다. (다시 로그인해야함)
로드밸런서가 사용자마다 적절한 서버에 접속하게 해준다면?
이를 해결하기 위해서, 각 사용자가 처음 접속했던 서버로만 접근할 수 있도록 로드밸런서가 처리를 해줄 수도 있습니다.
이것을 Sticky Session 이라고 합니다.
[Sticy Session]
고정 세션이라고도 불린다. 로드밸런서가 지원하는 기능으로, 쿠키값을 활용해서 사용자가 처음 접근한 서버에만 접속할 수 있도록 하는 기능을 말한다.
하지만, 이 경우 아래와 같은 문제가 발생하게 됩니다.
- 로드밸런서가 추가적으로 수행해야 하는 작업이 늘어났기 때문에, 로드밸런서의 부하가 증가한다.
- 특정 서버에만 부하가 집중될 수 있다.
- 만약 서버 A에 ‘대부분의 헤비 유저에 대한 세션 정보’가 담겨있게 된다면, 서버 A에게 과도한 트래픽이 집중된다.
하지만 무상태 웹 계층으로 구성한다면, 이 문제를 해결할 수 있게 됩니다.
무상태 아키텍처
아래 그림은 무상태 아키텍처를 보여줍니다.
위와 같이 시스템을 구성하게 되면, 웹 서버는 상태 정보가 필요할 경우 공유 저장소로부터 데이터를 가져옵니다.
따라서 상태 정보는 웹 서버로부터 물리적으로 분리되어 있게 됩니다.
실제로 기존 시스템에 공유 저장소를 추가해서, 웹 계층이 무상태를 갖도록 구성하면 아래와 같습니다.
위와 같이 구성하면 상태 정보를 웹 서버들로부터 분리해낼 수 있게 됩니다.
따라서 트래픽 양에 따라 웹 서버를 늘리거나 줄이는 오토 스케일링(Auto-Scaling) 이 가능해집니다.
메시지 큐
메시지 큐는 메시지의 무손실을 보장하고, 비동기 통신을 지원하는 컴포넌트입니다.
이 메시지 큐를 도입하여, 시스템의 컴포넌트들을 분리해서 세분화하고 비동기적으로 처리할 수 있도록 만들 수 있습니다.
즉, 메시지 큐를 통해 시스템의 컴포넌트들이 비동기적으로 통신하게 됩니다.
메시지 큐의 기본 아키텍처는 아래와 같습니다.
- 발행자(Publisher) 컴포넌트가 메시지를 만들어서, 메시지 큐에 발행(Publish)한다.
- 메시지 큐를 구독(Subscribe)하고 있는 구독자(Subscriber)가 메시지를 꺼내서, 그에 맞는 동작을 수행한다.
[메시지 큐를 사용했을 때, 비동기 처리가 가능해지는 이유]
생산자가 소비자의 작업을 기다리지 않고, 다른 작업을 수행할 수 있기 때문입니다.
생산자는 메시지를 발행한 뒤, 소비자의 작업을 기다리지 않고, 다른 작업을 처리할 수 있습니다.
이와 같은 메시지 큐를 사용하면, 서버(컴포넌트)간의 결합이 느슨해져서, 규모 확장성을 보장하기 쉬워집니다.
즉, 생산자 컴포넌트와 구독자 컴포넌트를 각각 독립적으로 확장시킬 수 있기 때문에, 좀 더 규모 확장성에 유리합니다. (필요한 컴포넌트만 더 확장시키면 되기 때문에)
메시지 큐 사용 예시
이해하기 쉽도록, 한가지 예시를 들어볼까요?
사진을 보정하는 서비스를 만든다고 해봅시다. 그리고 사진을 보정하는 작업이 매우 오래걸리는 작업인 경우, 아래와 같이 시스템을 구성할 수 있습니다.
이 시스템의 특징은 아래와 같습니다.
- 오래 걸리는 작업인 사진 보정 작업을 비동기적으로 처리할 수 있어서 효율적이다.
- 만약 동기적으로 처리한다면, ‘Web Server의 요청 처리 쓰레드’는 사진 보정 작업이 끝날 때까지 다른 작업을 수행할 수 없고 대기해야한다.
- 사진 보정 작업이 오래 걸린다면, 사진 보정 Server만 추가적으로 확장시킬 수 있다.
최종적으로 기존 시스템에 메시지 큐를 추가하면, 아래와 같은 시스템 구성도가 나오게 됩니다.
DB의 규모 확장 (샤딩)
이전에 DB를 확장하기 위한 방법 중 하나인, Main-Replica 모델에 대해 설명했습니다.
Main-Replica 모델을 통해서, DB의 부하를 줄이고 가용성을 확보하는 것이 가능했습니다.
하지만 이것은 매우 많은 데이터를 저장해야 하는 경우에 대한 해결책을 제시해주지는 못합니다.
따라서 이번에는 방대한 양의 데이터를 나눠서 저장하는 방법, 즉 샤딩에 대해 알아보겠습니다.
샤딩은 대규모 데이터베이스를 샤드(Shard)라는 단위로 분할하는 기술을 말합니다.
모든 샤드는 같은 스키마를 쓰지만, 샤드에 보관되는 데이터 사이에는 중복이 없습니다.
그 예시는 아래와 같습니다.
위 그림은 user_id
를 mod
연산자로 계산해서, 그 결과에 따라 서로 다른 DB Shard에 저장하는 것을 나타냅니다.
이때 가장 중요한 것은 샤딩 키(Sharding Key)를 어떻게 정하느냐는 것입니다.
샤딩 키는 ‘하나 이상의 칼럼으로 구성돼, 데이터를 어떻게 분산시킬지 결정하는 키’입니다.
이렇게 완벽해보이는 샤딩 기술에도 몇가지 극복해야하는 문제가 있습니다.
샤딩 시, 해결해야 하는 문제
- 데이터의 재 샤딩
- 만약 현재 구성된 샤드만으로 데이터를 관리하기 어려워서, 새로운 분할 DB를 추가한다면 모든 데이터를 다시 새롭게 분배해서 저장해야함.
이때 많은 자원을 소비해야함.
이 문제는 추후 포스팅으로 다루겠습니다.
- 만약 현재 구성된 샤드만으로 데이터를 관리하기 어려워서, 새로운 분할 DB를 추가한다면 모든 데이터를 다시 새롭게 분배해서 저장해야함.
- 유명인사 문제
- 특정 샤드에 질의가 집중되어서, 특정 DB에 과부하가 발생하는 문제
- 만약 SNS 서비스에서 여러 톱스타의 정보를 한 샤드에 저장하고 관리한다면, 발생하는 쿼리가 해당 샤드에 집중될 것
- 조인과 비정규화
- 만약 ‘특정 데이터와 연관된 데이터’가 여러 샤드에 걸쳐서 저장되어있고,
Join
을 통해서 함께 조회하려고 한다면, 모든 샤드를 살펴봐야함. - 이 문제를 해결하는 방법 중 하나가 바로 비정규화.
비정규화를 통해서, 하나의 샤드나 테이블에서만 쿼리를 실행하도록 만들 수 있음.
이 문제 역시 추후에 자세히 다뤄보겠습니다.
- 만약 ‘특정 데이터와 연관된 데이터’가 여러 샤드에 걸쳐서 저장되어있고,
샤딩이 적용된 최종 시스템 아키텍처
기존 시스템 구조에 샤딩을 적용하면, 최종적으로 아래와 같은 아키텍처가 됩니다.
정리하며
이번 포스팅을 통해서 대규모 시스템을 구성할 때, 필요한 기술들에 무엇이 있고 각 개념은 어떻게 되는지 알아보았습니다.
많은 키워드가 등장했고, 그렇기에 자세한 부분까지 다루지는 못했습니다. (아직 저도 각 기술에 대해서 자세히 학습해보지는 못했어요!)
계속해서 교재의 다음 챕터를 학습하며, 그 내용을 정리해보도록 하겠습니다.
이번 글을 통해서, 시스템을 구성하는 요소로는 무엇이 있고, 대략적으로 어떻게 동작하게 되는 것인지, 그리고 고려해봐야 하는 문제상황으로는 어떤 것이 있는지에 대해 깨닫게 되는 것이 있었으면 좋겠습니다.
감사합니다.