데브콘 활동 후기

[Review] 시스템 디자인 스터디 1주차 후기

dev-jonghoonpark 2025. 9. 16. 16:27

안녕하세요!

K-DEVCON (이하 “데브콘”) 그로스 매니저 박종훈입니다🙋🏻‍♂️

 

데브콘에서는 8월에 시스템 디자인 스터디 참여자를 모집하여 지난 9월 11일(목) 드디어 첫 스터디를 시작하였습니다!!!

이번 스터디는 「가상 면접 사례로 배우는 대규모 시스템 설계 기초」 라는 책으로 진행해보기로 했습니다. 

(모집글 보러가기)

 

처음에는 지원자가 없을까 걱정했지만, 예상보다 많은 관심으로 지원자가 너무 많아 놀랐습니다. 지원해주신 분들의 배움에 대한 열정을 느낄 수 있었습니다. 모든 지원자분들이 훌륭하셨지만, 부득이하게 장소와 운영 인원의 제약으로 인해 아쉽게도 모든 분을 모시지 못해 죄송한 마음을 전합니다🙏🏻

 

직접 스터디를 개설해보고 싶은 분이 계시다면, K-DEVCON에서 운영을  도와드리겠습니다.

데브콘의 '랩짱'에 도전하여 커뮤니티 성장을 함께 이끌어주세요! 슬랙을 통해 운영진에게 DM 부탁드리겠습니다😉

 

이 글에서는 9월 11일(목)에 진행된 스터디에서 나눈 이야기를 정리합니다.

 

 

 

이번 시스템 디자인 스터디에서는 많은 이야기를 자유롭게 나누길 기대했습니다. 그렇기 때문에 스터디를 시작하면서, 책에 없는 내용이지만 주제와 관련된 내용이라고 생각된다면 자유롭게 공유해주고, 다른 의견이 있을 때에도 서로 좋은 피드백을 줄 것을 요청드렸습니다.

 

 

시스템 디자인 스터디 책에는 시스템 디자인 면접을 하는 이유에 대해서 다음과 같이 설명하고 있습니다.

“두 명의 동료가 모호한 문제를 풀기 위해 협력하여 그 해결책을 찾아내는 과정에 대한 시뮬레이션이다”

우리는 이 모호한 문제를 다루면서 어떻게 trade off 를 할 것인지를 결정해야합니다. 때로는 정답이었던 것이 상황에 따라서는 부족할수도, 과도한 엔지니어링이 될 수도 있습니다. 

 

시스템은 사용자 수가 적을 때는 큰 문제가 없습니다. 하지만 사용자가 늘어나면 다양한 문제에 직면하게 되고, 이에 따라 시스템 확장을 고려해야 합니다. 시스템을 확장하게 되면 더 많은 사용자 요청을 처리 할 수 있겠지만, trade off 로 다양한 문제점이 발생하게 됩니다. 확장된 시스템을 조율해야 하기 때문에 시스템의 복잡도도 증가할 것이고, 그 사이에 SPoF(Single Point of Failure, 단일 장애 지점) 가 없는지도 고려해야 합니다. 그리고 가장 어려운 부분은 데이터를 어떻게 잘 저장하고, 잘 제공할 지에 대한 부분입니다.

 

우리는 이번 시간에 이러한 내용들에 대해 많은 이야기를 나눴지만 그 중 재미있던 이야기 3가지를 이야기 해보겠습니다.

 

1. 데이터 일관성과 정족수 합의 프로토콜

 

이번 스터디 범위에는 분산 환경에서의 데이터 일관성과 이를 달성하기 위한 정족수 합의 프로토콜에 대한 주제가 있었습니다.

 

책에서는 W (쓰기 연산에 대한 정족수), R (읽기 연산에 대한 정족수), N (사본 개수) 로 정의하고

W + R > N 일 경우 강한 일관성이 보장되는 것으로, W + R < N 일 경우 강한 일관성이 보장되지 않는 것으로 설명을 하고 있습니다. 그리고 강한 일관성이 보장되는 경우에 “클라이언트는 절대로 낡은 데이터를 보지 못한다” 라고 설명을 하고 있습니다.

 

저는 사실 이 책을 처음봤을 때, 위 내용을 보고 그냥 그렇구나 생각하고 넘어갔었는데, 이번에 다시 읽어볼 때는 좀 더 깊게 이해해보고 싶다는 마음으로 관련 자료들을 찾아보았습니다. 좀 더 구체적인 예시를 들어보기 위해서 Amazon Aurora를 예시로 들어보겠습니다.

 

Aurora는 기존의 DataBase 에서 컴퓨팅 영역과 스토리지 영역을 나누어 관리합니다. 스토리지 영역은 3개의 AZ 와 각 AZ 마다 2개의 스토리지 노드로 구성하여 총 6개의 노드로 구성되어있습니다.

 

 

이 노드들은 정족수 합의 프로토콜을 통해 강한 일관성을 보장하고 있습니다. (W=4, R=3)

진짜일까요? 먼저, W=3, R=3 인 상황을 생각해보겠습니다. 모든 Node 가 ‘a=0’ 이라는 값을 가지고 있다고 가정해보겠습니다.

 



이때 알 수 없는 이유로 Node 4,5,6 이 다운되었습니다.

 

 

이러한 상태에서 Client가 a의 값을 1로 변경하면 어떻게 될까요?

 

 

W=3 이기 때문에, 살아있는 3개의 노드가 응답을 해준다면 Node 1, 2, 3 은 a=1 로 업데이트가 될 수 있을 것입니다. Node 4, 5, 6 은 다운되어 있기 때문에 요청을 받지 못하고 a=0 상태로 남아있습니다. 이후에 Node 4, 5, 6 이 다시 살아나게 되면 아래와 같은 상황이 될 것입니다.

 

 

이때 Client가 a 를 조회하면 어떻게 될까요? R = 3 이기 때문에 만약 Node 4,5,6 로 부터 데이터를 받았다면 Client는 a=0 을 받을 수 있게 됩니다. 이는 ‘강한 일관성이 깨진다’는 것을 의미합니다. 

 

반면에 W=4, R=3 인 상황을 생각해보겠습니다. 마찬가지로 a=0 인 상태에서 Client가 a의 값을 1로 변경하는 상황을 생각해보겠습니다. W=4 이기 때문에, 최소 4대가 살아있어야 정족수 합의가 가능합니다.

 



 

Node 1, 2, 3, 4 은 a=1 로 업데이트가 된 상태이고, Node 5, 6 은 요청을 받지 못하고 a=0 상태로 남아있다가 다시 살아났습니다.


 

이때 a 의 값을 요청하면 어떻게 될까요? R=3 이기 때문에, 6개의 노드 중 어떤 3개로 부터 값을 수신하더라도 정상인 데이터(a=1)를 수신하거나 데이터 충돌을 판단할 수 있는 데이터(a=1, a=0)를 얻을 수 있게 됩니다. 따라서 W=4, R=3 인 경우 강한 일관성을 만족하게 됩니다. Amazon Aurora는 강한 일관성 (W + R > N) 을 가지고 있음을 볼 수 있습니다.

 

 

2. 블룸필터(Bloom filter) : 확률적 자료구조를 이용한 추정

 

블룸필터(Bloom filter)는 확률적 자료구조를 이용한 추정을 돕습니다. 이를 통해 빠른 판단을 할 수 있습니다. 블룸필터는 확률적 자료구조를 사용하기 때문에, 특정 요소가 있다고 했는데 없을 수 있습니다. 하지만 없다고 했다면 반드시 없습니다. 모든 데이터를 찾아볼 필요 없이 빠르게 없음을 판단하는데 사용할 수 있습니다. 

 

블룸 필터의 동작 방식에 대해서 이야기를 나누는데 스터디원분 중에 한 분이 왜 여러 개의 해시 함수를 사용하는지에 대한 질문을 주셨습니다. 그리고 그에 대한 답을 찾아보니 거짓 양성을 낮출 수 있기 때문이라고 합니다. 이에 대해서 쉽게 설명을 해보자면, 우연히 해시 값이 같을 수 있다는 것입니다.

만약에 해시가 하나일 경우 다음의 경우가 발생될 수도 있습니다.

  • a != b , but hash(a) = hash(b)
    → 데이터가 일치하지 않으나 hash 상 동일하므로 존재한다고 판단함. (거짓 양성)

 

이는 또 다른 해시 함수를 두어 해결할 수 있습니다.

  • a != b, hash(a) = hash(b), bash2(a) != hash(b)
    → hash 의 결과는 동일하나, hash2 의 결과는 동일하지 않으므로 존재하지 않다고 판단

 

이런 방식으로 해시 함수를 추가함으로써 해시 충돌로 인한 거짓 양성을 낮출 수 있습니다. 하지만 해시 함수를 추가할 경우 더 빠르게 공간이 포화 될 수 있습니다. 따라서 적절한 균형이 필요합니다. 

 

3. Rate limiter (처리율 제한 장치)

각자의 회사에서 어떻게 처리하고 있는지 경험을 들어볼 수 있었어서 유익한 시간이었습니다. 책에서는 5개의 방식에 대해서 설명합니다,

  • 토큰 버킷
  • 누출 버킷
  • 고정 윈도우 카운터
  • 이동 윈도 로그
  • 이동 윈도 카운터

 

이 중 토큰 버킷 방식과 고정 윈도 카운터 알고리즘의 적용 사례에 대해서 이야기를 나눴습니다. 보통은 대규모 트래픽이 예상되는 경우 (ex. 이벤트시) 를 대비하여 도입한 경우들이 많았습니다. 구현 방식에서도 차이가 있었는데 책에서 이야기 하는것처럼 실제로 버킷에 토큰을 채우는 것과 같이 배치를 사용하여 횟수를 리셋해주는 경우가 있었고 다른 한 경우는 마지막 토큰 리필 시간을 확인하여, 그에 따라 처리하는 방식이였습니다. 두 가지 모두 재미 있는 방식이라고 생각됩니다.

 

그 외에 2가지 재밌는 사례가 있었는데 하나는 OPEN API에 대한 Rate Limiter 적용 사례였습니다. API가 공개된 형태이기 때문에 API 악용의 소지가 있어 Rate Limiter를 도입하였다고 하셨습니다.

 

또 하나의 재밌는 사례는 GraphQL을 사용하는 사례였습니다. GraphQL은 일반적인 Rest API 와 다르게 Rate Limit을 적용한다고 하는데요, 그 이유는 GraphQL은 사용자가 필요한 데이터를 직접 명시하여 요청할 수 있기 때문입니다. 따라서 해당 요청이 어떤 Entity에 대한 요청인지를 쪼개어 계산을 하게 됩니다. 이 부분은 디버깅을 어렵게 하기도 한다네요. 



—-

 

오늘은 위와같은 이야기를 함께 나누어보았습니다. 사실 더 많은 이야기를 나눴지만, 여기에 다 기록하지 못해 아쉽습니다. 기대했던 것 이상으로 다들 열심히 참여해주셔서 더 풍성한 스터디가 될 수 있었던것 같습니다. 참여자분들 덕분에 다양한 시각을 배울 수 있었고, 제가 놓쳤던 부분도 다시 생각해볼 수 있었습니다👍🏻

 

 

다음 시간부터는 본격적으로 시스템 디자인을 함께 진행할 예정입니다. 더욱 유익한 시간이 될 수 있기를 기대합니다😎