Skip to content
피스타치오는 맛있어
Instagram

1장. 신뢰할 수 있고 확장 가능하며 유지보수하기 쉬운 애플리케이션

, 아키택처, 프로그래밍, 분산시스템, 시스템디자인3 min read

데이터 시스템에 대한 생각

좋은 데이터 시스템을 개발하기 위해 우리들은 신뢰성, 확장성, 유지보수성에 집중해야 합니다.

신뢰성

우리가 기대하는 기능을 시스템이 수행할 뿐 아니라, 무언가 잘못되더라도 지속적으로 올바르게 동작해야 한다는 것이 신뢰성입니다.

여기서 무언가 잘못된다는 것은 결함을 의미한다. 결함을 예측하고 대처할 수 있는 시스템을 내결함성을 지녔다고 말하는데, 대부분의 결함은 미흡한 오류 처리에서 기인합니다.

Fault(결함)와 Failure(장애)는 다릅니다.

  • 결함: 잘못될 수 있는 일
  • 장애: 사용자에게 필요한 서비스를 제공하지 못하고 중단되는 경우

하드웨어 결함

하드웨어에서 물리적으로 문제가 생겨 신뢰성이 꺠지는 경우가 있습니다. 이 경우는 언제든 발생 가능하고 원천 차단이 불가능하기 때문에 요즘에는 소프트웨어 내결함성 기술을 사용하거나 하드웨어 중복성을 추가해 전체 장비의 손실을 견딜 수 있는 시스템(AWS, GCP 등)으로 옮겨가고 있습니다.

다운 타임이 발생하지 않도록 설정할 수 있기 때문에 물리 장비보다 더 매력적입니다.

소프트웨어 오류

Systematic error(체계 오류) 가 발생하여 신뢰성이 깨질 수 있습니다.

  • 잘못된 입력이 있을 때 애플리케이션이 뻗는 버그
  • CPU 시간, 메모리, 디스크 공간, 네트워크 대역폭 같은 공유 리소스를 과도하게 사용하는 프로세스
  • 시스템 속도가 느려져 반응이 없거나 잘못된 응답을 반환하는 서비스
  • 한 구성요소의 결함이 다른 구성요소들에 연쇄적으로 결함을 일으키는 연쇄 장애(Cascading failure)

이런 버그들은 특정 상황에 도달하기 전까지 나타나지 않습니다.

해결책 또한 딱 떨어지는 것이 아니라 미리미리 대비하는 수밖에 없습니다.

  • 시스템의 가정과 상호작용에 대해 주의 깊게 생각하기
  • 빈틈없는 테스트
  • 프로세스 격리
  • 죽은 프로세스의 재시작 허용
  • 프로덕션 환경의 시스템 모니터링, 동작 측정, 분석

과 같은 방법들을 통해 문제 해결에 도움을 얻을 수 있다.

인적 오류

운영자의 실수에 의해 신뢰성이 떨어질 수 있습니다.

  • 잘 설계된 추상화로 실수를 미연에 방지하자.
  • 사람이 많이 실수하는 부분에서 장애가 발생할 수 있는 부분을 분리해서 샌드박스 안에 집어넣자.
  • 테스트 코드를 통합테스트까지 철저하게 짜자.
  • 빠르게 복구할 수 있는 시스템을 고안하자.
  • 성능지표, 오류율 같은 모니터링 시스템을 구축하자.

신뢰성은 얼마나 중요할까?

신뢰성의 저하는 곧 비즈니스의 타격을 의미합니다.

확장성

부하 기술하기

부하 매개변수(load parameter)로 부하를 기술할 수 있습니다. 적절한 부하 매개변수는 시스템에 따라 다르지만, 예시는 다음과 같습니다.

  • 서버 초당 요청 수
  • DB write/read 비율
  • 대화방의 동시 active user
  • 캐시 적중률

트위터의 경우를 볼까요?

  • 평균적으로 초당 4600건의 트윗 메시지 게시 요청이 발생한다. 피크인 경우에는 초당 12000건의 요청이 발생
  • 자신이 팔로우한 사람의 트윗을 타임라인에서 조회하는 요청이 초당 300000건 발생

트윗 전역 컬렉션을 쓰는 경우라면, 타임라인 조회시마다 다음 쿼리가 실행됩니다.

1SELECT tweets.*, user.* FROM tweets
2 JOIN user ON tweets.sender_id = users.id
3 JOIN followers ON follows.followee_id = users.id
4 WHERE follows.follower_id = current_user

tweets에 트윗이 게시될 때마다 락이 잡혀서 원활하게 초당 300000건의 조회 요청을 수행하지 못할 겁니다.

이 문제를 해결하기 위해 사용자별 타임라인 캐시를 둔다고 가정하겠습니다.

사용자가 트윗을 작성하면 그 사용자의 팔로워의 캐시를 찾아 새로운 트윗을 삽입합니다. 조회 결과가 미리 계산되어 있기 때문에 앞선 방법보다 훨씬 저렴합니다.

그러나 이 경우도 문제점을 안고 있습니다. 쓰기를 하는 시점에 일일이 캐시를 찾아다니면서 트윗을 삽입해야 하는데, 일부 사용자는 팔로워가 3천만명이 넘습니다.

따라서 이 문제를 해결하기 위해 최종적으로 hybrid 형태의 접근 방식을 취합니다. 팔로워 수가 많은 경우 일일이 캐시를 업데이트 하는 것이 아니라, 기존처럼 join 해서 가져오는 방법을 사용합니다.

성능 기술하기

시스템의 성능이 높을수록 높은 부하를 견딥니다. 부하를 기술해보았으니 성능을 기술해볼 차례입니다. 성능은 응답 시간으로 측정해볼 수 있습니다.

응답 시간으로 시스템의 성능을 기술할 때는 단일 숫자가 아니라 분포를 보아야 합니다. 보통 쓰는 것이 p95(95분위), p99(99분위), p999(99.9분위) 입니다. p95가 1.5초라면, 100개 중 5개만 1.5초를 초과한다는 의미입니다.

outlier(특이 값)를 자세히 관찰하고 싶다면 p999를 보면 되는데, 이 정도로 느린 응답을 경험한 고객은 데이터가 많다는 뜻일 것이고, 곧 로열 고객일 확률이 높기 때문에 의미가 있습니다.

시스템 성능에 대해 모니터링할 때, 다음과 같이 정의를 세워볼 수도 있습니다.

"p50(중앙값)은 200ms 이하이고 p99 가 1초 미만인 서비스 제공 시간이 99.9% 이상이어야 시스템이 정상이라고 간주한다."

부하 대응 접근 방식

부하를 대응하기 위해서는 2가지 방법이 있습니다.

  • Scaling up(수직 확장, vertical scaling): 성능이 높은 장비로 업그레이드
  • Scaling out(수평 확장, horizontal scaling): 다수의 장비로 처리하도록 업그레이드

고사양장비는 비싸기 때문에 scaling out이 더 경제적입니다. 그러나 stateful 시스템을 분산으로 관리하는 건 복잡합니다.

유지보수성

그 누구도 레거시 시스템과 작업하는 걸 좋아하지 않습니다. 내가 짠 코드를 남들이 보고싶어 하지 않는 건 슬픈 일입니다. 두고두고 보고싶게 만들 순 없을까요?

운용성: 운영의 편리함 만들기

운영팀이 시스템을 원할하게 운영할 수 있으려면, 다음을 책임질 수 있어야 합니다.

  • 시스템 상태를 모니터링하고 상태가 좋지 않다면 빠르게 복원한다.
  • 시스템 장애, 성능 저하 등의 문제의 원인을 추적한다.
  • 보안 패치를 포함해 소프트웨어와 플랫폼을 최신 상태로 유지한다.
  • 다른 시스템이 서로 어떻게 영향을 주는지 확인해 문제가 생길 수 있는 변경 사항을 선제적으로 차단한다.
  • 미래에 발생 가능한 문제를 예측해 문제가 발생하기 전에 해결한다(시스템 용량 등).
  • 배포, 설정 관리 등을 위한 도구를 마련한다.
  • 설정 변경으로 생기는 시스템의 보안을 유지 보수 한다.

이것을 위해 시스템이 제공해주어야 하는 것은 다음과 같습니다.

  • 좋은 모니터링으로 런타임동작과 시스템의 내부에 대한 가시성을 제공한다.
  • 표준 도구를 이용해 자동화와 통합을 위한 우수한 지원을 제공한다.
  • 개별 장비 의존성을 회피한다.
  • 좋은 문서와 이해하기 쉬운 운영 모델을 제공한다.
  • 만족할 만한 기본 동작을 제공하고, 필요할 때 기본값을 다시 정의할 수 있는 자유를 관리자에게 부여한다.
  • 적절하게 자기 회복이 가능할 뿐만 아니라 필요에 따라 관리자가 수동으로 시스템을 제어하는 인터페이스를 제공한다.
  • 예측 가능하게 동작하고 예기치 않은 상황을 최소화한다.

단순성: 복잡도 관리

시스템에서 복잡도를 최대한 제거해서 엔지니어가 시스템을 이해하기 쉽게 만들어야 합니다.

복잡도를 제거하기 위한 최상의 도구는 추상화입니다. 좋은 추상화는 깔끔하고 직관적인 외관 아래로 많은 세부 구현을 숨길 수 있습니다.

발전성: 변화를 쉽게 만들기

엔지니어가 시스템을 쉽게 변경할 수 있게 합니다.

시스템에 대한 요구사항은 끊임없이 변합니다. TDD, Refactoring, 애자일 기법을 통해 민첩성을 높여야 합니다.

© 2023 by 피스타치오는 맛있어. All rights reserved.