728x90

요즘 대부분의 애플리케이션은 계산중심(CPU 성능)이 아닌 데이터 중심(데이터 복잡도, 변화 속도 등)이다.

즉, CPU성능은 더이상 애플리케이션의 동작을 제한하는 요소가 아니며, 이제는 데이터의 양, 복잡도, 변화속도 그리고 이를 처리할 수 있는 방안과 기술이다. 

 

이러한 데이터 중심 애플리케이션은 기본적으로 "데이터베이스. 캐시, 검색 색인, 스트림처리, 일괄처리" 등을 필요로 한다.

이들을 데이터 시스템이라고 묶으며, 이러한 데이터 시스템의 활용에 대한 고민과 구조 설계는 애플리케이션 서비스 개발자들 또한 고민해야 하는 사항이다.

(가령 클라이언트에서 A라는 정보에 대한 조회를 요청했을때, 실제 서버에서는 해당 api를 받고난 이후에, 캐시를 확인하고 데이터가 있으면 반환, 없으면 메인DB를 조회 하는 등의 다양한 데이터 시스템을 거친다.)

이에따라 상황에 맞게 다양한 도구들을 결합하는 방안에 대해서도 고민해야 한다.

 

데이터시스템에 대한 생각

데이터를 다루는 다양한 기술들이 최근에 만들어지고 있으며, 점차 그 기능에 있어서 경계가 흐려지고 있다.

책에서는 대표적으로 redis와 kafka를 언급하고 있다.
redis와 kafka 둘다 큰 범위에서는 끊임없이 들어오는 데이터를 누락없이 지정한 순서에 맞게 처리하기 위한 메시지 큐이다.
그러가 redis는 일시적으로 데이터를 처리하고, kafka는 데이터를 영구적으로 저장하는 데이터베이스처럼 영구성을 보장한다.
즉 같은 역할을 하면서도 다른 역할을 하는 데이터 처리 기술과 점점 영역 구분이 흐려지면서 필요에 따라 여러 기능을 하는 새로운 데이터 처리 기술들이 등장하고 있다.

또한 복잡성이 높아지면서 단일 도구로 전체 데이터 처리를 감당할 수 없으며, 각 도구들을 결합하여 데이터 처리를 구현하게 된다.

즉 개발자는 단순히 데이터 처리를 위한 애플리케이션을 개발하는 것에서 넘어서서 다양한 데이터 처리 도구들을 적절하게 활용하는 방안을 고민하며 데이터 시스템을 설계하는 설계자 역할을 해야한다. 

 

이러한 시스템에서 가장 중요한 세가지 관심사가 있다. 신뢰성, 확장성, 유지 보수성이다.

 

신뢰성

소프트웨어 시스템에서 신뢰성은 애플리케이션이 "무언가 잘못되더라도 지속적으로 올바르게 동작함"을 의미한다.

애플리케이션은 사용자가 기대한 기능을 수행하며, 시스템 성능이 예상된 부하와 데이터 양에서 필수적인 사용 사례를 충분히 만족하고, 허가되지 않는 접근과 오남용을 방지한다는 기대치를 어느정도 충족할 때 신뢰성이 있다고 볼 수 있다.

 

즉 신뢰성은 시스템의 결함과 관련된 부분을 얼마나 잘 예측하고 대비하여 서비스를 유저들에게 문제없이 제공해주는가이다.

 

여기서 결함은 잘못될 수 있는 일을 뜻하며, 이를 대처할 수 있는 시스템을 내결함성 혹은 탄력성을 지녔다고 한다. 실제로 내결함성은 100프로를 달성할 수 없다.(책에서 언급되는 최악의 상황 즉, 블랙홀이 지구상의 모든 서버를 삼키는 경우에도 잘못되지 않을 내결함성은 불가하다)

 

또한 결함과 장애는 다르다. 결함은 사양에서 벗어난 시스템의 한 구성요소로 정의되나, 장애는 사용자에게 필요한 서비스를 제공하지 못하고 시스템 전체가 멈춘 경우다. 즉 결함확률을 0으로 줄이는 것은 불가하나, 장애가 발생하지 않게끔 최대한 구조를 설계해야한다.

 

이는 즉 신뢰할 수 없는 여러 부품(결함확률이 0일 수 없는)으로 신뢰할수있는 시스템을 구축(장애가 최대한 발생하지 않게)해야하는 것이다.

 

실제로 넷플릭스의 사례로, 고의적으로 결함을 유도함으로써 내결함성 시스템을 지속적으로 훈련하고 테스트하는 카오스몽키 방식이 있다.

 

하드웨어 결함

하드웨어 결함에 의한 문제를 예방하기 위해서는 중복을 추가 하는 방법 즉, 하드웨어를 여러개 두는 것이 있다. 

디스크는 RAID구성으로, 서버는 이중전원 디바이스와 핫 스왑 가능한 CPU를, 데이터 센터는 건전지와 예비 전원용 디젤 발전기를 갖출 수 있다. 

 

그러나 데이터의 양과 애플리케이션의 계산요구가 늘어나는 등 소프트웨어적인 복잡도와 요구가 증가하면서 하드웨어 중복 구성으로는 신뢰성을 보장하는 것에 한계가 왔다. 

이에 따라 소프트웨어 내결함성 기술과 하드웨어 중복으로 시스템을 설계하고 있다.

 

소프트웨어 오류

보통 하드웨어 결함은 서로 독립적이다.  그러나 소프트웨어 결함은 노드간 상관관계가 있으며, 이에 따라 해결하고 예측하기가 더 까다롭다. 

 

대표적으로 CPU, 메모리 등 공유자원을 과도하게 사용하는 일부 프로세스가 발생한 경우, 한 구성 요소의 작은 결함이 다른 구성요소의 결함을 야기하여 더 많은 결함을 발생시키는 연쇄 장애 등이 있다.

 

하드웨어 결함은 보통 중복구성으로 해결하나, 소프트웨어 오류는 특정 해결책이 없다. 빈틈없이 테스트하거나 프로세스를 격리하고, 모니터링 등의 작은 여러 일들이 필요하다. 

 

인적오류

이를 막기 위해서는 결국 시스템을 잘 설계해야 한다. 오류의 가능성을 최소화하거나, 장애 가능성을 미리 예측하여 시스템을 분리하고 혹여나 장애 발생 시, 빠르고 쉽게 복구할 수 있는 등의 설계가 필요하다. 

혹은 꾸준히 테스트를 하거나 모니터링을 하고, 인적 교육을 실행하는 방법이 있다.

 

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

일상적인 애플리케이션의 안정적인 작동에 매우 중요한 것이 바로 신뢰성이다. 

이는 실제로 비즈니스의 생산성 저하를 불러올 수도 있기 때문이다.

 

확장성

증가한 부하에 대처하기 위해 시스템이 충분한 성능을 지녔는지이다. 

즉 시스템이 현재 상황에서 안정적으로 동작하지만, 미래에 다른 상황(이 때는 전반적으로 사용자가 늘어난 경우)에서도 안정적으로 동작하는 지를 보장해야 한다는 것이다.

 

부하기술하기

확장성을 위해서는 우선 현재 시스템의 부하를 간결하게 기술할 수 있어야 한다. 이를 측정하기 위한 지표를 부하 매개변수라고 한다. 

책에서는 트위터를 예로 들고 있다. 트위터의 확장성 문제는 트윗양이 아니라 바로 팬아웃 때문이었다. 즉 개별 사용자는 많은 사람을 팔로우하고, 많은 사람이 개별사용자를 팔로우 하면서 발생하는 성능 부하가 이슈였다.
이들의 쓰기 작업과 읽기 작업 시에 부하를 다루는 것이 중요했고, 실제로 쓰기보다는 읽기 작업 요청이 더 많으므로, 
쓰기 작업에서 더 많은일을하고 읽기 작업에서 적은 일을 하도록 시스템을 설계했다.

그러나 결국 각 개인의 팔로워 수마다 실질적인 부하원인이 다르고 이를 결정짓는 팔로우수가 부하 매개 변수가 되며, 
결국 혼합형을 택했다.

성능기술하기

또한 현재 시스템의 성능 또한 기술 할수 있어야 하는데, 대표적으로 처리량(하둡과 같은 일괄 처리 시스템은 초당 처리할 수 잇는 레코드수나 일정 크기의 데이터집합으로 작업을 수행할때 걸리는 전체 시간)에 관심을 가지며, 온라인 시스템에서는 서비스 응답시간 즉 클라이언트가 요청을 보내고 응답을 받는 사이의 시간을 중요하게 여긴다. 

지연시간과 응답시간은 차이가 있다. 응답 시간은 클라이언트 관점으로 요청을 처리하는 실제 시간 외에도 네트워크 지연과 큐지연도 포함한다. 지연시간은 서버에서 요청을 받은 후 처리되길 기다리는 시간이다. 

응답시간은 같은 요청이라도 항상 다르므로 단일값이 아니라 분포로 표현한다. 

이 때 서비스 평균 응답시간을 구하기 위해서는 실질적인 평균을 구하는 것보다 백분위의 중앙값을 구하는 것이 더 실제 유저의 경험을 반영하기에 좋다. 일반적인 산술평균은 얼마나 많은 사용자가 실제로 지연을 경험했는지 알려주지 않기 때문이다.

 

여기서 사용자 실제 경험에 중요한 것은 꼬리 지연시간이란 개념이다. 상위 백분위 응답시간으로 실제 사용자 표본의 95분위, 99분위 , 99.9분위의 응답시간을 살펴보는 것이다. 가령 95분위를 기준으로 한다치면, 95분위 응답시간이 1.5초이면 95프로가 1.5초 미만의 응답시간이 걸리고, 나머지 5%가 1.5초보다 응답시간이 더 걸린다는 의미이다. 아마존의 경우는 99.9분위로 서비스 응답시간 요구사항을 기술하여 까다롭게 응답시간을 관리한다. 

 

부하 대응 접근 방식

응답지연을 최소화 하기 위해서 서버의 부하에 대응해야 하는데, 이와 관련해서 크게 용량확장(수직적)/규모확장(수평적)/다수의 낮은 사양장비에 부하를 분산(비공유 아키텍쳐)하는 이 세가지로 구분할 수 있다.

이와 관련해 최근 분산 데이터 시스템이 가장 주목 받고 있다.

(기존에는 용량확장을 기반으로 하나의 노드에 데이터베이스를 돌리는 것이 대부분이었다.)

분산 설치하고 관리하는 것에 대한 복잡도가 조금은 낮아지고 추상화가 좋아지면서 분산 시스템이 기본 아키텍쳐로 잡아가게 되는 것이다. 

 

유지보수성

유지보수에 드는 비용도 크기 때문에, 이러한 비용을 최소화 하기 위해 소프트웨어 설계부터 신경써야 한다. 

운용성

운영의 편리함 만들기, 즉 자동화하기. "좋은 소프트웨어라도 나쁘게 운영할 경우 작동을 신뢰할 수 없다." 즉 운영 중 일부 측면은 자동화하여 효율적인 운영을 꾀해야한다. 

이와 관련해서는 기본적으로 모니터링, 이를 기반으로 한 장애 원인 추적등이 중요하다. 

단순성

복잡도 관리, 이를 위해 중요한 도구 중 하나는 추상화이다. 좋은 추상화는 깔끔하고 직관적인 외관 아래로 많은 세부 구현을 숨길 수 있다. 또한 재사용성을 높여준다. 

복잡도가 높으면 시스템 유지보수가 어려워질 수 있으며 이에 따라 예산과 일정이 초과될 수 있다. 

발전성

변화하기 쉽게 만들기. 즉 시스템의 요구사항이 끊임없이 변화할 수 있으므로 이에 유연하게 대응할 수 있도록 설계해야한다. 

여기서 자주 언급되는 것이 애자일 작업 패턴과 이에 따른 테스트 주도개발과 리팩토링이다. 

 

 

728x90

+ Recent posts