[SWE-010][실무] 서비스 확장성과 데이터 일관성 선택하기
페이지 정보

본문
[이번 수업]
사용자가 늘어날 때 처리 능력을 키우는 방법과, 일부 서버가 통신하지 못할 때 일관성·가용성 사이에서 무엇을 선택할지 배웁니다.
[선수지식]
로드밸런서, 캐시, 데이터베이스 복제, 트랜잭션을 알아야 합니다. 확장성은 요청이나 데이터가 늘어도 필요한 성능을 유지하도록 처리 능력을 키울 수 있는 성질입니다.
[학습목표]
- 수직 확장과 수평 확장을 구분합니다.
- 강한 일관성과 최종 일관성의 차이를 설명합니다.
- 기능별로 지연·정확성·가용성 요구를 기록합니다.
[핵심개념]
수직 확장은 한 서버의 CPU·메모리를 키우는 방법이라 단순하지만 장비 한계와 중단 위험이 있습니다. 수평 확장은 같은 역할의 서버를 여러 대 두고 요청을 나눕니다. 애플리케이션 서버가 세션과 파일을 자기 디스크에만 저장하면 다른 서버가 이어받기 어렵습니다. 공유 저장소나 외부 세션 저장소를 사용하고, 상태 없는 처리를 늘린 뒤 병목을 측정합니다. 자동 확장은 관측 지표, 최소·최대 개수, 증가·감소 안정 시간을 함께 정해야 합니다.
일관성은 여러 복제본에서 읽은 값이 어떤 규칙으로 최신 상태를 보이는지입니다. 강한 일관성은 성공한 쓰기 뒤의 읽기가 최신 값을 보도록 보장하는 모델입니다. 최종 일관성은 잠시 오래된 값을 볼 수 있지만 새 변경이 없으면 복제본이 같은 값으로 모이게 합니다. 가용성은 장애나 네트워크 단절 중에도 요청에 응답할 수 있는 성질입니다. 단순한 서버 가동률과 같은 말은 아닙니다.
CAP 정리는 네트워크 분할, 즉 노드 사이 통신이 끊긴 동안 일관성과 가용성을 동시에 완전히 보장할 수 없다고 설명합니다. 항상 둘 중 하나만 고른다는 뜻이 아니라 분할 상황에서 어떤 요청을 거절하고 어떤 오래된 응답을 허용할지 정한다는 뜻입니다. 결제 승인·재고 차감은 오래된 읽기가 큰 문제를 만들 수 있고, 상품 설명·활동 피드는 잠깐 늦게 맞아도 서비스 응답을 우선할 수 있습니다. 한 시스템 안에서도 기능마다 선택이 다릅니다.
결정표에는 읽기·쓰기 지연 목표, 허용 가능한 오래된 시간, 데이터 손실 허용량, 충돌 해결 규칙, 실패 때 사용자 메시지를 적습니다. 복제 모드 이름만 믿지 말고 장애 훈련에서 실제 동작을 확인합니다. 재시도에는 요청 ID를 사용해 중복 변경을 막습니다.
[따라하기]
네트워크 분할 때 두 읽기 전략을 가상으로 비교합니다. tradeoff.py로 저장하세요.
```python
primary = {"stock": 5}
replica = primary.copy()
partitioned = True
primary["stock"] = 4
def strong_read():
if partitioned:
raise ConnectionError("replica cannot confirm latest value")
return primary["stock"]
def available_read():
return replica["stock"]
try:
print("strong=", strong_read())
except ConnectionError:
print("strong=unavailable")
print("available=", available_read(), "(stale)")
partitioned = False
replica.update(primary)
print("after_sync=", available_read())
```
macOS/Linux는 `python3 tradeoff.py`, Windows PowerShell은 `py tradeoff.py`로 실행합니다. 예상 결과입니다.
```text
strong=unavailable
available= 5 (stale)
after_sync= 4
```
강한 읽기는 최신 확인이 불가능해 실패하고, 가용한 읽기는 응답하지만 재고 5라는 오래된 값을 줍니다. 통신 복구와 동기화 뒤 4로 수렴합니다. 이는 개념 모형이며 실제 제품의 보장은 공식 문서에서 확인해야 합니다.
[흔한 실수]
서버 수만 늘리면 데이터베이스 병목도 사라진다고 생각하거나, CAP를 평상시 성능 선택으로 오해하기 쉽습니다. 평균 지연만 보지 말고 상위 백분위와 오류율을 측정합니다. 캐시 만료와 복제 지연도 사용자 기능별로 정합니다.
[보안 주의]
복제본과 관리 포트를 외부에 공개하지 않고 노드 통신을 인증·암호화합니다. 읽기 전용 복제본에도 최소 권한을 적용하고 백업으로 착각하지 않습니다. 부하·장애 실험은 본인 소유의 로컬·격리 환경에서 가짜 데이터로만 수행합니다.
[직접 해볼 과제]
위 코드에서 상품 설명은 30초 동안 오래된 값을 허용하고 재고 차감은 최신 확인 실패 시 거절한다는 결정표를 만드세요. 각 선택의 사용자 메시지도 한 줄씩 적으세요.
[확인문제]
1. 상태 없는 애플리케이션이 수평 확장에 유리한 이유는 무엇인가요?
2. 최종 일관성에서는 사용자가 어떤 값을 볼 수 있나요?
3. CAP 선택을 기능별로 나눠야 하는 이유는 무엇인가요?
[다음 학습]
MOBILE-010에서는 배터리·메모리·네트워크 성능을 다룹니다. SWE-011에서는 안전한 리팩터링과 기술 부채를 배웁니다.
[공식 참고 자료]
- 수평 자동 확장: https://kubernetes.io/docs/concepts/workloads/autoscaling/horizontal-pod-autoscale/
- 동기 복제: https://www.postgresql.org/docs/current/warm-standby.html#SYNCHRONOUS-REPLICATION
- 일관성 보장 예시: https://etcd.io/docs/v3.6/learning/api_guarantees/
- CAP 정리 논문: https://groups.csail.mit.edu/tds/papers/Gilbert/Brewer2.pdf
사용자가 늘어날 때 처리 능력을 키우는 방법과, 일부 서버가 통신하지 못할 때 일관성·가용성 사이에서 무엇을 선택할지 배웁니다.
[선수지식]
로드밸런서, 캐시, 데이터베이스 복제, 트랜잭션을 알아야 합니다. 확장성은 요청이나 데이터가 늘어도 필요한 성능을 유지하도록 처리 능력을 키울 수 있는 성질입니다.
[학습목표]
- 수직 확장과 수평 확장을 구분합니다.
- 강한 일관성과 최종 일관성의 차이를 설명합니다.
- 기능별로 지연·정확성·가용성 요구를 기록합니다.
[핵심개념]
수직 확장은 한 서버의 CPU·메모리를 키우는 방법이라 단순하지만 장비 한계와 중단 위험이 있습니다. 수평 확장은 같은 역할의 서버를 여러 대 두고 요청을 나눕니다. 애플리케이션 서버가 세션과 파일을 자기 디스크에만 저장하면 다른 서버가 이어받기 어렵습니다. 공유 저장소나 외부 세션 저장소를 사용하고, 상태 없는 처리를 늘린 뒤 병목을 측정합니다. 자동 확장은 관측 지표, 최소·최대 개수, 증가·감소 안정 시간을 함께 정해야 합니다.
일관성은 여러 복제본에서 읽은 값이 어떤 규칙으로 최신 상태를 보이는지입니다. 강한 일관성은 성공한 쓰기 뒤의 읽기가 최신 값을 보도록 보장하는 모델입니다. 최종 일관성은 잠시 오래된 값을 볼 수 있지만 새 변경이 없으면 복제본이 같은 값으로 모이게 합니다. 가용성은 장애나 네트워크 단절 중에도 요청에 응답할 수 있는 성질입니다. 단순한 서버 가동률과 같은 말은 아닙니다.
CAP 정리는 네트워크 분할, 즉 노드 사이 통신이 끊긴 동안 일관성과 가용성을 동시에 완전히 보장할 수 없다고 설명합니다. 항상 둘 중 하나만 고른다는 뜻이 아니라 분할 상황에서 어떤 요청을 거절하고 어떤 오래된 응답을 허용할지 정한다는 뜻입니다. 결제 승인·재고 차감은 오래된 읽기가 큰 문제를 만들 수 있고, 상품 설명·활동 피드는 잠깐 늦게 맞아도 서비스 응답을 우선할 수 있습니다. 한 시스템 안에서도 기능마다 선택이 다릅니다.
결정표에는 읽기·쓰기 지연 목표, 허용 가능한 오래된 시간, 데이터 손실 허용량, 충돌 해결 규칙, 실패 때 사용자 메시지를 적습니다. 복제 모드 이름만 믿지 말고 장애 훈련에서 실제 동작을 확인합니다. 재시도에는 요청 ID를 사용해 중복 변경을 막습니다.
[따라하기]
네트워크 분할 때 두 읽기 전략을 가상으로 비교합니다. tradeoff.py로 저장하세요.
```python
primary = {"stock": 5}
replica = primary.copy()
partitioned = True
primary["stock"] = 4
def strong_read():
if partitioned:
raise ConnectionError("replica cannot confirm latest value")
return primary["stock"]
def available_read():
return replica["stock"]
try:
print("strong=", strong_read())
except ConnectionError:
print("strong=unavailable")
print("available=", available_read(), "(stale)")
partitioned = False
replica.update(primary)
print("after_sync=", available_read())
```
macOS/Linux는 `python3 tradeoff.py`, Windows PowerShell은 `py tradeoff.py`로 실행합니다. 예상 결과입니다.
```text
strong=unavailable
available= 5 (stale)
after_sync= 4
```
강한 읽기는 최신 확인이 불가능해 실패하고, 가용한 읽기는 응답하지만 재고 5라는 오래된 값을 줍니다. 통신 복구와 동기화 뒤 4로 수렴합니다. 이는 개념 모형이며 실제 제품의 보장은 공식 문서에서 확인해야 합니다.
[흔한 실수]
서버 수만 늘리면 데이터베이스 병목도 사라진다고 생각하거나, CAP를 평상시 성능 선택으로 오해하기 쉽습니다. 평균 지연만 보지 말고 상위 백분위와 오류율을 측정합니다. 캐시 만료와 복제 지연도 사용자 기능별로 정합니다.
[보안 주의]
복제본과 관리 포트를 외부에 공개하지 않고 노드 통신을 인증·암호화합니다. 읽기 전용 복제본에도 최소 권한을 적용하고 백업으로 착각하지 않습니다. 부하·장애 실험은 본인 소유의 로컬·격리 환경에서 가짜 데이터로만 수행합니다.
[직접 해볼 과제]
위 코드에서 상품 설명은 30초 동안 오래된 값을 허용하고 재고 차감은 최신 확인 실패 시 거절한다는 결정표를 만드세요. 각 선택의 사용자 메시지도 한 줄씩 적으세요.
[확인문제]
1. 상태 없는 애플리케이션이 수평 확장에 유리한 이유는 무엇인가요?
2. 최종 일관성에서는 사용자가 어떤 값을 볼 수 있나요?
3. CAP 선택을 기능별로 나눠야 하는 이유는 무엇인가요?
[다음 학습]
MOBILE-010에서는 배터리·메모리·네트워크 성능을 다룹니다. SWE-011에서는 안전한 리팩터링과 기술 부채를 배웁니다.
[공식 참고 자료]
- 수평 자동 확장: https://kubernetes.io/docs/concepts/workloads/autoscaling/horizontal-pod-autoscale/
- 동기 복제: https://www.postgresql.org/docs/current/warm-standby.html#SYNCHRONOUS-REPLICATION
- 일관성 보장 예시: https://etcd.io/docs/v3.6/learning/api_guarantees/
- CAP 정리 논문: https://groups.csail.mit.edu/tds/papers/Gilbert/Brewer2.pdf
- 이전글[MOBILE-010][실무] 배터리·메모리·데이터 사용 줄이기 26.09.05
- 다음글[DATA-010][실무] 배치와 스트리밍으로 이벤트 처리하기 26.09.05
댓글목록
등록된 댓글이 없습니다.
