당신의 마이크로서비스는 확장되지 않는다. 당신의 데이터베이스는 울고 있다.

발행: (2026년 2월 5일 오전 06:24 GMT+9)
8 min read
원문: Dev.to

Source: Dev.to

숨겨진 병목 현상

우리는 처음에 “아마 복제본을 더 늘려야 할지도 몰라”라며 명백한 원인을 제외한 모든 것을 탓했습니다.
하지만 진실은 더 간단하고 불편했습니다: 우리 마이크로서비스가 문제가 아니었습니다.

마이크로서비스는 “시스템의 각 부분을 독립적으로 확장한다”는 매혹적인 아이디어를 판매합니다. 실제로 대부분의 팀은 다음과 같이 합니다:

  1. 애플리케이션을 10~20개의 서비스로 나눈다.
  2. 모든 서비스를 동일한 데이터베이스에 연결한다.
  3. 이를 “마이크로서비스 아키텍처”라고 부른다.

그 결과는 네트워크 지연이 있는 분산 모놀리식이 됩니다. 각 서비스는 수평적으로 확장될 수 있지만, 모든 트래픽이 여전히 같은 병목으로 모입니다. 부하가 증가하면 데이터베이스가 혼란에 빠지고, 마이크로서비스가 문제가 되는 것이 아닙니다.

증상

  • 오류나 크래시 없이 지연이 급증한다.
  • 연결 수 증가, 읽기 복제본 지연, 연결 풀 최대치 도달.
  • 아무도 모니터링하지 않는 곳에서 락이 쌓인다.

단독으로 보면 무해해 보이는 일반적인 변경 사항들이 함께하면 재앙이 됩니다:

서비스변경 내용추가 쿼리
A새로운 엔드포인트+3 쿼리
B“그냥 조인”+2 쿼리
C5초마다 폴링

확장의 효과

서비스를 2개의 파드에서 20개의 파드로 확장한다는 것은 단순히 처리량을 곱하는 것이 아니라 다음을 곱합니다:

  • 열린 연결 수
  • 유휴 트랜잭션
  • 동시 쓰기
  • 캐시 미스
  • 락 경쟁

데이터베이스는 각 파드를 새로운 낯선 사람처럼 여기며, 대시보드에 “서비스 지연은 괜찮아 보인다”고 표시돼도 공격적으로 주의를 요구합니다.

캐싱 유혹

대부분의 팀이 추가합니다:

  • 읽기를 위한 Redis
  • 감정적으로 선택한 TTL을 가진 HTTP 캐시

캐싱은 시스템을 빠르게 만들지만… 결국 그렇지 않게 됩니다. 이유는:

  • 쓰기는 여전히 같은 데이터베이스를 거친다
  • 캐시 무효화가 금세 복잡해진다
  • 서비스 간 데이터 일관성이 추측 게임이 된다
  • 운영 복잡도는 증가하지만 결합은 사라지지 않는다

캐싱은 치료제가 아니라 진통제에 불과합니다.

문제를 해결하지 못한 시도

  • 더 큰 데이터베이스 인스턴스
  • 더 많은 복제본
  • 높은 연결 제한
  • 스탠드업에서 “쿼리 최적화”를 외치기

도움이 된 방법

각 서비스가 자신의 데이터를 소유한다. 이것이 전부입니다.

다른 서비스가 그 데이터를 필요로 하면 반드시:

  • API를 호출하거나, 또는
  • 이벤트를 소비하거나, 또는
  • 목적에 맞게 만든 읽기 모델에서 읽어야 합니다.

“서비스 간에 이 조인 하나만 하면 된다”는 식은 데이터베이스 고통을 다시 불러옵니다.

우리는 동기식 의존성을 다음으로 교체했습니다:

  • 이벤트
  • 비동기 워크플로우
  • 최종 일관성 업데이트

모든 것이 즉시일 필요는 없습니다; 대부분의 시스템은 신뢰성이 필요합니다.

사고 방식의 전환

“이 서비스가 확장될 수 있는가?” 대신에 “트래픽이 10배가 되면 데이터베이스에 어떤 영향을 미치는가?”를 묻습니다. 이 한 가지 질문이 우리의 아키텍처 리뷰를 완전히 바꾸었습니다.

마이크로서비스가 자동으로 확장성을 제공하는 것은 아닙니다. 옵션을 제공할 뿐이며, 규율이 필요합니다. 엄격한 경계가 없으면 데이터베이스 문제를 해결하기보다 오히려 증폭시킵니다.

주요 시사점

  • 데이터를 소유하라. 각 서비스는 자체 스키마 또는 데이터베이스를 가져야 합니다.
  • 서비스 간 공유 테이블을 피하라; 이는 숨은 결합을 만들기 때문입니다.
  • 트래픽 패턴을 설계하라. 파드 확장이 데이터베이스 부하를 어떻게 곱하는지 이해하라.
  • 비동기 통신을 선호하고, 동기식 조인을 최소화하라.
  • 데이터베이스 건강(연결 수, 복제 지연, 락 경쟁)을 일류 관심사로 모니터링하라.

시스템이 트래픽이 증가할 때마다 느려진다면, 서비스만 보지 말고 다음을 살펴보세요:

  1. 누가 데이터를 소유하고 있는가?
  2. 몇 개의 서비스가 같은 테이블을 건드리는가?
  3. 파드 확장이 데이터베이스 부하를 어떻게 곱하는가?
  4. 아키텍처가 트래픽 패턴에 맞는가?

왜냐하면 10번 중 9번은 “마이크로서비스가 확장되지 않는다”는 경우가 실제로는 데이터베이스가 도움을 외치고 있기 때문입니다.

Back to Blog

관련 글

더 보기 »

gRPC 구현

gRPC는 Google에서 개발한 프레임워크로, 효율적이고 언어에 독립적인 메커니즘을 제공하여 Remote Procedure Calls(RPC)를 수행할 수 있게 합니다. 주요 사용 사례는…