[Review] 시스템 디자인 스터디2 - 4주차 후기

안녕하세요!
K-DEVCON (이하 “데브콘”) 그로스 매니저 박종훈입니다.

어느새 2026년이 되었습니다.
올해 목표하신 모든 것들 다 이룰 수 있는 한해 되시길 바랍니다 : )

이 글에서는 01/08 (목)에 진행된 스터디에서 나눈 이야기를 정리합니다.

이번 시간에는 “분산 메시지 큐” 에 대한 시스템 설계를 해보았습니다.

---

“메시지 큐” 는 많은 곳에서 활용됩니다. 결합도를 완화해주고, 규모 확장을 쉽게 할 수 있도록 돕습니다. 또 시스템을 비동기 통신으로 처리하기 쉽도록 합니다.

다양한 메시지 큐들이 있으며, 각 메시지큐는 서로 장단점을 가지고 있어, 본인의 상황에 맞는 메시지 큐를 적절히 선택하는 것이 중요합니다. 클라우드 벤더에서도 다양한 솔루션을 제공해주고 있습니다. (ex. aws sns, aws sqs, aws msk …)

[Review] 시스템 디자인 스터디2 - 4주차 후기
주요 메시지 큐의 star 수 비교

필요한 상황에 맞게 잘 사용했을 경우에는 시스템에 큰 도움이 될 수 있지만, 무작정 도입했을 경우에는 오히려 오버엔지니어링이 되어서 비용이나 복잡도를 올릴 수 있기도 합니다.

[0] 분산 메시지의 핵심 구조

[Review] 시스템 디자인 스터디2 - 4주차 후기 - 이미지 2
분산 메시지의 핵심 구조

- 생산자는 메시지를 메시지 큐에 발행(생산, produce) 합니다.
- 소비자는 큐를 구독(subscribe)하고, 구독한 메시지를 소비(consume) 합니다.

이 구조를 통해 생산자와 소비자 사이의 결합을 느슨하게 할 수 있고, 이는 서로를 독립적으로 운영 가능하게 하며, 규모 확장을 용이하게 합니다.



[1] 메시지 큐 와 이벤트 스트리밍 플랫폼의 차이

사실 우리가 흔히 같은 개념으로 이야기하는 메시지 큐와 이벤트 스트리밍 플랫폼에는 명확한 차이가 있습니다.
흔히 카프카를 메시지 큐 라고 부르지만, 엄밀하게는 이벤트 스트리밍 플랫폼 입니다.

메시지 큐는 배달에 집중하고, 이벤트 스트리밍 플랫폼은 저장 후 공유하는 흐름에 집중합니다.
전통적인 메시지 큐는 소비 순서를 보증하지 않으며, 한 번 소비된 메시지는 지웁니다. 메시지를 한 번 읽으면 다른 소비자는 읽을 수 없습니다. (ex. rabbitmq)
반면 이벤트 스트리밍 플랫폼은 소비 순서를 보장하며, 메시지를 보관하고 있으며, 메시지를 누군가 읽더라도 다른 소비자도 읽을 수 있습니다. (ex. kafka)



[2] 메시지 큐를 직접 구현한다면?

메시지 큐의 트래픽 패턴은 정리하면 다음과 같습니다.

- 읽기와 쓰기가 빈번하게 발생
- 갱신/삭제 연산은 발생하지 않음
- 일반적으로 순차적으로 읽기/쓰기 발생

이러한 패턴에 적절한 선택지는 어떤것이 있을까요?

<1> 데이터베이스를 사용할 수 있다.

데이터 베이스는 다양한 쿼리 패턴을 지원합니다. 따라서 해결책 중 하나가 될 수 있습니다.
간단한 메시지 큐를 위해서는 사용할 수 있겠지만, 메시지 큐에 이상적인 구조는 아닙니다.

<2> 쓰기 우선 로그 (Write-Ahead Log, WAL)

WAL은 새로운 항목이 추가되기만 할 수 있는 파일 구조입니다. WAL에 대한 접근 패턴은 읽기/쓰기 모두 순차적입니다. 따라서 접근 패턴이 순차적일 때 아주 좋은 성능을 보이는데, 이는 메시지큐에 어울리는 방법이라고 할 수 있습니다.

데이터 장기 보관을 위해서는 디스크 드라이브가 유리한데요 이 때, 회전식 디스크가 느릴 것이라 예상할 수 있지만, 이것은 편견이라고 합니다. 회전식 디스크가 정말로 느려지는 것은 데이터 접근 패턴이 무작위 (random) 일 경우입니다.

디스크 탐색 (random seek)에는 2ms 가 드는 반면, 디스크를 순차적으로 1MB 를 읽는데 드는 시간은 1ms 보다도 적습니다. (출처: 모든 프로그래머가 알아야 하는 응답지연 값 (원본, 번역))

많은 시스템들에서 데이터를 효율적으로 적재하기 위해 노력합니다.

<3> 메모리를 사용할 수도 있다.

책에서는 나오지 않는 방식이지만, 데이터 베이스를 활용할 수 있듯, 메모리를 사용할수도 있습니다.
초기 Slack 에서는 Redis 를 활용하여 메시지 큐로 사용했었습니다.
관심 있는 사람은 https://k-devcon.com/channel/4/post/141 의 글을 참고하시면 되겠습니다.



[3] 분산 환경의 어려움

큐는 장점도 있지만, 실제로 운영해 볼 경우 많은 어려움을 주기도 합니다.
내가 사용하고 있는 큐의 특징과, 설정값에 대해 잘 알고 있어야 합니다. 잘못된 구성/설정은 시스템 장애로 이어지기 쉽습니다.

아래와 같은 키워드 들에 대해서 이야기를 나눴습니다.

타임아웃(Timeout): 네트워크 지연이나 서비스 장애는 상시 발생합니다. 시스템이 무한정 대기하지 않도록 적절한 타임아웃을 설정해야 합니다. 하지만 너무 짧은 시간 설정은 마찬가지로 장애로 연결될 수 있으므로 주의해야 합니다.

리밸런싱(Rebalancing): 컨슈머 그룹 내에서 노드가 추가되거나 이탈할 때 파티션 소유권을 재조정 하는 과정입니다. 이 과정에서 소비가 중단되거나 중복 메시지가 발생될 수 있기 때문에 주의가 필요합니다.

ISR(In-Sync Replicas): 데이터 유실을 막기 위해 리더와 동기화된 복제본(ISR) 그룹을 관리합니다.  리더와 데이터가 동일하다고 간주되는 신뢰할 수 있는 기준을 잡고, 그 기준에 따라 최신 데이터가 아니게 될 경우 그룹에서 추방합니다. 추방된 팔로워는 이후 리더와의 격차를 줄이면 다시 합류할 수 있습니다. 이를 통해 리더에서 장애가 발생했을 경우, 데이터가 뒤처진 잘못된 리더가 선출되는 것을 방지합니다.

전송 보장 범위:
- 최대 한 번 (At most once): 메시지는 최대 한 번만 전달됩니다. 시스템 장애가 발생할 경우 메시지가 유실될 수 있으며, 재전송되지 않습니다.
- 최소 한 번 (At least once): 메시지가 한 번 이상 전달됨을 의미합니다. 시스템 장애가 발생하더라도 메시지는 절대 유실되지 않지만, 동일한 메시지가 중복 전달될 수 있습니다.
- 정확히 한 번 (Exactly once): 가장 이상적인 동작 방식으로, 각 메시지는 반드시 한 번만 전달됩니다. 시스템의 일부에서 장애가 발생하더라도 메시지가 유실되거나 중복해서 읽히는 일이 없습니다.

모든 메시지 처리는 멱등성(Idempotency)이 보장되도록 설계해야 합니다. 동일한 메시지가 여러 번 도달해도 결과가 같아야 시스템의 안정성이 유지됩니다.

분산 환경에서는 비즈니스 영향도를 고려해 성능을 위해 정확도를 어느 정도 타협(Trade-off)해야 하기도 합니다.



[4] 메시지 큐 운영 노하우

메트릭 모니터링: 초당 발행(Produce)되는 이벤트와 소비(Consume)되는 이벤트의 양을 실시간으로 확인해야 합니다. 특히 Consumer Lag(생산 속도를 소비 속도가 따라가지 못해 쌓이는 지연량)는 장애의 전조 증상입니다.

병목 지점 파악: 시스템이 느려진다면 어디가 문제인지 식별해야 합니다. 단순히 CPU 나 메모리 이슈가 아닐수도 있음을 고려해야합니다.
- Disk I/O: 메시지 영속화를 위한 디스크 쓰기 속도 한계.
- Network Bandwidth: 노드 간 복제나 대량의 메시지 전송 시 발생하는 대역폭 부족.

카프카의 경우 파티션의 수를 늘릴수는 있지만 줄일 수는 없습니다. 이 점에 유의해야 합니다.
일반적으로 파티션의 수는 컨슈머의 수와 1:1 인 것이 좋지만, 파티션의 수가 컨슈머보다 많아질 경우 하나의 컨슈머에 여러 파티션이 연결될 수 있습니다. 따라서 골고루 배치될 수 있도록 그 배수(Ratio)를 고려해주는것이 좋겠습니다.

별도의 Outbox 테이블을 둬서 메시지가 쌓이기만 하고 처리가 안 되고 있지는 않은지 감시하는 것도 권장되는 운영 방식 중 하나입니다. 처리되지 않은 메시지가 유실되는 것도 방지할 수 있습니다.



[5] 메시지 지연 전송

때때로, 특정 시간 뒤에 메시지를 처리해야 하는 요구사항이 생기기도 하는데요. 이를 위해 어떤 방식을 사용할 수 있을까요?

책에서는 아래의 두가지 방식을 소개하는데 두가지 모두 컨셉이 재미있어서 알아두면 잘 활용할 수 있을 것 같습니다.

- 메시지 지연 전송 전용 메시지 큐 사용
- 계층적 타이밍 휠 사용 (논문)

추가적으로 RocketMQ 는 해당 기능을 자체적으로 지원한다고 합니다. (알리바바에서 만들어, 실제 알리 익스프레스 에서 사용중이라고 함.)



[6] 마무리

[Review] 시스템 디자인 스터디2 - 4주차 후기 - 이미지 3
스터디 사진 : )

스터디에서 더 많은 이야기를 나눴지만, 오늘은 여기서 마쳐보겠습니다. 이번 장은 서로 겪었던 실제 이슈에 대해서 이야기를 나눌 수 있었던 시간이었습니다.

우리 스터디에서는 실제 사례들을 통해 문제를 어떻게 해결해 나갔을까 많은 고민을 해보고 이야기를 나눠보고 있습니다. 이번주도 다들 열심히 참여해주셔서 더 풍성한 스터디가 될 수 있었습니다.


직접 스터디를 개설해보고 싶은 분이 계시다면, K-DEVCON에서 운영을  도와드리겠습니다. 데브콘의 '랩짱'에 도전하여 커뮤니티 성장을 함께 이끌어주세요! 운영진에게 DM 부탁드리겠습니다😉