'CH.01 신뢰할 수 있고(신뢰성) 확장 가능하며(확장성) 유지보수하기 쉬운(유지보수성) 애플리케이션'은 이 책이 다루는 주제인 '데이터 중심 애플리케이션 설계'의 전반적인 원칙에 대해 다루는 장이다.
자, 그럼 하나씩 각 요소들을 살펴보기 전 데이터 중심 애플리케이션을 이루는 표준 구성 요소에 대해 살펴보자.
이러한 용어들이 뻔한 말처럼 들린다면, 데이터 시스템이 그만큼 성공적으로 추상화됐음을 의미한다. 즉, 데이터엔지니어는 애플리케이션의 요구사항을 충족하기 위해 여러 추상화된 도구들을 결합하여 사용할 수 있어야 한다.
데이터 시스템이나 서비스를 설계할 때는, 주로 세 가지 관점을 중요하게 여긴다.
1. 신뢰성(Reliability)
- 하드웨어나 소프트웨어 결함, 인적오류 같은 fault에 직면하더라도 시스템은 지속적으로 올바르게 동작해야한다.(fault tolerance)
신뢰성에서 다루는 fault는 해결책이 있는 fault에 한정한다. ex) 보안의 경우에는 공격자가 민감한 데이터에 접근권한을 가지는 순간, 이를 되돌릴 방법은 없다.
하드웨어 결함
하드웨어의 평균 장애 시간은 약 10~50년이다. 따라서 10,000개의 디스크로 구성된 클러스터는 평균적으로 하루에 한 개의 디스크가 죽을 수 있다.
이를 위한 해결 방법으로는 디스크를 RAID 구성으로 설치할 수 있고, 서버는 이중 전원 디바이스와 핫 스왑이 가능한 CPU로 구성, 데이터 센터는 예비 전원용 발전기를 갖출 수 있다.
소프트웨어 오류
보통 하드웨어 결함은 무작위적이고 서로 독립적이지만, 소프트웨어 결함(시스템 내 체계적 오류)은 예상하기가 더 어렵고, 노드 간 상관관계때문에 전방위적으로 발생할 여지가 있다.
이러한 체계적 오류는 신속한 해결책이 없다. 빈틈없는 테스트, 프로세스 격리, 죽은 프로세스의 재시작 허용, 시스템 동작의 측정, 모니터링, 분석하기와 같은 형식들이 문제해결에 도움을 줄 수 있다.
인적 오류
한 연구에 따르면 서비스의 중단 원인 중 75 ~ 90%가 인적 오류에 의해 만들어진다. 이를 해결하기 위해선 다양한 접근 방식을 결합한다.
2. 확장성(Scalability)
- 시스템의 데이터 양, 트래픽 양, 복잡도가 증가하더라도 이를 처리할 수 있는 적절한 방법이 있어야 한다.
시스템이 현재 안정적으로 동작한다고 해서 미래에도 안정적으로 동작한다고 보장할 수 없다. 가장 흔한 원인은 부하증가다. 하지만, 확장성을 논한다는 것은 단순히 확장 가능하다, 확장성이 없다와 같은 일차원적인 의미가 아니다. "시스템이 특정 방식이 커지면 이에 대처하기 위한 선택은 무엇인가?"(기술 스택을 의미하는 것으로 보임)와 "추가 부하를 다루기 위해 계산 자원을 어떻게 투입할까?"와 같은 질문을 고려해야 한다.
부하 기술하기
시스템 확장에서 고려해야할 것은 부하를 올바르고 간결하게 기술해야 한다는 것이다. 부하는 부하 매개변수라고 부르는 몇 개의 숫자로 나타낼 수 있다. ex) 웹 서버의 초당 요청 수, 데이터베이스의 읽기 대 쓰기 비율, 대화방의 동시 활성 사용자, 캐시 적중률 등
트위터의 예시
트위터의 주요 부하 원인은 '팬 아웃'때문이다. 즉, 개별 사용자는 많은 사람을 팔로우 하고 많은 사람이 개별 사용자를 팔로우 한다.이 동작을 구현하는 방식은 크게 두가지로 분류할 수 있다.
SELECT tweet.*, users.* FROM tweets
JOIN users ON tweets.sender_id = users.id
JOIN follows ON follows.followee_id = users.id
WHERE follows.follower_id = current_user
트위터는 1의 방식에서 2의 방식으로 전환했다. 평균적으로 트윗 게시 요청량이 홈 타임라인 읽기 요청량에 비해 수백 배 적기 때문이다. 즉, 쓰기 시점에 더 많은 일을 하고, 읽기 시점에 적은 일을 하는 것이 바람직하다.
이후에는 1과 2를 선택적으로 적용하는 혼합형으로 바뀌었다. 팔로워 수가 매우 많은 소수 사용자(유명인)은 팬 아웃에서 제외하고 1의 방식을 적용한다. 왜나하면 특정 유저는 팔로워가 3천만 명이 넘는 경우가 있다. 이 경우, 한 번의 트윗 요청이 3천만 건 이상의 쓰기 요청이 된다는 것을 의미하기 때문에 1의 방식이 더 알맞다.
즉, 트위터의 사례에서는 사용자당 팔로워의 분포가 확장성을 논의할 때 핵심 부하 매개변수가 될 수 있다.
3. 유지보수성(Maintainability)
- 시간이 지나더라도 모든 사용자가 시스템 상에서 생산적으로 작업할 수 있게 해야 한다.
유지보수에는 버그 수정, 시스템 운영 유지, 장애 조사, 새로운 플랫폼 적응, 새 사용 사례를 위한 변경, 기술 채무 상환, 새로운 기능 추가 등이 있다.
유지보수를 편하게 하기 위해 소프트웨어 설계시 고려해야 할 점은 다음과 같다.
운용성 : 운영팀이 시스템을 원할하게 운영할 수 있게 쉽게 만든다.
단순성 : 시스템의 복잡도를 최대한 제거해 새로운 엔지니어가 시스템을 쉽게 이해할 수 있도록 만든다.
발전성 : 엔지니어가 이후에 시스템을 쉽게 변경할 수 있게 만든다.