들어가기 전에
글또에서 좋은 기회로 <데이터 중심 애플리케이션 설계> 스터디에 합류하게 되어 열심히 배우고 있다. Github 레포지토리에 스터디 자료를 정리해서 올리고 있었는데 아무래도 읽는 분들은 블로그 자료를 참고하겠다 싶어서 내용을 공유하기 위해 블로그에도 남기기로 했다.
하지만 특정 템플릿에 따라 내용을 정리했기 때문에 책의 모든 내용이 요약되어있지 않다. 똑같은 내용을 읽으면서 다른 사람은 어떤 점이 새로웠고, 어떤 점이 어려웠는지 그 내용이 비슷하다면 어떤 점을 추가로 배웠는지 등에 초점을 맞춰 보면 좋을 것 같다.
스터디 소개
해당 스터디는 매주 1장씩 읽고 다음 템플릿에 따라 학습 내용을 정리하고 발표하며 서로 의견을 나눈다.
NDA
- 새롭게 알게 된 점(New)
- 어려웠거나 이해하지 못한 부분(Difficulty)
- 추가 내용(Amendment): 학습이 도움이 되었던 블로그, 유튭, 사례 등
NDA 템플릿은 글또 멤버 분이 쓰신 어떻게 하면 탈주닌자가 생기지 않을까? - 📚 스터디 방법론이라는 글에서 차용되었다. 글을 읽으면 왜 이런 템플릿을 고안하게 되었는지에 대한 이야기가 나와있는데 스터디 경험이 있다면 크게 공감을 할 수 있을 것이다. 약 2년 전, 6개월에 가까운 기간 동안 같은 멤버들과 스터디를 했었는데 우리도 처음엔 발표 형식으로 스터디를 하다가, 마지막에는 책에서 인상 깊게 보거나 이해가 안 갔던 부분에 밑줄을 치고 같이 페이지를 넘기며 서로 의견을 나눴었다. 마지막 스터디 형식을 템플릿 화했다면 비슷한 패턴이 되었지 않을까 싶다.
확실히 처음부터 끝까지 책 내용을 정리하는 것보다 발표할 때 핵심 내용을 전달하기 쉽고, 아는 내용보다는 모르는 내용에 집중해서 추가 지식을 쌓기 좋다.
01장. 신뢰할 수 있고 확장 가능하며 유지보수하기 쉬운 애플리케이션
[핵심 내용]
이번 장에서는 데이터 중심 애플리케이션을 생각하는 기본적인 방법 몇 가지를 배운다. 애플리케이션이 유용하려면 다양한 요구사항을 충족시켜야 하는데, 이번 장에서는 비기능적 요구사항 중 신뢰성, 확장성, 유지보수성을 자세히 살펴본다.
✅ 신뢰성 : 결함이 발생해도 시스템이 올바르게 동작하게 만들어야 한다.
✅ 확장성 : 부하가 증가해도 좋은 성능을 유지하기 위한 전략을 가져야 한다.
✅ 유지보수성 : 좋은 추상화로 복잡도를 줄이고 쉽게 시스템을 변경할 수 있어 개발자와 운영 팀의 피로도를 줄여야 한다.
[개념 사전]
단어 | 의미 |
팬 아웃 (fan-out) | 다른 게이트의 출력에 배속된 논리 게이트 입력의 수 (트랜잭션 처리 시스템에서 하나의 수신 요청을 처리하는 데 필요한 다른 서비스의 요청 수를 설명하기 위해 사용) |
처리량 (throughput) | 초당 처리할 수 있는 레코드 수나 일정 크기의 데이터 집합으로 작업을 수행할 때 걸리는 전체 시간 |
응답 시간 (response time) | 클라이언트가 요청을 보내고 응답을 받는 사이의 시간(네트워크 지연, 큐 지연 포함) |
지연 시간 (latency) | 요청이 처리되길 기다리는 시간, 서비스를 기다리며 휴지(latent) 상태인 시간 |
산술 평균 (arithmetic mean) | n개 값이 주어지면 모든 값을 더하고 n으로 나눔 |
꼬리 지연 시간 (tail latency) | 상위 백분위 응답 시간 |
선두 차단 (head-of-line blocking) | 소수의 느린 요청 처리만으로 후속 요청 처리가 지체되는 것 |
우발적 복잡도 (accidental complexity) | 소프트웨어가 풀어야 할 (사용자에게 보이는) 문제에 내재하고 있지 않고 구현에서만 발생하는 것 |
새롭게 알게 된 점(New)
1장을 읽고 난 후에 남긴 모니터링 툴 실습 글에 적어둔 것을 가져왔다.
1장을 읽으면서 새롭게 알게 되면서 흥미로웠던 주제가 바로 "응답 시간"이었다. 응답을 기다리지 않는 비동기 처리는 경험해 봤어도 응답 시간을 측정하고 그걸 통해 서비스를 개선해 본 경험은 없었기 때문에 더 흥미롭고 재미있었다. 최근에 토스에서 진행한 멘토링 프로그램인 "Learner's High 서버 1기"에 선정되어 세션을 들었는데 해당 세션을 통해서도 메트릭에 대한 중요성을 알게 되어서 더 관심이 생기기도 했었다.
<성능 기술하기>에서 응답 시간의 평균과 백분위를 다루는 부분을 보면 아래와 같은 내용이 나온다.
[1] 응답 시간 계산법
- 응답 시간은 단일 숫자가 아니라 측정 가능한 값의 분포로 생각해야 한다.
- 사용자가 보통 얼마나 오랫동안 기다려야 하는지 알고 싶다면 중앙값이 좋은 지표다.
- 중앙값은 단일 요청을 참고한다.
- 사용자가 여러 개의 요청을 보내면 최소한 하나의 요청이 중앙값보다 느릴 확률이 50%보다 훨씬 높다.
- 일반적으로 상위 백분위에서 사용하는 백분위는 95분위, 99분위, 99.9분위이다.
- 요청의 95%, 99%, 99.9%가 특정 기준치보다 더 빠르면 해당 특정 기준치가 각 백분위의 응답 시간 기준치가 된다.
[2] 상위 백분위 응답시간
- 꼬리 지연 시간(tail latency)은 서비스의 사용자 경험에 직접 영향을 주기 때문에 중요하다.
- 99.9분위 같은 최상위 백분위는 통제할 수 없는 임의 이벤트에 쉽게 영향을 받기 때문에 응답 시간을 줄이기가 매우 어렵다.
[3] 실전 백분위
- 병렬로 호출하더라도 병렬 호출 중 가장 느린 호출이 완료되길 기다려야 하기 때문에 그 하나로 인해 전체 최종 사용자의 요청이 느리게 될 수 있다.
- 서비스의 모니터링 대시보드에 응답 시간 백분위를 추가하려면 지속적으로 백분위를 효율적으로 계산할 필요가 있다.
- 방법 1. 단순한 구현으로 시간 구간 내 모든 요청의 응답 시간 목록을 유지하고 1분마다 목록을 정렬한다..
- 방법 2. 상황에 따라 포워드 디케이(forward decay), T 다이제스트(t-digest), Hdr히스토그램(hdrHistogram) 같은 CPU와 메모리 비용을 최소로 하면서 좋은 백분위 근사치를 계산할 수 있는 알고리즘을 사용한다.
- 응답 시간 데이터를 집계하는 올바른 방법은 히스토그램을 추가하는 것이다.
어려웠거나 이해하지 못한 부분(Difficulty)
부하 기술하기(11p)에서 다룬 트위터 사례에서 팬 아웃에 대한 개념이 낯설어서인지 접근 방식 2의 데이터 파이프라인이 처음 읽었을 당시에는 잘 이해가 가지 않아 이 부분을 적었다. 다시 읽고 난 후에는 아래와 같이 정리를 했다.
Point
평균적으로 트윗 게시 요청량이 홈 타임 라인 읽기 요청량에 비해 수백 배 적다.
- 트위터의 확장성 문제는 주로 트윗 양이 아닌 팬 아웃 때문이다.
- 트위터 사례에서 사용자당 팔로워의 분포는 팬 아웃 부하를 결정하기 때문에 확장성을 논의할 때 핵심 부하 매개변수가 된다.
팬 아웃이 트랜잭션 처리 시스템에서 하나의 수신 요청을 처리하는 데 필요한 다른 서비스의 요청 수를 설명하기 위해 사용하는 개념인 것을 인지하고, 트위터에서 한 명의 유명 인사가 글을 올렸을 때 그 사람을 팔로우하고 있는 여러 사람들의 홈 타임 라인에 해당 트윗을 업데이트해줘야 한다는 사실을 떠올리면 왜 데이터 파이프라인을 고민했을까를 이해할 수 있을 것이다.
추가 내용(Amendment)
낯설었던 개념이나, 추가적으로 자료를 찾아봤을 때 도움이 되었던 자료들을 남겨보았다.
[1] 카오스 몽키
🔗 카카오 장애가 우리에게 던진 세 가지 질문
- '야생의 원숭이가 무장을 한채 우리 데이터센터에 난동을 부려도 우리 서비스는 살아남을 수 있을까?'
- 서비스에 장애를 주입해 서비스가 견디는지를 보는 것을 의미한다.
[2] Prometheus 메트릭 타입
🔗 [Chapter 05 | Observability] Prometheus 이해하기
응답 시간 데이터를 올바르게 집계하는 방법으로 히스토그램이 나왔기 때문에 관련해서 메트릭 타입을 정리했다.
타입 | 의미 | 예제 |
Counter | 축적되는 단방향으로 증가하는 숫자 메트릭 | 요청 수 | 완료된 태스크의 수 |
Gauge | 증가하거나 감소할 수 있는 숫자 값을 나타낼 때 쓰는 메트릭 | 최근 기온 | 활성화 쓰레드 수 |
Histogram | 관찰 대상을 일정 시간 간격으로 나누어 기록(샘플링)하고, 그 값을 범위(버킷) 별로 구분 및 저장하고 조회할 수 있는 메트릭 | 데이터베이스 I/O Latency |
Summary | 관찰 대상을 일정 시간 간격으로 나누어 기록(샘플링)하고, 총 발생 횟수나 합계를 제공하는 메트릭 | 응답 시간의 합 |
안 그래도 모니터링 툴에 대해 관심이 많았기 때문에 이 타입들 중 Histogram 데이터를 통해 p9x 시리즈 데이터를 보는 실습을 진행했고 정리해서 글로 남기기도 했다. 아래의 글에서 <더해보기> 챕터를 보면 알 수 있다.
모니터링 툴 씬의 맛없없 조합: Spring Boot Actuator X Prometheus X Grafana
들어가기 전에작년 12월, 테오의 스프린트에 참여해 '부꾸러미' 서비스를 만들었다. 부꾸러미부꾸러미 has 2 repositories available. Follow their code on GitHub.github.com 서비스의 특성상 사용자들의 적극
justsora.tistory.com
그런데 스터디 내용을 다시 정리하다 보니 궁금해졌다. Histogram과 Summary은 비슷해 보이는데 둘 중 하나를 선택할 수 있는 기준은 도대체 뭘까? 메트릭의 분포와 요약 정보를 제공하는 데 사용되는 것은 동일하지만 좀 더 구분해 보자면 아래와 같은 차이점이 있다.
Histogram | Summary | |
집계(Aggregation) 가능 | ⭕️ | ❌ |
값의 범위, 분포 확인 | ⭕️ | ❌ |
정확한 quantile(분위수) 제공 | ❌ (근사값 제공) | ⭕️ |
예를 들어, 두 학생이 있다고 하자.
A : 나는 서버가 여러 대인데, 대부분의 요청이 몇 초 이내로 처리되는지 궁금해!
B : 나는 서버가 한 대인데, 요청의 95%는 몇 초 이내로 처리되는지 궁금해!
아래처럼 요청이 들어온다면 Histogram과 Summary는 각각 어떤 정보를 줄 수 있을까?
- 요청 1: 0.5초
- 요청 2: 1.2초
- 요청 3: 2.8초
Histogram은 A 학생에게 답을 줄 수 있다. 각 요청 시간을 사전에 정의된 구간(버킷)에 분류해서 저장하기 때문에 값의 범위나 분포를 확인할 수 있기 때문이다. 요청들이 0-1초, 1-2초, 2-3초 구간에 속해 있다면 각 구간별 요청 수를 기록하고, 이 데이터를 기반으로 분위수를 추정한다.
Summary는 B 학생에게 답을 줄 수 있다. 95%처럼 미리 정한 분위수 값에 맞게 데이터를 미리 계산하기 때문이다. 거기다 서버가 한 대라면 Aggregation이 필요하지 않으므로 여러 서버의 데이터를 합산할 수 없는 Summary의 특성이 문제가 되지 않는다.
[3] fan-out
한 개의 요청이 여러 개의 작업을 유발하는 정도
트위터에서 팬 아웃 부하를 이야기하는 것은, 팔로우 기반의 SNS이기 때문이다. 한 사용자의 트윗이 N명의 팔로워들에게 전달하는 과정에서 부하가 생길 수 있다.
참고 자료
'노트' 카테고리의 다른 글
모니터링 툴 씬의 맛없없 조합: Spring Boot Actuator X Prometheus X Grafana (0) | 2025.03.02 |
---|---|
Github Actions (CI) (0) | 2023.02.23 |
Testcontainers (0) | 2023.02.20 |