스터디를 위한 자료로 "데이터 중심 애플리케이션 설계" 책을 읽고 정리한 것이다.
Q. 시스템(현재 서비스 되고 있는)에서 가장 크게 부하를 주는 요소는 무엇일까?
Q. 소프트웨어의 3가지 요소(신뢰성, 확장성, 유지보수성)을 고려하고 있는가? (고려 했는가?)
Q. 내부 시스템 요소(데이터베이스 등)를 잘 이해하고 사용하고 있는가?
시스템은 기술 숙련도, 조직 구성과 같은 외부적인 요인과 시스템 간의 의존성, 응답 시간과 같은 내부적인 요인들이 설계에 많은 영향을 끼친다. (현실은 항상 Clear하지 않으므로)
그러나 이런 상황에서도 시스템은 항상 신뢰성, 확장성, 유지보수성에 대한 기준을 가지고 고려되어야 한다. (그렇게 하려고 최소한 노력해야 한다.)
때문에 소프트웨어 시스템에서 중요하게 여기는 3가지 관점(신뢰성, 확장성, 유지보수성) 즉, 엔지니어링 관점에 대한 의미를 알아보려고 한다..
신뢰성 (Reliablity)
내부적인 문제가 발생하더라도 시스템은 정상적*으로 동작해야 한다.
*시스템에 정의한 수준만큼 동작하는 것 (정의한 것 이하로 동작한다면 비정상 동작)
즉, 운영 도중에 결함(Fault)이 발생하더라도 원하는 만큼 동작해야 한다.
(내부 결함이 발생할 때, 예측한 Flow로 동작하면 해당 시스템 -> 내결함성(Fault tolerenct) 또는 탄력성(Resilient)를 지닌 시스템)
# 신뢰성 있는 시스템에서 결함과 장애의 단어의 의미는 다르다.
결함 (Fault) |
장애 (Failure) |
시스템 Spec에서 벗어난 것 |
사용자에게 서비스를 제공하지 못하는 것 |
궁극적으로 장애가 0이 되어야하겠지만 현실적으로는 거의 불가능하다. 때문에 결함으로 인한 장애가 발생하지 않도록 하는 것이 신뢰성 있는 시스템 구축의 가장 중요한 점이다.
하드웨어 결함 (Hardware Fault)
데이터 센터에서 잘못된 하드웨어 사용으로 인한 결함이 늘상 발생한다. (그렇지 않을 것 같지만...)
# 시스템 장애율을 줄이는 방법 (완전히 방지는 안된다.)
Disk |
Server |
Data Center |
RAID |
Hot Swap CPU |
예비 발전기 |
# 장비가 늘어나면서 하드웨어 결함률도 높아지고 있다. -> 소프트웨어 내결함성으로 해결하려는 방향..
소프트웨어 결함 (Software Fault)
디스크 장애*와 시스템 내부 오류(Systematic Error)
*하드웨어와 독립적인 것 같지만 서버의 랙(Rack)에서는 조금의 영향이 있을 수 있다.)
특히, 시스템 내부 오류는 예상하기 쉽지 않고 하드웨어 결함보다 더 많이 발생한다.
- 잘못된 입력 (aka 버그)
- 공유 자원 부족 (특정 프로세스에서 과도하게 공유 자원을 사용하였을 경우)
- 잘못된 응답 또는 응답 없음
- 연쇄 장애 (Cascading Failure)
시스템 내부적인 리소스 사용 고려, 프로세스 격리(Isolation), 테스트 등의 방법으로 덜 발생하게 해야 한다. (+ 내부 경고 시스템)
인적 오류 (Human Error)
운영자의 설정 오류가 하드웨어 결함으로 인한 장애보다 더 많이 발생한다.
버그가 자주 발생하는 시스템은 직접적으로 회사의 매출에 타격을 줄 수 있다. 때문에 이후에 해결하기 위해 비용이 드는 것보다 신뢰성있는 시스템을 구축하기 위해 소요되는 비용이 더 낫다.
- 오류 가능성을 최소화 할 수 있는 시스템 설계
- 철저한 테스트
- 빠른 Roll-back 시스템
- 모니터링 제공
- 조직 교육
확장성 (Scalability)
- 현재 안정적으로 동작하는 시스템이 미래에도 안정적으로 동작한다는 보장은 없다. (부하 증가 등등)
- 일차원적인 의미가 아니다 -> "시스템이 커지면 어떻게 대처할 것인가" 에 대한 종합적인 관점으로 고려해야 한다.
부하 기술
부하를 발생시키는 매개 변수*를 나열해야(찾아야) 한다.
* 웹 서버의 초당 요청 수, 데이터베이스의 읽기 대 쓰기 비율, 캐시 적중률 등
# 부하 매개 변수에 따라 시스템 설계가 달라진다.
성능 기술
부가 증가 할 때 발생할 수 있는 일을 예측 한다.
- 현 리소스를 유지할 때, 부하가 발생하면 기존 성능에 어떤 영향을 미칠 것인가? (성능 유지가 될 것 인가?)
- 부하가 발생 할 때 기존 성능을 유지하기 위해서는 리소스를 얼마나 투입해야 할 것인가? (성능 유지를 하기 위해서는?)
1) 서비스 성능 측정 예시
- 평균 응답 시간 (일반적인 방법)
- 보다 나은 방법 : 백분위 (Percentile) + 중앙값(Median)
- 특이값(Outlier) 확인
확장성 논의
- 일반적인 접근 방식 : Scaling-Up (Vertical Scaling) or Scaling-out (Horizontal Scaling)
- 하지만 현실적인 접근 방안을 고려해야 한다. (고사양 시스템은 비용이 비싸다)
1) Stateful 서비스 배포
Stateless 서비스 배포에 비해 추가적인 복잡도가 높다 -> 통념상 고가용성 요구 사항이 있을 때까지 단일 노드에 데이터베이스 유지하는 편이다.
2) 범용(General) 확장 아키텍처
해당 아키텍처는 존재하지 않는다 -> 대부분의 아키텍처는 애플리케이션에 특화되어 있다.
# 아키텍처 결정 요소는 아래와 같다.
- Read Capacity
- Write Capacity
- Data Size
- Data Complexity
- Response time
- Access Pattern
...
유지보수*성 (Maintainability)
*시스템 운영, 기능 추가, 버그 수정 등등
- 대부분의 사람들은 레거시(Legacy) 시스템 유지보수를 좋아하지 않는다.
- 소프트웨어 비용의 대부분은 초기 개발이 아닌 유지보수에 들어간다.
소프트웨어 설계 원칙
유연하게 유지 보수를 할 수 있는 시스템을 설계
1) 운용성(Operability) : 시스템을 원활하게 운영할 수 있도록 해야 한다.
좋은 소프트웨어라도 나쁘게 운영할 경우 작동을 신뢰 할 수 없다. -> 자동화 할 수 있는 것은 자동화 해야 한다. (제대로 동작하는지 확인하는 것은 사람의 몫)
그렇기에 시스템의 운영을 위해서는 좋은 운영팀과 그에 따른 좋은 운영성이 필요하다.
좋은 운영팀 |
좋은 운영성 |
- 시스템 모니터링 - 시스템 장애, 성능 저하 등의 문제 원인 추적 - 소프트웨어와 플랫폼을 최신 상태 (보안 패치 등) - 문제 예측 (Capacity와 같은 향후의 문제들) - 배포, 설정 관리 등을 위한 모범 사례와 도구 준비 ... |
- 좋은 모니터링으로 시스템에 대한 가시성 제공 - 좋은 문서 제공 - 관리자 부여 (설정 변경이 가능한 권한) - 불필요한 상황을 최소화 ... |
2) 단순성(Simplicity) : 시스템 복잡도*를 최대한 낮춰야 한다.
* 강한 커플링(Tight Coupling), 의존성, Naming 등등
프로젝트가 커질 수록 시스템은 점점 복잡해 진다. -> 복잡도로 인해 시스템 유지보수가 어려울 수록 예산과 일정이 초과할 수 있다.
따라서 복잡성을 줄여(즉, 단순하게 만들어) 시스템의 유지 보수성을 높여야 한다.
시스템의 추상화 (단순한 시스템) -> 비슷한 기능을 여러 번 재구현하는 것보다 재사용하는 것이 효율직이며 품질 향상이 될 수 있다.
3) 발전성(Evolvability) : 시스템을 쉽게 수정할 수 있도록 해야 한다.
- 계속 예기치 않은 사례가 등장한다.
- 새로운 플랫폼이 등장한다.
- ...
요구 사항에 대한 발빠른 대응 -> 조직 측면에서 애자일(Agile) 프로세스 적용 (TDD + Refactoring 등등)
# 간단하고 이해하기 쉬운 시스템은 수정하기 쉽다.
'IT > Architecture' 카테고리의 다른 글
SOLID Principle (2) | 2019.11.17 |
---|---|
Software Requirement - Part 2 (0) | 2019.10.27 |
Software Requirement - Part 1 (0) | 2019.10.20 |
댓글