← 학습 카테고리

Learn

Kafka

42개 모듈 · 현재 2번째

Kafka 모듈 2/42 kafka-learn-02

Kafka를 선택하는 이유와 탄생 배경

Kafka: The Definitive Guide (O'Reilly, 2017, 1st Edition) — Neha Narkhede, Gwen Shapira, Todd Palino Chapter 1: Meet Kafka — Why Kafka? ~ Getting Started with Kafka (pp.10-16)

여러 pub/sub 후보 중 Kafka를 고르게 만드는 다섯 가지 특성(다중 프로듀서, 다중 컨슈머, 디스크 기반 리텐션, 확장성, 고성능)을 정리하고, Kafka가 데이터 생태계에서 맡는 역할과 대표적인 사용 사례를 살펴본다. 마지막으로 LinkedIn이 겪었던 구체적인 문제와 그 해결로서 Kafka가 태어난 과정, 오픈소스 연혁을 다룬다.

왜 Kafka인가 — 다섯 가지 특성

다중 프로듀서. Kafka는 클라이언트가 여러 토픽을 쓰든 같은 토픽을 쓰든 상관없이 여러 프로듀서를 매끄럽게 처리한다. 덕분에 여러 프론트엔드 시스템의 데이터를 모아 일관되게 만들기 좋다. 예를 들어 여러 마이크로서비스로 콘텐츠를 제공하는 사이트는 페이지뷰용 토픽 하나를 두고 모든 서비스가 공통 포맷으로 쓰게 할 수 있다. 그러면 컨슈머 애플리케이션은 서비스마다 하나씩인 여러 토픽을 조율해 소비할 필요 없이 사이트 전체의 페이지뷰 스트림 하나만 받으면 된다.

다중 컨슈머. Kafka는 하나의 메시지 스트림을 여러 컨슈머가 서로 간섭 없이 읽도록 설계되었다. 이는 한 클라이언트가 메시지를 소비하면 다른 클라이언트가 더 이상 그 메시지를 볼 수 없는 많은 큐잉 시스템과 대조된다. 동시에 여러 Kafka 컨슈머가 하나의 그룹으로 묶여 스트림을 나눠 갖고, 그룹 전체로는 특정 메시지를 한 번만 처리하도록 할 수도 있다.

디스크 기반 리텐션. 메시지가 디스크에 커밋되고 설정 가능한 리텐션 규칙에 따라 저장되므로 컨슈머가 항상 실시간으로 동작할 필요가 없다. 처리가 느려지거나 트래픽이 몰려 컨슈머가 뒤처져도 데이터가 유실될 위험이 없다. 컨슈머 애플리케이션을 잠시 내려 유지보수를 해도 프로듀서 쪽에 메시지가 밀리거나 유실될 걱정이 없다. 컨슈머를 멈춰도 메시지는 Kafka에 남아 있어, 재시작하면 멈춘 지점부터 데이터 유실 없이 이어서 처리할 수 있다.

확장성. 개념 증명은 브로커 하나로 시작해, 개발 클러스터는 브로커 셋으로, 프로덕션은 수십에서 수백 대 규모로 데이터 증가에 맞춰 확장할 수 있다. 확장 작업은 클러스터가 온라인인 상태에서 시스템 전체 가용성에 영향 없이 수행할 수 있다. 이는 곧 여러 브로커로 구성된 클러스터가 개별 브로커의 장애를 견디며 계속 클라이언트에 서비스할 수 있다는 뜻이기도 하다. 동시 장애를 더 많이 견뎌야 한다면 복제 계수를 높이면 된다.

고성능. 위 특성들이 결합되어 Kafka는 높은 부하에서도 뛰어난 성능을 낸다. 프로듀서, 컨슈머, 브로커를 모두 스케일 아웃해 아주 큰 메시지 스트림을 다루면서도 메시지 생성부터 컨슈머가 볼 수 있게 되기까지 1초 미만의 지연을 제공한다.

핵심 포인트

  • 다중 프로듀서: 여러 프론트엔드의 데이터를 하나의 공통 포맷 토픽으로 집약
  • 다중 컨슈머: 소비해도 메시지가 사라지지 않으며, 그룹으로 묶으면 그룹 단위 1회 처리
  • 디스크 기반 리텐션: 컨슈머가 뒤처지거나 잠시 내려가도 유실 없음
  • 확장성: 온라인 상태로 확장 가능, 브로커 장애를 견딤
  • 고성능: 대규모 스트림에서도 subsecond 지연

데이터 생태계에서의 역할과 사용 사례

Apache Kafka는 데이터 생태계의 순환계 역할을 한다. 인프라의 여러 구성원 사이에서 메시지를 실어 나르며 모든 클라이언트에게 일관된 인터페이스를 제공한다. 메시지 스키마를 제공하는 시스템과 결합하면 프로듀서와 컨슈머는 더 이상 강하게 결합되거나 직접 연결될 필요가 없다. 비즈니스 요구에 따라 컴포넌트를 추가하거나 제거할 수 있고, 프로듀서는 누가 그 데이터를 쓰는지, 소비 애플리케이션이 몇 개인지 신경 쓸 필요가 없다.

활동 추적(Activity tracking). LinkedIn에서 Kafka가 설계된 원래 사용 사례다. 사용자가 프론트엔드 애플리케이션과 상호작용하면 그 행동에 관한 메시지가 생성된다. 페이지뷰나 클릭 추적 같은 수동적 정보일 수도 있고, 프로필에 정보를 추가하는 것 같은 더 복잡한 행동일 수도 있다. 이 메시지들은 하나 이상의 토픽에 게시되어 백엔드 애플리케이션이 소비하며, 리포트 생성·머신러닝 시스템 공급·검색 결과 갱신 등에 쓰인다.

메시징. 사용자에게 이메일 같은 알림을 보내야 할 때도 쓰인다. 생성하는 애플리케이션은 포맷이나 실제 발송 방법을 신경 쓰지 않고 메시지만 만들면 되고, 하나의 애플리케이션이 모든 발송 메시지를 읽어 공통된 룩앤필로 포맷팅(decorating)하고, 여러 메시지를 하나의 알림으로 모으고, 사용자의 수신 선호를 적용하는 일을 일관되게 처리한다. 이렇게 하면 여러 애플리케이션에 기능이 중복되는 것을 피하고, 다른 방식으로는 불가능한 집계 같은 연산도 가능해진다.

메트릭과 로깅. 애플리케이션과 시스템 메트릭·로그 수집에도 이상적이다. 여러 애플리케이션이 같은 유형의 메시지를 생성한다는 특성이 빛을 발하는 사례다. 메트릭은 모니터링·알림 시스템이 소비할 수도 있고, Hadoop 같은 오프라인 시스템에서 성장 예측 같은 장기 분석에 쓸 수도 있다. 로그 메시지도 같은 방식으로 게시해 ElasticSearch 같은 전용 로그 검색 시스템이나 보안 분석 애플리케이션으로 라우팅할 수 있다. 목적지 시스템을 교체해야 할 때 프론트엔드 애플리케이션이나 집계 방식을 바꾸지 않아도 된다는 점이 추가 이점이다.

커밋 로그. Kafka는 commit log 개념에 기반하므로 데이터베이스 변경을 Kafka에 게시하고 애플리케이션이 이 스트림을 감시해 실시간 업데이트를 받을 수 있다. 이 changelog 스트림은 원격 시스템으로 DB 업데이트를 복제하거나 여러 애플리케이션의 변경을 하나의 DB 뷰로 통합하는 데도 쓸 수 있다. durable 리텐션은 changelog의 버퍼 역할을 해서 소비 애플리케이션이 실패해도 재생할 수 있게 해 준다. 로그 컴팩션 토픽을 쓰면 키당 하나의 변경만 남겨 더 긴 리텐션을 제공할 수 있다.

스트림 처리. Kafka 사용의 거의 전부를 스트림 처리로 볼 수도 있지만, 보통 이 용어는 Hadoop의 map/reduce와 비슷한 기능을 제공하는 애플리케이션을 가리킨다. Hadoop이 몇 시간에서 며칠 단위의 긴 시간 프레임으로 데이터를 집계하는 데 의존한다면, 스트림 처리는 메시지가 생성되는 즉시 실시간으로 처리한다. 메트릭 카운팅, 다른 애플리케이션의 효율적 처리를 위한 메시지 파티셔닝, 여러 소스의 데이터를 이용한 메시지 변환 같은 작업을 작은 애플리케이션으로 작성할 수 있다.

핵심 포인트

  • Kafka는 데이터 생태계의 '순환계' — 모든 클라이언트에 일관된 인터페이스 제공
  • 활동 추적이 LinkedIn에서의 원래 사용 사례
  • 메트릭/로깅에서는 목적지 시스템을 바꿔도 프론트엔드를 건드릴 필요가 없다
  • 커밋 로그 사용 사례에서 로그 컴팩션은 키당 최종 변경만 남겨 긴 리텐션을 가능하게 한다

LinkedIn의 문제와 Kafka의 탄생

Kafka는 LinkedIn의 데이터 파이프라인 문제를 풀기 위해 만들어졌다. 여러 유형의 데이터를 다루면서 사용자 활동과 시스템 메트릭에 대한 깔끔하고 구조화된 데이터를 실시간으로 제공하는 고성능 메시징 시스템이 목표였다.

당시 LinkedIn에는 두 개의 서로 다른 시스템이 있었다. 하나는 커스텀 수집기와 오픈소스 도구로 데이터를 저장·표현하던 시스템·애플리케이션 메트릭 수집 시스템이다. CPU 사용률이나 애플리케이션 성능 같은 전통적 메트릭 외에, 단일 사용자 요청이 내부 애플리케이션들을 어떻게 흘러가는지 들여다볼 수 있는 정교한 요청 추적 기능도 있었다. 그러나 결함이 많았다 — 폴링 기반 메트릭 수집, 메트릭 간 긴 간격, 애플리케이션 소유자가 자기 메트릭을 직접 관리할 수 없음. 단순한 작업에도 사람 손이 필요한 high-touch 시스템이었고, 같은 측정값인데 시스템마다 메트릭 이름이 다른 등 일관성도 없었다.

다른 하나는 사용자 활동 추적 시스템이었다. 프론트엔드 서버가 주기적으로 접속해 XML 형식 메시지 배치를 게시하는 HTTP 서비스였고, 이 배치들은 오프라인 처리로 옮겨져 파싱·대조되었다. 역시 결함이 많았다 — XML 포맷이 일관되지 않고 파싱이 계산 비용이 컸다. 추적하는 사용자 활동 유형을 바꾸려면 프론트엔드와 오프라인 처리 사이에 상당한 협업이 필요했고, 그러고도 스키마 변경 때문에 시스템이 계속 깨졌다. 시간 단위 배치로 만들어져 실시간으로 쓸 수 없었다.

모니터링과 활동 추적은 같은 백엔드 서비스를 쓸 수 없었다. 모니터링 서비스는 너무 투박했고 데이터 포맷이 활동 추적에 맞지 않았으며, 모니터링의 폴링 모델은 추적의 푸시 모델과 맞지 않았다. 반대로 추적 서비스는 메트릭에 쓰기에 너무 취약했고 배치 지향 처리는 실시간 모니터링·알림에 맞는 모델이 아니었다. 그러나 두 데이터는 공통점이 많았고, '특정 유형의 사용자 활동이 애플리케이션 성능에 어떤 영향을 주는가' 같은 상관 분석이 매우 바람직했다. 특정 사용자 활동의 감소는 그것을 서비스하는 애플리케이션의 문제를 시사할 수 있는데, 활동 배치 처리에 몇 시간씩 걸리면 대응이 느려진다.

먼저 기성 오픈소스 솔루션들을 철저히 검토했다. ActiveMQ로 프로토타입을 만들었지만 당시로서는 필요한 규모를 감당하지 못했다. LinkedIn의 사용 방식에는 취약한 해법이었고, 브로커가 멈추게 만드는 많은 결함이 발견되었다. 브로커가 멈추면 클라이언트 연결이 밀려 애플리케이션이 사용자 요청을 처리하지 못하게 된다. 결국 데이터 파이프라인을 위한 커스텀 인프라를 만들기로 결정했다.

LinkedIn의 개발팀은 앞서 분산 키-값 저장소 Voldemort의 개발과 오픈소스 공개를 담당했던 principal software engineer Jay Kreps가 이끌었다. 초기 팀에는 Neha Narkhede가 있었고 이후 Jun Rao가 합류했다. 이들이 세운 주요 목표는 다음과 같았다.

- push-pull 모델을 사용해 프로듀서와 컨슈머를 분리한다 - 여러 컨슈머를 지원하기 위해 메시징 시스템 안에 메시지 데이터의 영속성을 제공한다 - 메시지의 높은 처리량에 최적화한다 - 데이터 스트림이 커짐에 따라 시스템이 수평 확장될 수 있게 한다

결과물은 메시징 시스템의 전형적인 인터페이스를 가지면서 저장 계층은 로그 집계 시스템에 가까운 publish/subscribe 메시징 시스템이었다. 메시지 직렬화에 Apache Avro를 채택하면서, Kafka는 하루 수십억 건 규모에서 메트릭과 사용자 활동 추적을 모두 효과적으로 처리했다. LinkedIn의 사용량은 2015년 8월 기준 하루 1조 건 이상의 메시지 생성과 페타바이트 이상의 데이터 소비까지 성장했다.

핵심 포인트

  • 모니터링 시스템(폴링, high-touch, 이름 불일치)과 활동 추적 시스템(XML, 시간 단위 배치, 스키마 변경에 취약)의 결함
  • 두 데이터를 상관 분석하고 싶었으나 푸시/폴링 모델과 배치/실시간 요구가 서로 맞지 않았다
  • ActiveMQ 프로토타입은 당시 규모를 감당 못 했고 브로커가 멈추는 결함이 있었다
  • 초기 설계 목표 4가지: push-pull 분리, 영속성, 높은 처리량, 수평 확장
  • 2015년 8월 기준 LinkedIn에서 하루 1조 건 이상 생성, 페타바이트 이상 소비

오픈소스 연혁과 이름의 유래

Kafka는 2010년 말 GitHub에 오픈소스 프로젝트로 공개되었다. 오픈소스 커뮤니티에서 주목받기 시작하면서 2011년 7월 Apache Software Foundation 인큐베이터 프로젝트로 제안·채택되었고, 2012년 10월 인큐베이터를 졸업했다. 이후 LinkedIn 밖에서도 견고한 컨트리뷰터·커미터 커뮤니티가 형성되었고, Kafka는 세계에서 가장 큰 데이터 파이프라인 몇몇에서 사용되고 있다.

2014년 가을, Jay Kreps, Neha Narkhede, Jun Rao는 LinkedIn을 떠나 Apache Kafka에 대한 개발·엔터프라이즈 지원·교육을 제공하는 회사인 Confluent를 설립했다. 두 회사와 오픈소스 커뮤니티의 기여가 계속되며 Kafka를 빅데이터 파이프라인의 첫 번째 선택지로 만들고 있다.

이름의 유래에 대해 Jay Kreps는 이렇게 설명했다 — 'Kafka는 쓰기(writing)에 최적화된 시스템이므로 작가의 이름을 쓰는 게 말이 된다고 생각했다. 대학에서 문학 수업을 많이 들었고 Franz Kafka를 좋아했다. 게다가 오픈소스 프로젝트 이름으로 멋있게 들렸다.' 즉 애플리케이션 자체와의 관련성은 거의 없다.

핵심 포인트

  • 2010년 말 GitHub 공개 → 2011년 7월 Apache 인큐베이터 → 2012년 10월 졸업
  • 2014년 가을 Confluent 창업 (인큐베이터 졸업 시점과 혼동 주의)
  • 이름은 '쓰기에 최적화된 시스템이니 작가 이름' + Franz Kafka 선호에서 유래

이 모듈과 연관된 문항 1개가 문제 은행에 있습니다.

이 내용으로 문제 풀어보기