System Design

키-값 저장소는 어떻게 동작할까?

mindol 2025. 8. 22. 22:26

ByteByteGo의 영상을 기반으로 Claude, Gemini 와 같이 추가 공부한 내용을 정리했습니다.


 

키-값 저장소는 어떻게 작동할까?

쇼핑카트에서 시작된 복잡한 분산 시스템 이야기

온라인 쇼핑을 할 때 장바구니에 물건을 담으면, 그 정보는 어디에 저장될까요? 채팅 메시지를 보내면 어떻게 상대방에게 정확히 전달될까요? 이런 일상적인 기능들 뒤에는 키-값 저장소(Key-Value Store)라는 데이터베이스가 숨어있습니다.

출처: ByteByteGo

키-값 저장소란?

키-값 저장소는 거대한 사전과 같습니다. 사전에서 단어(키)를 찾으면 그 뜻(값)을 얻는 것처럼, 키-값 저장소에서는 특정 키로 데이터를 저장하고 찾을 수 있습니다.

예를 들어보겠습니다:

  • : user12345_cart
  • : 사용자의 장바구니에 담긴 모든 상품 정보

이렇게 간단해 보이는 개념이 실제로는 어떤 복잡한 문제들을 만들어낼까요?

 

규모의 문제: 한 대의 컴퓨터로는 부족하다

아마존 같은 대형 서비스를 생각해보세요. 전 세계 수억 명의 사용자가 동시에 쇼핑을 하고, 각 지역마다 테라바이트 단위의 데이터가 저장됩니다. 수십억 개의 키-값 쌍이 초당 수백만 번씩 접근됩니다.

당연히 한 대의 컴퓨터로는 감당할 수 없습니다. 수천 대의 서버에 데이터를 분산해서 저장해야 합니다. 하지만 여기서 새로운 문제가 생깁니다.

첫 번째 도전: 어느 서버에 데이터가 있을까?

사용자가 user12345_cart 정보를 요청했을 때, 수천 대의 서버 중 어느 서버에 그 데이터가 있는지 어떻게 알 수 있을까요?

 

단순한 해시 방법의 한계

처음에는 간단한 방법을 생각할 수 있습니다:

  1. 키를 해시 함수에 넣어서 숫자로 변환
  2. 서버 개수로 나눈 나머지를 구함
  3. 그 나머지에 해당하는 서버에 저장

예를 들어, 서버가 3대라면:

  • user12345_cart의 해시값이 157이라면
  • 157 ÷ 3 = 52 나머지 1
  • 1번 서버에 저장

출처: ByteByteGo

 

 

하지만 서버를 하나 추가하면 어떻게 될까요? 갑자기 모든 계산이 바뀝니다. 4로 나누게 되면서 거의 모든 데이터가 다른 서버로 이동해야 합니다. 이는 엄청난 비용과 시간이 듭니다.

 

출처: ByteByteGo

 

일관된 해싱

일관된 해싱(Consistent Hashing)은 이 문제를 해결하는 영리한 방법입니다. 시계를 상상해보세요. 12시간 대신 수백만 개의 위치가 있는 거대한 원형 시계입니다.

 

이 원 위에 서버들을 무작위 위치에 배치합니다:

  • 서버 A: 위치 100
  • 서버 B: 위치 1,000
  • 서버 C: 위치 5,000

이제 user12345_cart를 저장하려면:

  1. 키를 해시해서 원 위의 위치를 구합니다 (예: 750)
  2. 그 위치에서 시계방향으로 돌면서 첫 번째 서버를 찾습니다
  3. 서버 B(위치 1,000)에 데이터를 저장합니다

새 서버 D를 위치 500에 추가하면 어떻게 될까요? 위치 101부터 500까지의 키들만 서버 D로 이동하면 됩니다. 나머지 데이터는 그대로 유지됩니다. 이렇게 데이터 이동을 최소화할 수 있습니다.

 

출처: ByteByteGo

 

여기서 한 걸음 더 나아가, 실제 시스템에서는 하나의 서버가 원 위의 여러 위치를 담당하는 '가상 노드' 개념을 사용하기도 합니다. 이렇게 하면 소수의 서버만으로도 데이터가 전체 원에 훨씬 더 균일하게 분포되어 특정 서버에 부하가 몰리는 것을 막아줍니다.

 

두 번째 도전: 서버가 고장나면?

서버 B가 갑자기 고장나면 해당 데이터에 접근할 수 없게 됩니다. 이를 해결하기 위해 복제(Replication)를 사용합니다.

각 데이터를 여러 서버에 복사해서 저장합니다. user12345_cart를 서버 B에 저장할 때, 시계방향으로 다음 두 서버(서버 C, 서버 A)에도 복사본을 저장합니다. 이제 서버 B가 고장나도 데이터에 접근할 수 있습니다.

 

출처: ByteByteGo

 

세 번째 도전: 일관성 문제

 

복제는 새로운 문제를 만듭니다. 가족 공용 계정으로 두 사람이 동시에 장바구니에 물건을 담는다고 상상해보세요. 두 요청이 서로 다른 서버에 도착하면, 같은 장바구니의 서로 다른 버전이 생깁니다. 어느 것이 정확한 버전일까요?

CAP 정리: 완벽함의 불가능성

분산 시스템에서는 다음 세 가지를 모두 완벽하게 가질 수 없습니다:

  • 일관성(Consistency): 모든 서버가 항상 최신 데이터를 가짐
  • 가용성(Availability): 시스템이 항상 응답함
  • 분할 내성(Partition Tolerance): 네트워크 문제가 있어도 작동함

더 정확히 말하면, 분산 시스템은 여러 서버로 이루어져 있기에 서버 간 통신이 끊어지는 네트워크 분할(Partition Tolerance) 상황을 피할 수 없습니다.

 

따라서 엔지니어는 네트워크 분할이 발생했을 때 일관성(Consistency)가용성(Availability) 중 무엇을 우선할지 선택해야만 합니다.

은행은 일관성을 선택합니다. 잘못된 계좌 잔고를 보여주는 것은 용납할 수 없으니까요. 서버 간 통신에 문제가 있으면 요청을 거부하더라도 정확한 정보만 제공합니다.

대부분의 웹 애플리케이션은 가용성을 선택합니다. 오래된 장바구니 정보를 보여주는 것이 아무것도 보여주지 않는 것보다 낫기 때문입니다.

 

최종적 일관성: 현실적 타협

대부분의 대규모 시스템은 최종적 일관성(Eventual Consistency)을 사용합니다. "충분한 시간이 지나면 모든 복사본이 일치하게 된다"는 개념입니다. 지금 당장은 약간 다를 수 있지만, 결국에는 같아집니다.

 

 

네 번째 도전: 서버 실패 감지

수천 대의 서버가 있는 환경에서는 항상 어딘가에서 고장이 납니다. 어떻게 서버가 다운되었는지 알 수 있을까요?

모든 서버가 다른 모든 서버를 확인하는 것은 비현실적입니다. 1,000대 서버라면 거의 100만 개의 연결이 필요합니다.

출처: ByteByteGo

가십 프로토콜

가십 프로토콜(Gossip Protocol)은 마치 학교에서 소문이 퍼지는 것과 같습니다. 각 서버는 다른 서버들의 목록을 가지고 있고, 가끔씩 몇 개의 무작위 이웃과 그 정보를 공유합니다.

 

서버 X가 응답하지 않으면, 그 소문이 전체 클러스터로 퍼집니다. 모든 서버가 모든 서버와 대화할 필요 없이도 효과적으로 작동합니다.

출처: ByteByteGo

 

 

결론: 단순함 뒤의 복잡성

"장바구니 기억하기"라는 단순한 요구사항이 분산 시스템 엔지니어링의 마스터클래스가 되었습니다. 그리고 이것은 시작에 불과합니다.

우리가 아직 다루지 않은 주제들이 더 있습니다:

출처: ByteByteGo

  • 스토리지 엔진 최적화
  • 데이터센터 전체 장애 대응
  • 수천 대 머신에서의 성능 최적화
  • 데이터 압축과 캐싱 전략

다음에 온라인 쇼핑에서 장바구니에 물건을 담았을 때 아무런 문제없이 잘 작동한다면, 그 순간 전 세계 데이터센터에서 벌어지고 있는 복잡하고 정교한 협업을 떠올려보세요. 이 모든 기술적 노력은 단 하나의 목표를 위한 것입니다. 바로 당신의 데이터가 언제나 정확한 곳에서 안전하게 기다리고 있도록 하는 것이죠.

 

키-값 저장소는 현대 인터넷의 숨은 영웅입니다. 단순해 보이지만 그 안에는 수십 년간 축적된 분산 시스템의 지혜가 담겨있습니다.