데이터 중심 애플리케이션 설계 - 1. Reliable, Scalable, and Maintainable Applications
본 글은 Designing Data-Intensive Applications 책의 내용을 개인 공부 목적을 위한 요약 및 정리한 내용입니다.
번역보다는 직역을 통해 영문책을 이해하려다 보니 단어나 문장이 다소 어색할 수 있습니다.
영어문장에 맞게 최대한 이해하려 했습니다. 가지치기($\nearrow$)로 꾸며주는 말을 따로 빼서 육하원칙, 지칭 등을 넣어 해석했습니다.
이 시리즈는 지속적으로 업데이트할 예정입니다. 먼저 한글책을 빠르게 보고, 영문책을 통해 심도있게 내용을 보완할 것입니다. 처음은 엉망일지라도 끝은 완벽할 것입니다.
오타나 오류는 알려주시길 바라며, 도움이 되길 바랍니다.
01장. Reliable, Scalable, and Maintainable Applications
- 데이터 중심 애플리케이션은 공통으로 필요로 하는 기능을 제공하는 표준 구성 요소(standard building block)로 만든다.
- 다음은 많은 애플리케이션들이 필요로 하는 것
- 데이터베이스 (database) : 애플리케이션에서 나중에 다시 데이터를 찾을 수 있게 데이터를 저장
- 캐시 (cache) : 읽기 속도 향상을 위해 값비싼 수행 결과를 기억
- 검색 색인 (search index) : 비동기 처리를 위해 다른 프로세스로 메시지 보내기
- 일괄 처리 (batch processing) : 주기적으로 대량의 누적된 데이터를 분석
- 기능적 요구사항 : 여러 방법으로 데이터를 저장하고 조회하고 검색하고 처리하게끔 허용하는 작업과 같이 해야 하는 일
- 비기능적 요구사항 : 보안, 신뢰성, 법규 준수, 확장성, 호환성, 유지보수성과 같은 일반 속성
Thinking About Data Systems
- work $\rightarrow$ (효율적으로 수행가능한) task로 분할
- 다양한 도구들은 애플리케이션 코드를 이용해 서로 연결한다.
- API(; application programming interface)는 클라이언트가 모르게 구현 세부 사항을 숨긴다.
- 소프트웨어 시스템에서 중요하게 여기는 3가지
- 신뢰성 (Reliability) : 하드웨어나 소프트웨어 결함, 심지어 인적 오류에 직면하더라도 시스템은 지속적으로 올바르게 동작해야 한다. $\nearrow$ (올바르게 동작은) 원하는 성능 수준에서 정확한 기능을 수행하는
- 확장성 (Scalability) : 시스템의 데이터 양, 트래픽 양, 복잡도가 증가하면서 이를 처리할 수 있는 적절한 방법이 있어야 한다.
- 유지보수성 (Maintainability) : 시간이 지남에 따라 여러 다양한 사람들이 시스템 상에서 작업할 것이기 때문에 모든 사용자가 시스템 상에서 생산적으로 작업할 수 있게 해야 한다.
Reliability
- 신뢰성 : 무언가 잘못되더라도 지속적으로 올바르게 동작함
- 결함 (fault) : 잘못될 수 있는 일
- 결함 : 사양에서 벗어난 시스템의 한 구성 요소
- 장애 (failure) : 사용자에게 필요한 서비스를 제공하지 못하고 시스템 전체가 멈춘 경우
- 내결함성(fault-tolerant) or 탄력성(resilient) : 결함을 예측하고 대처할 수 있는 능력
- 실제로 많은 중대한 버그는 미흡한 오류 처리에 기인한다.
- 카오스 몽키 (Chaos Monkey) : 서비스를 공급하는 인스턴스에 일부러 랜덤으로 장애를 일으킨다. 이를 통해 미래에 발생할 장애에 대해 빠르게 대응할 수 있는 시스템을 구축함 1
- 인스턴스 (instance) : 객체 (object)가 값을 갖을 경우를 말함
Hardware Faults
- 시스템 장애율을 줄이기 위한 첫 번째 대응으로 각 하드웨어 구성 요소에 중복 (redundancy)을 추가하는 것이다.
- 하지만 데이터 양과 애플리케이션의 계산 요구가 늘어나면서 더 많은 애플리케이션이 많은 수의 장비를 사용하게 되었고 이에 하두에어 결함율도 증가했다.
- AWS 플랫폼은 단일 장비 신뢰성보다 유연성(flexibility)과 탄력성(elasticity)을 우선적으로 처리하게끔 설계됐다.
- 따라서 소프트웨어 내결함성 기술을 사용하거나 하드웨어 중복성을 추가해 전체 장비의 손실을 견딜 수 있는 시스템으로 점점 옮겨가고 있다.
Human Errors
- 최고의 시스템을 위한 다양한 접근 방식
- 오류의 가능성을 최소화하는 방향으로 시스템을 설계한다.
- 사람이 가장 많이 실수하는 장소에서 사람의 실수로 장애가 발생할 수 있는 부분을 분리한다.
- 샌드박스 (sandbox) : 실제 데이터를 사용해 안전하게 살펴보고 실험할 수 있지만 실제 사용자에게는 영향이 없는 비 프로덕션
- 단위 테스트부터 전체 시스템 통합 테스트와 수동 테스트까지 모든 수준에서 철저하게 테스트한다.
- 장애 발생의 영향을 최소화하기 위해 인적 오류를 빠르고 쉽게 복구할 수 있게 한다.
- 성능 지표와 오류율 같은 상세하고 명확한 모니터링 대책을 마련한다.
Scalability
- 성능 저하를 유발하는 흔한 이유 중 하나는 부하 증가다.
- 확장성 (scalability)은 증가한 부하에 대처하는 시스템 능력을 설명하는 데 사용하는 용어
- 부하가 증가해도 좋은 성능을 유지하기 위한 전략
Describing Load
- 시스템의 현재 부하를 간결하게 기술해야 한다. 그래야 부하 성장 질문을 논의할 수 있다.
Describing Performance
- 하둡같은 일괄 처리 시스템은 보통 처리량 (throughput)에 관심을 가진다. $\nearrow$ (처리량은) 초당 처리할 수 있는 레코드 수나 일정 크기의 데이터 집합으로 작업을 수행할 때 걸리는 전체 시간
- 온라인 시스템에서 더 중요한 사항은 서비스 응답 시간 (response time)이다. $\nearrow$ (응답 시간은) 클라이언트가 요청을 보내고 응답을 받는 사이의 시간
- 응답 시간 (response time) : 클라이언트 관점에서 본 시간. 요청을 처리하는 실제 시간(서비스 시간) 외에도 네트워크 지연과 큐 지연도 포함된다.
- 지연 시간 (latency) : 요청이 처리되길 기다리는 시간으로, 서비스를 기다리며 휴지(latent) 상태인 시간
- 클라이언트가 몇 번이고 반복해서 동일한 요청을 하더라도 매번 응답 시간이 다르기 때문에 응답 시간을 분포로 생각해야 한다.
- 백분위는 서비스 수준 목표 (SLO; service level objective)와 서비스 수준 협약서 (SLA; service level agreement)에 자주 사용한다.
Approaches for Coping with Load
- 수직 확장 (vertical scaling) : 좀 더 강력한 장비로 이동
- 수평 확장 (horizontal scaling) : 다수의 낮은 사양 장비에 부하를 분산
- 비공유 아키텍처 (sharing-nothing architecture) : 다수의 장비에 부하를 분산하는 아키텍처
- 일부 시스템은 탄력적이다.
- 탄력적 (elastic) : 부하 증가를 감지하면 컴퓨팅 자원을 자동으로 추가할 수 있다.
- 특정 애플리케이션에 적합한 확장성을 갖춘 아키텍처는 주요 동작이 무엇이고 잘 하지 않는 동작이 무엇인지에 대한 가정을 바탕으로 구축한다. $\nearrow$ 가정은 곧 매개변수가 된다.
Maintainability
- 유지보수에는 버그 수정, 시스템 운영 유지, 장애 조사, 새로운 플랫폼 적응, 새 사용 사례를 위한 변경, 기술 채무 상환, 새로운 기능 추가 등이 있다.
- 소프트웨어 시스템 설계의 3가지 원칙
- 운용성 (operability) : 운영팀이 시스템을 원할하게 운영할 수 있게 쉽게 만들어야 한다.
- 단순성 (simplicity) : 시스템에서 복잡도를 최대한 제거해 새로운 엔지니어가 시스템을 이해하기 쉽게 만든다.
- 발전성 (evolvability) : 엔지니어가 이후에 시스템을 쉽게 변경할 수 있게 한다. 이 속성은 유연성(extensibility), 수정 가능성(modifiability), 적응성(plasticity)로 알려져 있다.
Operability: Making Life Easy for Operations
- 운영 중 일부 측면은 자동화할 수 있고 또 자동화해야 한다.
- 시스템이 지속해서 원활하게 작동하기 위해 운영팀의 작업 목록들
- 시스템 상태를 모니터링하고 상태가 좋지 않다면 빠르게 서비스를 복원
- 시스템 장애, 성능 저하 등의 문제의 원인을 추적
- 보안 패치를 포함해 소프트웨어와 플랫폼을 최신 상태로 유지
- 다른 시스템이 서로 어떻게 영향을 주는지 확인해 문제가 생길 수 있는 변경 사항을 손상을 입히기 전에 차단
- 미래에 발생 가능한 문제를 예측해 문제가 발생하기 전에 해결
- 배포, 설정 관리 등을 위한 모범 사례와 도구를 마련
- 애플리케이션을 특정 플랫폼에서 다른 플랫폼으로 이동하는 등 복잡한 유지보수 태스크를 수행
- 설정 변경을 생기는 시스템 보안 유지보수
- 예측 가능한 운영과 안정적인 서비스 환경을 유지하기 위한 절차 강의
- 개인 인사 이동에도 시스템에 대한 조직의 지식을 보존함
- 좋은 운연성은 동일하게 반복되는 태스크를 쉽게 수행하게끔 만들어 운영팀이 고부가가치 활동에 노력을 집중한다는 의미
Simplicity: Managing Complexity
- 복잡도 (complexity)는 다양한 증상으로 나타난다.
- 상태 공간의 급증, 모듈 간 강한 커플링, 복잡한 의존성, 일관성 없는 명명과 용어, 성능 문제 해결을 목표로 한 해킹, 임시방편으로 문제를 해결한 특수 사례 등
- 우발적 복잡도 (accidental complexity) : 소프트웨어가 풀어야할 (사용자가 보이는) 문제에 내재하지 않고 구현에서만 발생
- 우발적 복잡도를 제거하기 위한 최상의 도구는 추상화다.
- 좋은 추상화는 깔끔하고 직관적인 외관 아래로 많은 세부 구현을 숨길 수 있다.
Evolvability: Making Change Easy
- 시스템의 요구사항이 끊임없이 변할 가능성이 훨씬 크다.
- 요구사항은, 새로운 사실을 배우고, 미처 예기치 않은 사용 사례가 나타나고, 비즈니스 우선순위가 바뀌고, 사용자가 새로운 기능을 요청하고, 새로운 플랫폼이 기존 플랫폼을 대체하고, 법적 또는 규제 요구사항이 변경되고, 시스템의 성장으로 인한 아키텍처 변화 등이다.
- 애자일 (agile) 작업 패턴은 변화에 적응하기 위한 프레임워크를 제공한다.
댓글남기기