RDBMS vs NoSQL
- 대부분은 RDBMS
- 아래와 같은 경우는 NoSQL 고려
- 아주 낮은 응답 지연시간이 필요함
- 비정형 데이터를 다룸
- 데이터(JSON, YAML, XML등)를 직렬화 혹은 역직렬화 할 수 있기만 하면됨
- 대용량의 데이터를 저장할 필요가 있음
수직적 규모 확장 vs 수평적 규모 확장
- 스케일 업(수직적 규모 확장)
- 서버에 고사양 자원을 추가하는 행위(더 좋은 CPU, RAM등)
- 서버로 유입되는 트래픽의 양이 적을 때 좋은 선택
- 장점
- 단점
- 한계가 있다. 한대의 서버에 CPU나 메모리를 무한대로 증설할 방법은 없다.
- 장애에 대한 자동복구 방안이나 다중화 방안을 제시하지 않는다. → 서버에 장애가 발생하면 서비스는 완전히 중단된다.
- 스케일 아웃(수평적 규모 확장)
- 더 많은 서버를 추가하여 성능을 개선하는 행위
- 대규모 애플리케이션을 지원할 때 좋은 선택
로드밸런서
- 사용자가 바로 웹 서버에 연결된다면 웹 서버가 다운되면 사용자는 웹 사이트에 접속할 수 없다. 또한, 너무 많은 사용자가 접속하여 서버가 한계에 도달하면 응답 속도가 느려지거나 서버 접속이 불가능해질 수도 있다. → 이러한 문제를 해결하기 위해 로드밸런서가 필요하다.

- 사용자는 로드밸런서의 Public IP로 접속하고, 서버 간 통신에는 Private IP가 이용된다.
데이터베이스 다중화
- 데이터 원본은 Master DB에, 사본은 Slave DB에 저장한다.
- insert, delete, update 연산은 Master에서만 지원하고, Slave는 Master로 부터 사본을 전달받으며, read 연산만을 지원한다.
- 대부분의 애플리케이션은 쓰기 연산의 비중이 읽기 연산보다 훨씬 높다.
→ 위 그림처럼 Slave의 수가 Master보다 많은 경우가 대부분이다.
- 데이터베이스 다중화로 인해서 성능이 좋아지고, 안정성이 올라가고, 가용성이 좋아진다.
응답시간(latency) 개선 → 캐시 사용, 정적 콘텐츠를 콘텐츠 전송 네트워크(CDN)로 이동으로 개선
캐시
캐시 사용시 고려할 사항
- 캐시를 사용할 상황: 데이터 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어나는 경우
- 캐시에 두어야 하는 데이터: 캐시는 데이터를 휘발성 메모리에 둠 → 영속적으로 보관할 데이터를 캐시에 두는것은 X
- 캐시 데이터 만료 정책: 만료 정책이 없다면 데이터는 캐시에 계속 남게된다. 만료 기한이 너무 짧다면 DB를 너무 자주 읽게 된다. 너무 길다면 원본과 차이가 날 가능성이 높아진다.
- 캐시의 일관성: 저장소의 원본을 갱신하는 연산과 캐시를 갱신하는 연산이 한 트랜잭션으로 처리되지 않는 경우 일관성이 깨질 수 있다.
- 장애에 대처할 방법: 캐시 서버를 한 대만 두는 경우 해당 서버는 단일 장애 지점(SPOF)이 되어버릴 가능성이 있다. 그러므로 캐시 서버를 여러 지역에 걸쳐 분산시켜야 한다.
- 캐시 메모리 크기: 캐시 메모리가 너무 작으면 엑세스 패턴에 따라 데이터가 너무 자주 밀려나버려 캐시의 성능이 떨어지게 된다. → 캐시 메모리를 과할당 하여 해결할 수 있다.
- 데이터 방출 정책: 캐시가 꽉차고, 새로운 데이터를 넣으려면 어떤 데이터를 캐시에서 방출할 지 정해야한다. 이를 정하는 방법으로는 LRU(사용된지 오래된 데이터), LFU(사용된 빈도가 낮은 데이터), FIFO(가장 먼저 들어온 데이터)등이 있다.
콘텐츠 전송 네트워크(CDN)
CDN은 정적 콘텐츠를 전송하는 데 쓰이는, 지리적으로 분산된 서버의 네트워크이다. 이미지, 비디오, CSS, JavaScript 파일 등을 캐시할 수 있다.
CDN의 동작방식
- image.png 엑세스
- 이미지가 CDN에 없으면 원본 서버에서 가져와서 CDN에 저장
- image.png 반환
- 다른 사용자가 image.png 엑세스
- image.png 가 CDN에 저장되어 있으므로 바로 반환
CDN 사용시 고려할 사항
- 비용: CDN은 보통 제3 사업자(third-party providers)에 의해 운영되며, 데이터 전송 양에 따라 요금을 낸다. → 자주 사용되는 콘텐츠만 CDN에 넣자.
- 만료 시한: 너무 짧으면 원본 서버에 자주 접속하기 되고, 너무 길면 콘텐츠의 신선도가 떨어질 것이다.
- 장애에 대한 대처 방안: CDN이 응답하지 않을 경우, 해당 문제를 감지하여 원본 서버에서 직접 콘텐츠를 가져오도록 클라이언트를 구성할 필요가 있다.
- 콘텐츠 무효화 방법: CDN에 들어가 있는 콘텐츠가 원본서버에서 수정이나 삭제되었고, 이를 CDN에서도 제거 하고 싶다면 아래의 방법들이 있다.
- CDN 서비스 사업자가 제공하는 API이용
- 콘텐츠의 다른 버전을 서비스 하도록 오브젝트 버저닝 이용. ex) image.png?v=2
캐시와 CDN을 사용한 설계

→ CDN을 사용함 으로써 정적 콘텐츠는 더이상 웹 서버가 아닌 CDN을 통해 제공하여 더 나은 성능을 보장한다.
→ 캐시가 데이터베이스 부하를 줄여준다
무상태(stateless) 웹 계층
웹 계층을 수평적인 확장을 위해서는 웹 계층에서 상태정보(세션 등)를 제거해야함
→ 상태 정보를 관계형 데이터베이스나 NoSQL등 공유 저장소에 보관, 가져오기
→ 무상태 웹 계층
이렇게 상태정보가 웹 서버들로 부터 제거되면 트래픽에 따라 웹 서버를 추가 및 제거하며 규모를 확장할 수 있다.
데이터 센터
여러개의 데이터 센터를 이용하는 경우, 장애가 없는 상황에서 가장 가까운 데이터 센터로 연결됨. (지리적 라우팅)
해결해야하는 문제
- 트래픽 우회: 올바른 데이터 센터로 트래픽을 보내는 방법 찾기 → GeoDNS(지리적 라우팅)
- 데이터 동기화: 장애 발생시 다른 데이터베이스로 우회되어도 찾는 데이터가 없을 수 있음 → 데이터를 여러 데이터센터에 걸쳐 다중화
- 테스트와 배포: 웹 or 애플리케이션을 여러 위치에서 테스트해야함 → 자동화된 배포도구 중요
메세지 큐
메시지의 무손실을 보장하는 비동기 통신 컴포넌트 → 메시지의 버퍼 역할 + 비동기적 전송
생산자(Producer) 혹은 발행자(Publisher) 라고 불리는 입력 서비스가 메세지를 만들어 메시지를 메시지 큐에 발행(publish)
큐에는 소비자(Consumer) 혹은 구독자(Subscriber)라고 불리는 서비스, 서버가 연결되어 있고 메시지를 받아 그에 맞는 동작 수행
→ 서비스, 서버 간 결합이 느슨해져서 규모 확장성이 보장(생산자는 소비자가 장애가 발생해도 메시지 발행 가능, 소비자는 생산자가 장애가 발생해도 메시지 수신 가능)
로그, 메트릭 그리고 자동화
로그: 에러 로그를 모니터링하는 것은 중요, 서버 단위 모니터링 보단 로그를 단일 서비스로 모아주는 도구를 활용하는 것이 좋음
메트릭: 메트릭을 잘 수집 하면 사업 현황에 관한 유용한 정보 획득, 시스템 현재 상태 파악 용이
- 유용한 메트릭들
- 호스트 단위 메트릭: CPU, 메모리, 디스크 I/O에 관한 메트릭이 여기 해당
- 종합 메트릭: DB, 캐시 계층의 성능 등
- 핵심 비즈니스 메트릭: 일별 능동 사용자, 수익, 재방문 등이 해당
데이터베이스의 규모 확장
- 수직적 확장: 하드웨어 자원의 증설
- 수평적 확장: 서버 증설, 데이터베이스의 수평적 확장 = 샤딩(sharding)
- 샤딩: 대규모 데이터베이스를 샤드라고 부르는 작은 단위로 분할하는 기술. 모든 샤드는 같은 스키마 사용 but 중복 X
샤딩 전략 구현시 핵심 부분 = 샤딩 키를 어떻게 정하는가?
- 샤딩 키: = 파티션 키, 데이터가 어떻게 분산될 지 정하는 하나 이상의 컬럼으로 구성
- ex: user테이블의 정보를 4개의 샤드에 나눠 저장하는 경우 → user_id % 4 로 저장(user_id=1→1번 DB에 저장, user_id=2→2번 DB에 저장) → 이 경우 user_id가 샤딩 키
→ 샤딩 키를 통해 올바른 데이터베이스에 질의를 보내어 데이터 조회/변경을 처리하므로 효율 UP
- 샤딩 키를 정할 때는 데이터를 고르게 분할 할 수 있는 것이 중요
샤딩 도입 시 해결해야할 문제
- 데이터의 재 샤딩: 데이터가 너무 많아져서 하나의 샤드로는 감당이 안되거나, 샤드 간 데이터 분포가 불균등(샤드 소진)할 때 재 샤딩이 필요하다. → 샤드 키를 계산하는 함수 변경 + 데이터 재 배치 → 안정 해시 기법 활용
- 유명인사 문제(핫스팟 키 문제): 특정 샤드에 질의가 집중되어 과부하가 발생하는 문제.
- 조인과 비정규화: 여러 샤드에 걸친 데이터를 조인하기 힘듦 → 데이터베이스를 비정규화하여 하나의 테이블에서 질의가 수행될 수 있도록 할 수 있음