이벤트 기반 아키텍처 구축하기

김하영·2025년 6월 13일

이벤트 기반 아키텍처란?

시스템 내 발생하는 이벤트를 기반으로 컴포넌트들이 통신하는 구조

왜 사용할까?

높은 비동기성느슨한 결합을 특징으로
이벤트 생산자와 소비자 사이의 직접적인 의존 관계를 제거할 수 있음.

이로 인해 시스템의 확장성과 유연성이 향상되며, 다양한 시스템 환경에 적용

주로 실시간 정보 처리가 중요한 시스템, 대규모 분산 시스템, 마이크로서비스 아키텍처 등에서 사용됨

이벤트 기반 아키텍처의 장점

이벤트 기반 아키텍처는 여러 가지 장점을 제공.

  1. 시스템 간의 결합도를 낮추어 개별 컴포넌트나 서비스의 변경이 전체 시스템에 미치는 영향을 줄임.

  2. 확장성 및 재사용성이 향상.

  3. 비동기 처리를 통해 시스템의 성능을 최적화

-> 왜냐하면 이벤트 처리가 동시에 이루어질 수 있으므로 병목 현상을 줄이고 시스템 전체의 처리량을 높일 수 있기 때문

  1. 유연한 시스템 통합이 가능.

이벤트 기반 아키텍처의 단점

  1. 시스템의 복잡도가 증가할 수 있음.
    -> 이벤트의 흐름을 추적하고 관리해야 하며 이벤트와 그에 대한 처리 로직을 분리해야함.

  2. 이벤트의 처리 순서를 보장하기 어려움.

  3. 데이터 일관성 유지가 어려움.

  4. 디버깅과 테스트가 어려울 수 있음.
    -> 비동기, 분산 시스템에서는 처리 순서가 보장되지 않기 때문에 추적이 어렵다.
    -> 따로 같은 요청에 대한 처리인지 각 스레드 단위마다 확인할 수 있는 키를 추가해야 한다.
    ( 예 : datadog trace id ..? )

이벤트 기반 아키텍처 적용을 위한 고려 사항

이벤트 기반 아키텍처를 성공적으로 적용하기 위해서는 아래 사항을 고려해야함.

  1. 시스템의 요구 사항과 목표를 명확히 해야함.

  2. 이벤트 설계와 모델링에 주의

  3. 이벤트 처리와 관련한 베스트 프랙티스와 패턴을 적용해야함.

  4. 시스템 전체의 관점에서 모니터링 및 로깅 전략을 수립.

실제 서비스 댓글 금칙어 판단 개선 시, 이벤트 기반 아키텍처 구축

  • 댓글 등록 시, 금칙어 판단 API를 통해 실시간으로 금칙어 판단하는 프로세스로 운영
    -> (서버) 댓글 등록 API <> (추천) 금칙어 판단 API
    -> 타 팀 API 끼리 강한 결합(Tight Coupling)
    -> 금칙어 판단 API 응답을 대기하고 판단 처리 후, 댓글 등록 완료 처리 되는 구조

만약 금칙어 판단 API 응답이 1분 뒤에 온다면??
댓글 등록 API 에서는 금칙어 판단 API 응답을 기다리다가 504 error 가 발생하게 될 것이다.

해결방안

  • Kafka 도입 및 이벤트 기반 아키텍처를 적용하여 각 팀의 결합도를 낮추는 방향 제안
  • 이벤트 규격 설계 및 댓글 금칙어 판단 / 차단 파이프라인 구축 및 프로세스 개발

위 작업을 기회로 kafka 이론만 학습했던 내용들을 실무에 적용할 수 있었고,
go 로 개발된 be 프로세스 단에서 Sarama client 를 통해 Pub-Sub 패턴으로 이벤트 기반 아키텍처를 구현했다.

이슈

  • 상용 배포 후,
    가끔 async producer 에서 Failed to produce message to topic 에러 발생.

원인

  • async producer 를 사용할 때는 saramaConfig.Metadata.RefreshFrequency 설정이 없으면 따로 백그라운드에서 클러스터 메타데이터를 새로고침하는 시간이 10m 으로 설정된다.

  • 댓글 등록 후, flush 관련 설정을 따로 하지 않아 1000개 메시지 또는 100ms 주기 중
    먼저 도달하는 조건이 발생하면 flush() 가 호출되어 데이터가 전송된다.


	// Flush 관련 설정 (default)
	saramaConfig.Producer.Flush.Messages = 1000        // 1000개 메시지
	saramaConfig.Producer.Flush.Frequency = 100 * time.Millisecond // 100ms마다 flush
	saramaConfig.Producer.Flush.Bytes = 0              // 크기 기준 flush 사용 안 함
  • async producer 가 아직 토픽, 파티션, 브로커 등 메타 데이터를 갱신 주기가 되지 않아
    반영되지 않은 메타 데이터가 있는 상태로 변경된 부분을 인지하지 못하는 경우가 생길 수 있다.

  • 댓글 등록 후, 해당 데이터를 async producer 가 지정된 토픽 파티션으로 send() 했을 때
    반영되지 않은 이전 버전의 메타 데이터 기준으로 메시지를 produce 하여 발생한 문제이다.
    (= 파티션 재조정 관련 정보를 가져오지 못한 걸로 판단됨. )

  • 참고 : https://www.tencentcloud.com/ko/document/product/597/45223

  • sarama trouble shooting 에 관련된 내용을 확인했을 때,
    Sarama 가 최신 파티션 정보를 가져오지 못하는 경우가 간헐적으로 발생하여
    메시지 보존 및 무작위 예외 보고를 유발하는 것을 발견했다.

  • 카프카 브로커의 파티션이 재조정 되었을 때, Sarama가 파티션 변경 사항을 감지하고
    현재 토픽의 메타데이터를 가져와 최신 파티션 데이터를 파싱하는데 약 10분이 소요된다.
    이 과정에 메시지 관련 예외가 발생할 수 있다.

  • 파티션 업데이트 감지 속도를 높이려면
    sarama.Metadata.RefreshFrequency 값을 줄이라는 가이드를 제공한다.

  • 추가로 Confluent-Kafka-Go 를 사용하는 걸로 해결하는 방식을 권장했다.

  • Confluent-Kafka-Go 는 안정성과 대량의 처리가 가능하다는 장점이 있지만,
    C 기반 라이브러리를 사용하므로 설정과 빌드 및 컴파일 관련 수정사항이 발생하고,
    현재 해당 문제를 해결하기 위해 도입하기에는 부담스러운 작업이라 판단되었다.

해결 방안

  • 즉, saramaClient 의 async producer 메시지 전송 시 broker 의 최신화된 메타 정보가 반영되지 않아 발생한 문제이므로 saramaConfig.Metadata.RefreshFrequency 30s 로 설정하여 메타 데이터 갱신 주기를 짧게 가져가도록 변경했다.

  • 추가로 flush 설정을 추가하여
    기존에 1000개 메시지 또는 100ms 마다 메시지를 전송하던 async producer 을 saramaConfig.Producer.Flush.Messages 를 10
    saramaConfig.Producer.Flush.Frequency 를 20s 로 설정하여
    최대 10개 메시지거나 20ms 마다 메시지를 전송하도록 변경했다.
    ( 기존에 메시지 flush 기준이 루즈했다고 판단함. )

saramaConfig.Producer.Flush.Messages = 10 // flush 메시지 수
saramaConfig.Producer.Flush.Frequency = time.Millisecond * 20 // flush 최대 시간
saramaConfig.Metadata.RefreshFrequency = 30 * time.Second 
// 백그라운드에서 클러스터 메타데이터를 새로고침하는 시간
// 30초마다 메타데이터 새로고침을 위해 network 연결 & 메타데이터 가져오므로 계속 network 연결 유지됨.
// async producer 쓸 땐 꼭 넣어야함.
  • AS-IS
    -> 1000개 메시지 또는 100ms 마다 메시지를 전송
    -> broker 에 대한 메타 데이터는 10분 마다 갱신
  • TO-BE
    -> flush 설정을 추가하여 최대 10개 메시지거나 20ms마다 메시지를 전송
    -> broker 에 대한 메타 데이터는 30초 마다 갱신

적당한 주기로 메시지를 flush 하고
메타 데이터를 갱신하여 안정적으로 이벤트를 전송하도록 변경했다.
( 댓글 입력 TPS 가 10 정도로 트래픽이 많지 않음 )

회고

위 이슈를 해결하면서 Confluent‑Kafka‑Go 를 사용하는 서비스들은 어떻게 구현했을까?
궁금함이 생기긴 했다.

Confluent‑Kafka‑Go 를 사용하는 서비스는 뭐가 있을까?

ChatGPT said:
Confluent-Kafka-Go는 높은 성능과 안정성을 제공하는 Kafka 클라이언트로, 다양한 산업과 서비스를 위해 사용되고 있습니다. 주로 고성능, 고가용성, 실시간 데이터 스트리밍을 필요로 하는 시스템에서 많이 활용되죠.

다음은 Confluent-Kafka-Go를 사용하는 대표적인 서비스와 기업 예시입니다:

1. LinkedIn

용도: LinkedIn은 Kafka의 창시자 중 하나로, 대규모 실시간 이벤트 스트리밍 시스템을 운영하고 있습니다.

특징: LinkedIn의 시스템은 수백억 건의 이벤트를 매일 처리하며, Kafka를 사용하여 실시간으로 데이터를 수집하고 분석합니다.

Confluent-Kafka-Go 사용 이유: 실시간 데이터 파이프라인 및 고속 메시징 시스템을 위해 Kafka를 활용, Go 언어로 작성된 서비스들이 Kafka 클러스터와 통합되어 빠른 이벤트 처리와 안정성 높은 데이터를 전달합니다.

2. Uber

용도: Uber는 분산 트랜잭션, 모니터링 시스템 및 실시간 지표 추적을 위해 Kafka를 사용합니다.

특징: Kafka는 Uber의 고급 메시징 시스템에서 핵심 역할을 하며, 사용자 트래픽과 실시간 위치 정보를 전송하는 데 사용됩니다.

Confluent-Kafka-Go 사용 이유: Uber의 Go 서비스와 Kafka 클러스터 간의 고성능 메시지 전송을 지원하여 스케일링과 신뢰성을 보장합니다.

3. Netflix

용도: Netflix는 Kafka를 사용하여 비디오 스트리밍 분석, 사용자 피드백 수집, 알림 시스템 등을 처리합니다.

특징: Netflix의 시스템은 고속 메시징을 요구하며, Kafka 클러스터는 실시간 데이터 분석, 로그 수집 및 트래픽 처리에 사용됩니다.

Confluent-Kafka-Go 사용 이유: Go로 작성된 일부 서비스들이 Confluent-Kafka-Go를 통해 Kafka와 통합되어 빠르고 안정적인 데이터 스트리밍을 제공합니다.

4. Airbnb

용도: Airbnb는 예약 처리 시스템, 리얼타임 알림 및 로그 집합을 위해 Kafka를 사용합니다.

특징: 실시간 예약 정보, 고객 피드백 및 시스템 로그를 처리하는데 Kafka를 활용하며, 대규모 분산 시스템에서 스케일링 및 신뢰성을 보장합니다.

Confluent-Kafka-Go 사용 이유: Go 기반의 서비스들이 Kafka를 통해 빠르게 데이터를 전송하고 소비할 수 있도록 하여, 높은 성능과 실시간성을 제공하고 있습니다.

5. Spotify

용도: Spotify는 사용자 활동 트래킹, 추천 알고리즘, 실시간 이벤트 처리 등을 Kafka를 통해 처리합니다.

특징: Kafka는 실시간 데이터 스트리밍, 분석, 추천 시스템에서 중요한 역할을 합니다. Spotify의 대규모 시스템에서 Kafka는 안정적인 이벤트 스트리밍을 제공합니다.

Confluent-Kafka-Go 사용 이유: Go 서비스들이 Kafka와 통합되어 빠르고 안정적인 데이터 전송과 실시간 데이터 처리를 가능하게 합니다.

6. Pinterest

용도: Pinterest는 사용자 활동, 게시물 추천, 알림 시스템 등에 Kafka를 사용합니다.

특징: 사용자 활동을 추적하고 추천 시스템에 필요한 데이터를 처리하며, Kafka는 Pinterest의 실시간 데이터 파이프라인에서 핵심적인 역할을 합니다.

Confluent-Kafka-Go 사용 이유: Go로 구현된 서비스들이 Kafka를 통해 고속 메시징과 실시간 스트리밍을 효과적으로 처리할 수 있습니다.

7. Slack

용도: Slack은 메시징 시스템, 알림, 이벤트 추적을 위해 Kafka를 사용합니다.

특징: Slack의 채팅 메시지 및 알림 시스템에서 Kafka가 실시간 데이터를 처리하는 데 중요한 역할을 하며, 메시지 지연 없이 빠르게 알림을 전달합니다.

Confluent-Kafka-Go 사용 이유: Go로 작성된 서비스들이 Kafka 클러스터와 고속으로 통신하고, 실시간 알림 시스템에서 낮은 지연을 유지합니다.

8. Goldman Sachs

용도: 금융 데이터 스트리밍, 실시간 거래 데이터 분석을 위해 Kafka를 사용합니다.

특징: 실시간 금융 데이터를 처리하는 데 Kafka가 사용되며, 거래 정보 및 시장 데이터의 흐름을 실시간으로 처리합니다.

Confluent-Kafka-Go 사용 이유: 고속 금융 데이터 스트리밍이 필요한 시스템에서 Kafka와 Go 클라이언트(Confluent-Kafka-Go)를 통해 신속한 데이터 처리가 이루어집니다.


🚀 Confluent-Kafka-Go 사용 이유

높은 성능: Confluent-Kafka-Go는 librdkafka를 기반으로 하여 C 언어로 작성된 Kafka 클라이언트의 성능을 그대로 가져올 수 있습니다.

고급 Kafka 기능 지원: Exactly Once Semantics(강력한 트랜잭션 지원) 및 압축, 파티셔닝, 리밸런싱과 같은 고급 Kafka 기능을 제공하여, 다양한 애플리케이션에서 안정성과 성능을 보장합니다.

실시간 데이터 처리: 대규모 실시간 데이터를 처리하는 데 뛰어난 성능을 발휘하고, 다양한 메시징 패턴을 효율적으로 지원합니다.

낮은 레이턴시: 낮은 메시지 지연을 제공하여, 실시간으로 데이터가 필요한 시스템에 이상적입니다.

실무에서 절대로 데이터가 유실되면 안되는 케이스나 대규모 실시간 데이터를 다룰 때,
Confluent-Kafka-Go 를 도입해보면 좋을 것 같다.
( 그런 기회가 있으면 좋겠다..! )

회고

  • 타 팀과의 연계는 느슨한 결합으로 진행한다.
    ( 초반 설계부터 위 원칙으로 접근했다면, 여러번 작업할 일이 없었을 것이다.. )

  • 이벤트 규격 설계나 golang 으로 be 프로세스 개발하는 건 재미있었다.
    ( 이전에 학습했던 이론들을 다시 복기시키는 맛으로..했다..like 할.머.니 )

  • kafka 나 golang 에 대해 단순하게 책 한권 읽고 바로 실무 작업을 하다보니 예상하지 못하던 실수들이 있었다.
    ( 공부 좀 했다고 겁도 없이 신나서 업무에 적용했더니.. 하나를 쓰더라도 제대로 알고 쓰자 )

위 영상을 보면서 내가 잘못된 방식으로 학습을 하고 업무를 진행했구나.. 현타가 왔다.

열정과 노력에 비해 좋지 않은 output 을 보면서, '아무튼 난 해냈다.' 로 혼자 위로하고 있었지만,
잘못된 방식으로 업무를 하고 있었고 그게 팀원들에게 피해가 간다는 점을 뒤늦게 알게되었다.

습관적으로 학습하고 실제 튜토리얼 코드를 짜는 작업을 반복하는 방식을 적용하고 실무에 적용하자.

  • 트래픽이 엄청난 기능에 도입한 게 아니라서 rabbitMq 를 활용해서 해결하는 방안이 더 좋지 않았을까? 라는 생각도 든다. ( 2026.01.19 )
항목RabbitMQKafka
성격메시지 브로커 (Message Queue)분산 이벤트 스트리밍 플랫폼
핵심 목적작업 전달·비동기 처리대용량 이벤트 저장·재처리
메시지 수명소비되면 사라짐디스크에 장기 보관
처리 방식Push 기반Pull 기반

-> 댓글 금칙어 판단은 비동기 처리를 위해 kafka 를 도입 했으나,
매우 많은 트래픽이 들어오는 기능도 아니고 메시지가 소비되서 사라져도 그리 크리티컬 하지 않다.
-> 카프카 도입을 하고 싶어 일을 키운 느낌이란 생각도 든다..
-> 그래도 자랑스럽다...

profile
Developer

0개의 댓글