IT도서요약

👍데이터 중심 어플리케이션- 1장

DEDS 2025. 3. 27. 17:16
728x90

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

오늘날 많은 애플리케이션은 연산 중심이기보다 데이터 중심입니다. 
순수한 CPU 성능이 제한 요소인 경우는 드물고 오히려 문제는 데이터의 양, 복잡성, 그리고 변화 속도입니다.

 

 어플리케이션에 필요한  표준적인 구성요소 필 기능

• 데이터를 저장하고 나중에 자신이나 다른 애플리케이션이 다시 찾을 수 있도록 하기 (데이터베이스)
• 시간이 오래 걸리는 연산 결과를 기억하여 읽기 속도를 높이기 (캐시)
• 키워드로 데이터를 검색하거나 다양한 방식으로 필터링할 수 있게 하기 (검색 인덱스)
• 메시지를 다른 프로세스에 보내 비동기적으로 처리하기 (스트림 처리)
• 많은 양의 누적 데이터를 주기적으로 처리하기 (배치 처리)

이런 데이터 시스템들은 너무 잘 추상화되어 있어서 깊이 생각하지 않고 사용합니다.
DBMS를 자주 사용하지만 직접 만들 생각을 하지는 않죠!!!)

 

데이터 시스템에 대한 새로운 관점

 

우리는 일반적으로 데이터베이스, 큐, 캐시 등을 서로 매우 다른 도구들로 생각합니다. 물론 겉보기에는 유사해 보일 수 있습니다. 예를 들어 데이터베이스와 메시지 큐 모두 일정 시간 동안 데이터를 저장한다는 점에서는 비슷합니다

  • 전통적인 범주 경계가 모호해짐: Redis는 데이터 저장소이자 메시지 큐로도 사용되고, Apache Kafka는 메시지 큐지만 데이터베이스 수준의 내구성(durability)을 제공합니다. 
  • 복잡한 요구사항으로 여러 도구 사용: 애플리케이션 수준의 캐시 계층(예: Memcached)이나 별도의 전문 검색 서버(예: Elasticsearch 또는 Solr)를 사용하는 경우, 이 캐시나 검색 인덱스를 메인 데이터베이스와 동기화하는 책임은 애플리케이션 코드에 있음 

 

데이터 시스템을 바라보는 관점

우리가 추구하는 핵심 목표:  신뢰성(Reliability), 확장성(Scalability), 유지보수성(Maintainability)

  • 신뢰성 (Reliability): 시스템은 장애(하드웨어, 소프트웨어, 인간 실수 등)가 발생하더라도 올바른 기능을 원하는
    성능 수준에서 계속해서 수행해야 합니다.
  • 확장성 (Scalability): 데이터 량, 트래픽, 시스템 복잡도가 증가하더라도 이에 대응할 수 있어야 합니다.
  • 유지보수성 (Maintainability): 시간이 지남에 따라 다양한 사람들이 시스템을 운영하고 개선할 수 있어야 하며,
    새로운 요구 사항에도 잘 적응할 수 있어야 합니다.

신뢰성(Reliability)

무엇을 신뢰한다는 의미는  직관적으로 모두 알고 있습니다. 소프트웨어에 대해서는 일반적으로 기대하는 것은

정상적으로 동작한다는 의미로 다음과 같습니다.

  • 사용자가 기대하는 기능을 제대로 수행한다.
  • 사용자의 실수나 예상치 못한 사용 방식에도 견딘다.
  • 예상된 부하와 데이터량에서도 충분히 성능을 발휘한다.
  • 무단 접근이나 악용을 방지한다.

신뢰성의   문제가 발생해도 계속해서 정상적으로 작동하는 것 으로 정의할 수 있습니다.

 

  내결함성(Fault-tolerant)/탄력성(resilient) 시스템: 결함을 예상하고 잘 대응하는 시스템

  결함(Fault) vs 장애(Failure)  차이

  결함(Fault)

  문제를 일으키는 원인, 시스템 구성 요소 중 하나가 사양에서 벗어나는 동작을 하는 것

  결함 발생 확률을 0으로 만드는 것은 불가능하기 때문에, 보통은 결함이 장애로 이어지지 않도록

  결함 허용 메커니즘을 설계하는 것이 중요

  장애(Failure): 전체 시스템이 사용자에게 필요한 서비스를 제공하지 못하는 상태


하드웨어 결함

 

대응방법: 하드웨어 구성 요소의 중복(redundancy)을 추가하는 것

  • 디스크는 RAID로 구성
  • 서버는 이중 전원 공급 장치와 핫스왑 가능한 CPU를 장착
  • 데이터센터는 배터리와 디젤 발전기를 준비

과거에는 이러한 하드웨어 수준의 중복만으로도 대부분의 애플리케이션에 충분했습니다.

최근에는 전체 머신의 손실도 견딜 수 있는 소프트웨어 기반의 내결함 시스템을 추구하는 추세입니다. 이런 시스템은 운영상의 이점도 있습니다. 예를 들어, 단일 서버 시스템은 보안 패치를 위해 재부팅 시 전체 서비스가 중단되어야 하지만, 내결함 시스템은 노드별 순차 패치(rolling upgrade)가 가능하여 전체 시스템의 다운타임 없이 운영할 수 있습니다.


소프트웨어 오류

 

한 대의 서버에서 디스크가 고장났다고 해서 다른 서버의 디스크도 고장날 가능성이 높다고 보진 않습니다.
여러 하드웨어 컴포넌트가 동시에 실패하는 일은 드뭅니다.

시스템 내에서 발생하는 시스템 오류(systematic error)는 예측하기 어렵고, 노드 전체에 걸쳐 영향을 미치기 때문에
단일 하드웨어 결함보다 훨씬 더 많은 시스템 장애를 유발합니다. 

예시)

  • 특정 잘못된 입력 값이 주어졌을 때, 모든 애플리케이션 서버 인스턴스를 동시에 크래시시키는 소프트웨어 버그
      → 예: 2012년 6월 30일, 윤초(leap second)로 인해 리눅스 커널의 버그가 발생하며 많은 앱이 동시에 멈춘 사건
  • 공유 자원(CPU, 메모리, 디스크, 네트워크 대역폭 등)을 과도하게 사용하는 프로세스
  • 의존하고 있는 외부 서비스가 느려지거나, 응답이 없거나, 오염된 데이터를 반환하는 경우
  • 연쇄 장애(cascading failures): 하나의 컴포넌트에서 발생한 작은 오류가 다른 컴포넌트에 영향을 주고,그것이 다시 다른 장애를 유발하는 도미노 현상

시스템 오류에 대한 즉각적인 해결책은 없습니다. 다음과 같은 실천이 필요합니다.

  • 시스템 내의 가정 및 상호작용을 신중하게 설계
  • 철저한 테스트 수행
  • 프로세스 격리
  • 프로세스가 실패하면 재시작 가능하게 설계
  • 운영 중인 시스템을 모니터링 및 분석

휴먼 에러

 

소프트웨어 시스템은 사람이 설계하고 구축하며, 그 시스템을 운영하는 사람들 역시 
사람입니다. 아무리 선의로 행동하더라도, 인간은 본질적으로 실수를 하게 마련입니다.

연구자료에 따르면 운영자가 설정(config)을 잘못 변경해서 발생한 오류가 장애의 주된 원인이었으며,
서버나 네트워크와 같은 하드웨어 문제는 전체 장애의 10~25%에만 관련되어 있음.

 

신뢰성을 보장하는 방식: 아래 방식을 결합하여 시스템에 적

  • 실수를 줄일 수 있도록 시스템을 설계
    → 잘 설계된 추상화, API, 관리자 인터페이스는 "올바른 행동"을 쉽게, "잘못된 행동"은 어렵게 만듭니다.
         다만 너무 제한적인 인터페이스는 사람들이 우회하려고 하므로 균형이 필요합니다.
  • 사람이 실수하기 쉬운 부분과, 그로 인해 심각한 장애가 생기는 부분을 분리
    → 예: 실제 데이터를 사용하되 실제 사용자에겐 영향을 주지 않는 샌드박스 환경 제공
  • 모든 수준에서 철저하게 테스트
    → 단위 테스트, 통합 테스트, 수동 테스트 등
    → 자동화 테스트는 경계 케이스를 검증하는 데 특히 유용합니다
  • 실수 발생 시 빠르게 복구 가능하도록 설계
    → 설정 롤백, 코드 점진적 배포(일부 사용자만 영향), 잘못된 계산 시 재계산 가능
  • 정밀한 모니터링(telemetry) 구축
    → 성능 메트릭, 오류율, 시스템 상태 모니터링
    → 로켓에서도 중요하게 쓰이는 개념으로, 문제 조기 감지 및 진단에 핵심적인 역할 
  • 운영 및 교육 체계 정비

신뢰성은 얼마나 중요한가? (How Important Is Reliability?)

 

  • 일반적인 어플리케이션
    버그는 업무 생산성 저하, 잘못된 수치 보고로 인한 법적 리스크를 유발할 수 있습니다.
    이커머스 사이트의 다운은 수익 손실뿐 아니라 브랜드 평판에도 큰 타격을 줍니다
  • 중요하지 않은 (noncritical) 애플리케이션   
    예를 들어, 한 부모가 자녀의 사진과 영상을 모두 여러분의 사진 앱에 저장해뒀다고 상상해보세요.
    만약 그 데이터베이스가 손상되었다면, 그들은 어떻게 느낄까요?

신뢰성을 희생해야 하는 경우 → 어디서 타협하고 있는지 명확히 인식하고 있어야 합니다.

  • 아직 시장성이 검증되지 않은 제품의 프로토타입 개발
  • 수익 마진이 매우 낮은 서비스의 운영 비용 절감 등 

확장성 (Scalability)

확장성은 부하 증가에 시스템이 얼마나 잘 대응할 수 있는지를 나타내는 개념입니다. 

확장성이 있다 없다로 단순히 평가하는 것이 아님

  • 시스템이 특정 방식으로 성장하면 우리는 어떻게 대응할 수 있을까?”
  • 추가 부하를 처리하기 위해 컴퓨팅 자원을 어떻게 확장할 수 있을까?”

확장성의 논의는 위와 같은 질문을 고려하는 것입니다.


부하 설명하기 (Describing Load)

현재 시스템의 부하가 어떤 상태인지 간결하게 설명할 수 있어야, 그 이후에  “만약 부하가 두 배로 증가한다면 어떻게 될까?”  같은 성장 관련 질문을 논의할 수 있습니다.

 

부하 파라미터

  • 웹 서버라면 초당 요청 수(requests per second)
  • 데이터베이스라면 읽기와 쓰기의 비율
  • 채팅방이라면 동시에 활성화된 사용자 수
  • 캐시라면 히트율(hit rate)

어떤 경우에는 평균적인 상황이 중요하고, 어떤 경우에는 몇몇 극단적인 상황이 병목의 원인이 될 수도 있습니다


성능 설명하기 (Describing Performance)

 

이제 부하가 증가했을 때 시스템에 어떤 일이 발생하는지를 조사할 수 있습니다. 이를 두 가지 방식으로 바라볼 수 있습니다.

  1. 부하 파라미터를 증가시키되 시스템 자원(CPU, 메모리, 네트워크 대역폭 등)은 그대로 유지할 때, 시스템 성능에 어떤 영향이 있는가?
  2. 부하 파라미터가 증가할 때, 성능을 동일하게 유지하려면 자원을 얼마나 더 늘려야 하는가?

이 두질문에 대한 성능 수치가 필요하며 성능을 아래와 같이 설명함

  • 배치 처리 시스템(예: Hadoop)에서는 보통 처리량(throughput)이 중요합니다. 즉, 초당 얼마나 많은 레코드를 처리할 수 있는지, 또는 특정 크기의 데이터셋을 처리하는 데 얼마나 걸리는지입니다.
  • 온라인 시스템에서는 보통 응답 시간(response time)이 더 중요합니다. 이는 클라이언트가 요청을 보내고 응답을 받기까지의 시간입니다.

응답시간(Response Time)  vs 지연시간(Latency)

  • 응답 시간(Response Time)은 클라이언트 입장에서 보는 시간이며, 서비스 처리 시간 + 네트워크 지연 + 대기 시간을 포함합니다.
  • 지연 시간(latency)은 요청이 서비스되기 전까지 대기하는 시간으로, "잠재(latent)" 상태에 있는 시간입니다.

응답시간 하나의 숫자가 아닌 분포로 생각해야 한다. 대부분은 빠르지만 일부는 다음과 같은 원인으로 훨씬 느릴수 있다.

 

  • 백그라운드 프로세스로 인한 컨텍스트 스위치
  • 네트워크 패킷 손실과 TCP 재전송
  • 가비지 컬렉션 일시 정지
  • 디스크 페이지 폴트
  • 서버 랙의 기계적 진동 등

소수의 매우 느린 요청이 평균값을 왜곡함으로 백분위수(Percentile)를 사용한다.

  • median(median, p50)은 절반의 요청이 이보다 빠르고, 절반은 느립니다.
  • p95: 95%의 요청이 이 시간보다 빠름
  • p99: 99%의 요청이 이 시간보다 빠름
  • p999: 99.9%의 요청이 이 시간보다 빠름

아마존은 응답시간이 100ms 증가시 매출이 1% 감소했으며 1초가 느려지면

고객 만족도가 16% 감소했다는 보도가 있습니다.

 

SLA/SLO에 활용

  • 중앙값 응답 시간이 200ms 미만
  • 99번째 퍼센타일이 1초 미만이면 서비스를 정상으로 간주(그 이상이면 사실상 다운된 것이나 다름없음)
  • 가용성은 99.9% 이상을 유지해야 함

 

부하에 대응하는 방법

확장 방식 

  1. 수직 확장 (Scale Up) 
    더 강력한 머신으로 교체, 구현은 간단하지만, 비용이 많이 들고 한계가 있음
  2. 수평 확장 (Scale Out)
    여러 대의 일반 머신에 작업을 분산, “공유 없는 아키텍처(shared-nothing)” 방식
    분산 시스템의 복잡성 수반
  • 상태 없는(stateless) 서비스는 수평 확장이 쉽습니다.
  • 반면, 상태를 가진 시스템(stateful system)은 분산화가 어렵고 복잡합니다.
    그래서 예전에는 데이터베이스는 가능한 한 단일 노드로 유지하는 것이 일반적이었습니다.
  • 탄력적 시스템 (Elasticity)
    자동으로 자원 추가 (클라우드 기반), 예측 불가능한 부하에 유리, 수동 확장보다 복잡하지만 유연함

유지보수성 (Maintainability)

 

개발자와 운영자가 시스템을 이해하고, 운영하고, 변경하기 쉽게 만드는 특성

  • 운용성(Operability): 운영팀이 시스템을 원활하게 운영할 수 있게 쉽게 만들어라.
  • 단순성(Simplicity): 시스템에서 복잡도를 최대한 제거해 새로운 엔지니어가 시스템을 이해하기 쉽게 만들어라(사용자 인터페이스의 단순성과는 다르다는 점에 유의하라).
  • 발전성(Evolvability) : 엔지니어가 이후에 시스템을 쉽게 변경할 수 있게 하라. 그래야 요구사항 변경 같은 예기치 않은 사용 사례를 적용하기 쉽다. 이 속성은 유연성(extensibility), 수정 가능성(modifiability), 적응성(plasticity)으로 알려져 있다.

운영성(Operability):운영을 쉽게 만들기

 

운영이 잘 되면 불완전한 소프트웨어도 잘 돌릴 수 있지만,
소프트웨어가 아무리 좋아도 운영이 엉망이면 제대로 동작하지 않는다.”

 

운영팀은 다음과 같은 역할을 수행합니다:

  • 시스템 상태 모니터링 및 문제 발생 시 빠르게 복구
  • 성능 저하나 장애의 원인 추적
  • 보안 패치 및 업데이트 적용
  • 시스템 간 상호작용 감시 및 문제 사전 방지
  • 용량 계획 및 미래 장애 대비
  • 배포, 설정관리 등 운영 도구 및 프로세스 정립
  • 플랫폼 변경, 마이그레이션 등 복잡한 작업 수행
  • 보안 유지 및 문서화 통한 지식 공유

좋은 운영성(Operability)을 갖춘 시스템은:

  • 시스템 내부 동작을 모니터링 도구로 가시화
  • 자동화 및 표준 툴과 통합이 쉬움
  • 특정 서버에 의존하지 않고 유지보수 중에도 무중단 운영
  • "X를 하면 Y가 된다"예측 가능한 작동 방식
  • 기본 설정이 잘 되어 있으면서도, 필요시 오버라이드 가능
  • 자가 복구(self-healing) 기능 + 수동 제어도 허용
  • 놀라움이 없는 예측 가능성

단순성(Simplicity): 복잡성 관리하기 

 

규모가 커지면 복잡도가 폭발적으로 증가합니다.

 

  • 복잡성의 증상
  • 상태 공간의 폭발
  • 모듈 간 과도한 결합
  • 얽힌 의존성
  • 불일치한 명명과 용어
  • 성능 개선을 위한 억지 코드
  • 다른 문제를 우회하기 위한 예외 처리 등

단순성은 반드시 기능을 줄인다는 뜻이 아닙니다. 종종 **‘우연한 복잡성(accidental complexity)’**을 제거하는 것을 의미

문제 자체에 내재된 복잡성이 아니라, 구현 방식에서 발생하는 복잡성(Moseley와 Marks )

우연한 복잡성을 줄이는 가장 강력한 도구는 추상화(abstraction)입니다. 좋은 추상화는 복잡한 내부 구현을 깔끔하고 이해하기 쉬운 인터페이스 뒤로 숨겨줍니다

 


발전성(Evolvability):변화에 잘 적응하는 시스템 만들기

 

  • 새로운 사실 발견
  • 예기치 않은 사용 사례가 등장
  • 비즈니스 우선순위 변경
  • 사용자의 요구가 증가
  • 새로운 플랫폼으로 이전
  • 법적/규제적 요구사항이 발생
  •  시스템의 성장으로 인해 아키텍처 변경

데이터 시스템이 얼마나 쉽게 변경 가능하며, 변화하는 요구사항에 얼마나 잘 적응할 수 있는지는 단순성과 추상화와도 밀접한 관련이 있습니다. 단순하고 이해하기 쉬운 시스템일수록 수정이 쉽습니다.

 

데이터 시스템 레벨에서의 민첩성  발전성(evolvability) 이라는 용어로 정의


신뢰성, 확장성, 유지보수성 모두 쉬운 해결책은 없지만, 공통적으로 효과적인 설계 패턴과 전략이 존재

 

728x90