우리팀은 카프카를 어떻게 사용하고 있을까

May.30.2024 김나은

Backend

누가 읽으면 좋을까?

카프카(Kafka)가 무엇인지 알고 있는 독자를 대상으로 합니다. 기술적 구현방식을 다루기보단 카프카를 기반으로 한 다양한 기술적 개념에 대해서 얇고 넓게 소개하고, 우리팀에서 어떻게 적용하는지 사례를 공유합니다. 기술적 내용에 대해 자세히 알고 싶다면 공식문서나 다른 기술블로그를 참고해 주세요. 글 하단 "참고 자료"에 관련 링크도 첨부하였습니다.

아래와 같은 키워드가 등장합니다. 각 문단에서 개념을 간단하게 설명하며 진행할 예정이나 관련 배경지식이 있다면 더 쉽게 이해할 수 있을 것으로 예상됩니다.

  • Kafka
  • Transactional Outbox Pattern
  • Event Bus
  • Kafka Streams

카프카, 한 섹션 요약

먼저 카프카를 매우 간단하게 알아보겠습니다. 카프카는 분산 스트리밍 플랫폼으로, 대량의 데이터를 처리하고 실시간으로 전송하는 데 사용됩니다. 모든 데이터는 로그 형식으로 파일 시스템에 기록됩니다. 여기서 말하는 로그는 추가만 가능하며, 시간순으로 완전히 정렬된 데이터의 흐름(레코드 시퀀스)을 의미합니다. 로그를 한곳에 모아 처리할 수 있도록 중앙집중화되어 있으며, 대용량 데이터를 수집하고 실시간 스트리밍으로 소비가 가능합니다.

메시지(레코드)는 발행처(프로듀서)가 보낸 순서로 기록되어 순서가 보장되며, 메시지의 위치 값(offset)으로 소비자(컨슈머)가 소비한 메시지의 위치를 표시합니다. 각 컨슈머 그룹마다 메시지의 위치 값을 가지고 있기 때문에 같은 소스에서 서로 다른 여러 개의 컨슈머 그룹이 개별적으로 소비가 가능합니다. 한 소스(Single Origin)에서 여러 소비자가 손실이나 변형 없이 메시지를 소비할 수 있으며, 원천 데이터를 기반으로 데이터 분석도 가능합니다.

아래는 이 글을 이해하는 데 필요한 카프카의 기본적인 용어와 개념입니다.

  • 토픽(Topic): 데이터의 주제를 나타내며, 이름으로 분리된 로그입니다. 메시지를 보낼 때는 특정 토픽을 지정합니다.
  • 파티션(Partition): 토픽은 하나 이상의 파티션으로 나누어질 수 있으며, 각 파티션은 순서가 있는 연속된 메시지의 로그입니다. 파티션은 병렬 처리를 지원하고, 데이터의 분산 및 복제를 관리합니다.
  • 레코드(Record): 레코드는 데이터의 기본 단위로 키와 값(key-value pair) 구성입니다.
  • 오프셋(Offset): 특정 파티션 내의 레코드 위치를 식별하는 값입니다.
  • 프로듀서(Producer): 데이터를 토픽에 보내는 역할을 하며, 메시지를 생성하고 특정 토픽으로 보냅니다.
  • 컨슈머(Consumer):토픽에서 데이터를 읽는 역할을 하며, 특정 토픽의 메시지를 가져와서(poll) 처리합니다. 컨슈머 그룹은 여러 개의 컨슈머 인스턴스를 그룹화하여 특정 토픽의 파티션을 공유하도록 구성합니다. 이를 통해 데이터를 병렬로 처리하고 처리량을 증가시킬 수 있습니다.
  • 카프카 커넥터(Connector): 카프카와 외부 시스템을 연동 시 쉽게 연동 가능하도록 하는 프레임워크로 MySQL, S3 등 다양한 프로토콜과 연동을 지원합니다.
    • 소스커넥터(source connector): 메시지 발행과 관련 있는 커넥터
    • 싱크커넥터(sink connector): 메시지 소비와 관련 있는 커넥터

concept of kafka

우리팀에서 활용하는 방식

딜리버리서비스팀은 하루 100만 건 이상 생성되는 배민배달(배달의 민족에서 관리하는 자체 배달)을 중계하는 역할을 합니다. 배달의 민족에서 제공하는 여러 주문서비스(배민배달, B마트, 배민스토어)의 배민배달을 받아 여러 배달서비스 중 하나로 분배하고, 배달과정을 중계하고 관리하는 역할을 합니다. 주문과 배달을 처리하는 방식으로 분산시스템 이벤트 기반 아키텍처를 사용하고 있으며, 카프카를 팀에서 주요 기술 중 하나로 사용하고 있습니다. 팀의 분산시스템이 어떻게 나뉘어 있는지 간략하게 설명하고, 카프카를 팀에서 활용하는 방식을 소개하겠습니다.

딜리버리서비스팀의 분산서버 구조에 대해 간략하게 설명하면 아래 그림과 같습니다.

delivery service team system

주문이벤트를 받아 배달 프로세스를 관리하는 주문/배달서버, 발행한 이벤트를 기반으로 분석하는 분석서버로 구성되어 있습니다. 처리량을 높이고 성능을 향상시키기 위해 많은 서비스에서 그러하듯 각 서버그룹은 N개의 여러 서버로 구성됩니다.

[1] 주문-배달을 안전하게 처리하자

미리보기

– 도메인 이벤트에 대해 카프카를 이벤트 브로커로 사용하여 이벤트 순서를 보장한다.
– MySQL source connector를 이용한 Transactional Outbox Pattern을 사용하여 분산시스템에서 데이터와 메시지 전송을 하나의 트랜잭션으로 관리하여 데이터 정합성을 확보한다.

주문이 발생하면 고객에게 배달이 완료될 때까지 안전하게 처리하는 것이 가장 큰 목표입니다. 그 과정을 혼란스럽지 않게 처리하기 위해서는 주문과 배달의 이벤트 순서가 중요하며, 이벤트가 누락되지 않도록 관리해야 합니다. 카프카를 이벤트 브로커로 사용하고, 이벤트 발생 순서를 보장하고 있습니다. 배달을 놓치지 않고 처리하기 위해서 Transactional Outbox Pattern을 사용하여 순서를 보장한 재시도를 통해 이벤트 누락이 없도록 처리하고 있습니다.

순서보장

배달프로세스를 간략하게 나타내면 아래 그림과 같습니다. 배달이 진행되면서 여러 이벤트가 발행되고, 몇 가지 이벤트는 배달상태를 변경시킵니다. 배달상태는 순서가 있기 때문에 순서대로 진행되며, 특정 이벤트들은 거의 동시에 발생하기도 하고, 배달상태를 변경시기키도 합니다. 혼란스럽지 않은 배달프로세스를 관리하기 위해서는 이벤트 발행과 관련하여 순서를 보장하는 것이 중요합니다.

delivery process

예를 들어, 배차완료와 거의 동시에 픽업준비요청이 발생할 수 있습니다. 프로듀서는 배차완료 이후 픽업준비요청을 발행하였으나 네트워크 등의 이슈로 컨슈머는 픽업준비요청 이후, 배차완료를 수신할 수도 있습니다. 이런 경우, 순서가 보장되지 않는다면 컨슈머 측에서는 거의 동시에 발생한 이벤트에 대해서 어떤 이벤트가 먼저 발생한 것인지 혼란스러워 비즈니스 로직 처리에 문제가 발생할 수 있습니다.

카프카는 메시지 발행 순서에 따라 소비할 수 있도록 순서를 보장합니다. 같은 카프카 클러스터에서 주문, 배달, 분석 토픽 등 목적에 따라 토픽을 구성할 수 있으며, 하나의 토픽은 병렬처리로 처리량을 높이기 위해 여러 개의 파티션으로 구성됩니다. 카프카에서는 같은 파티션에 대해서 프로듀서가 보낸 데이터의 순서를 보장합니다. 같은 키를 가진다면 같은 파티션으로 할당되고, 하나의 파티션에 하나의 컨슈머가 할당됩니다. 따라서 같은 키에 대해서는 분산시스템에서도 같은 서버가 소비하게 되어 이벤트 순서가 보장될 수 있습니다. 주문식별자, 배달식별자 등과 같이 순서관리가 필요한 식별자를 키로 관리하여 순서를 보장합니다. 메시지 공급자가 발행 순서를 보장하기에 거의 비슷한 시점에 발행되는 메시지 동시성 이슈 발생 상황을 줄일 수 있습니다.

데이터 정합성

비즈니스 로직을 처리하기 위한 데이터를 MySQL 데이터베이스에 저장하고, 카프카로 이벤트를 발행하는 방식으로 데이터와 이벤트를 관리하고 있습니다. 카프카에 문제가 발생할 경우, 데이터베이스에는 변경된 배달상태가 저장되었으나 이벤트는 발행되지 않을 수도 있습니다. 예를 들어 주문취소가 발생한 경우를 생각해 봅시다. 주문취소로 배달취소가 발생하게 되면 데이터베이스에는 해당 배달은 취소된 상태로 저장될 것입니다. 하지만 이벤트 발행에 실패하게 된다면 컨슈머는 메시지를 수신하지 못해 여전히 배달을 진행할 수 있습니다. 취소된 배달이 진행되는 문제가 발생할 수 있습니다. 데이터와 메시지 발행의 트랜잭션을 하나로 관리하여 데이터 정합성을 확보할 필요가 있었습니다.

인프라와 커넥션 이슈, 타임아웃 등의 문제로 토픽에 메시지를 넣는 과정에서 실패할 수도 있습니다. 메시지 발행에 실패하는 경우, 메시지가 누락되어 정합성이 보장되지 않기에 누락 방지를 위해서 재시도가 필요했습니다. 재시도 과정에서도 메시지의 순서는 보장되기를 바랐습니다. 하지만, 다른 비즈니스 이벤트 처리에 미치는 영향은 최소화하며 재시도를 하고 싶었습니다. 이벤트 발행에 실패하는 경우, 순서와 영향도를 고려하여 재시도를 시도하는 방법으로 Transactional Outbox Pattern을 이용하였습니다.

Transactional Outbox Pattern은 분산 시스템에서 데이터베이스 트랜잭션과 메시지 큐를 조합하여 데이터 일관성과 메시지 전송의 원자성을 보장하는 패턴입니다. 분산시스템에서 트랜잭션 완료 후, 이벤트를 보내야 하는 경우에 트랜잭션에 실패할 경우 데이터는 롤백되지만, 이벤트는 발송될 수 있고, 메시지 전송 중 문제가 발생하는 경우 메시지 전송 원자성이 보장되지 않을 수 있습니다. 문제를 해결하기 위한 이 패턴의 핵심 아이디어는 다음과 같은 흐름으로 진행됩니다.

  1. 트랜잭션 데이터베이스에 Outbox 테이블을 도입하여, 트랜잭션 완료 시 변경 사항을 기록합니다.
  2. Outbox 테이블에 새로운 레코드가 추가될 때마다 변경 사항을 메시지로 전송합니다.

log-tailing

설명한 패턴을 구현하기 위해 Debezium이라는 라이브러리에서 지원하는 MySQL 카프카 커넥터를 이용하고 있습니다. Debezium은 데이터베이스의 변경 사항을 감지하고 이벤트 스트림으로 변환하는 오픈 소스 라이브러리입니다. 데이터베이스의 기록인 binlog의 변경 사항을 감지(Change Data Capture)하여 읽는 로그 테일링 기법을 사용되어 있습니다. 변경사항을 읽어 설정한 토픽으로 보내주는 방식으로 동작합니다. 트랜잭션의 성공 내역을 binlog 기록하고, 기록을 순서대로 읽어가도록 동작합니다. 메시지 발행에 실패하면 아웃박스테이블의 데이터도 롤백되기 때문에 하나의 트랜잭션으로 데이터 정합성을 관리하고 있습니다. Debezium에서 메시지 발행에 사용되는 MySQL source connector는 태스크를 하나만 사용하도록 강제하기 때문에, 단일 커넥터에서 메시지 전송 순서를 보장할 수 있습니다.

하나의 태스크로 동작하면 테이블에 데이터가 쌓이는 속도보다 커넥터가 처리하는 속도가 느릴 경우 메시지 지연이 발생할 수 있습니다. 처리량을 높이기 위해 토픽별로 outbox 테이블을 분리하여 만들고, 각 outbox 테이블은 식별자 기반으로 N개의 테이블로 구성하였습니다. delivery-outbox1, delivery-outbox2, delivery-outbox3과 같이 여러 개의 outbox 테이블을 구성하고, 각 테이블에 커넥터를 연결하여 한 커넥터가 처리하는 양을 분산하여 처리량을 확보하였습니다. outbox 테이블은 쓰기(insert)만 동작하는 테이블로 저장된 순서대로 이벤트 메시지 발행을 보장하도록 설정되어 있습니다. 같은 키는 같은 테이블에 저장되며, 한 테이블에서는 하나의 커넥터를 사용하기 때문에 같은 키에 대해서는 순서를 보장됩니다.

transactional outbox pattern

[2] 카프카를 이벤트 버스로도 활용해보자

미리보기

– 카프카를 이벤트 버스로 활용하여 분산시스템에 알린다.

분산 시스템에서는 서버 여러 대로 서버군을 이룹니다. 한 서버에서 값을 변경하면 서버군에 속한 모든 서버의 변경된 값을 관리해야 할 때가 있습니다. 배달서버에서 어떤 배달서비스로 분배할지 결정하며, 분배 규칙은 인메모리로 관리합니다. 이 경우, 분배 규칙 이벤트를 소비한 배달서버만 분배규칙이 변경되고 다른 배달서버들은 기존 분배 규칙을 유지할 수 있습니다. 운영자가 필요에 의해 분배 규칙을 변경하면, 모든 배달서버는 해당 변경 값을 알아야 합니다. 카프카를 이벤트버스로 활용하여 값 관리가 필요한 서버군에 변경된 값을 알리고, 변경된 내용을 반영하도록 관리하고 있습니다.

스프링 클라우드에서 제공하는 RemoteApplicationEvent를 사용하여 이벤트 버스로 카프카를 사용하고 있습니다. 이벤트 버스 토픽(예: event-bus)을 설정하고, id는 고유해야 하기에 ${서버명}:${식별자} 형식으로 설정합니다. RemoteApplicationEvent를 상속한 이벤트를 정의하고, 원하는 목적지(서버군)를 명시하여 발행하면 이벤트 버스는 목적 서버군에 이벤트를 전달합니다. 스프링 클라우드에서 id 서버명의 인스턴스에 애플리케이션 이벤트를 발행하기 때문에, 목적 서버에서 발행한 팀에서 정의한 이벤트를 구독하여 처리한다면, 정의한 이벤트를 수신하여 변경된 값을 반영할 수 있게 됩니다. 이렇게 되면 분산시스템에서 인메모리로 관리되는 값도 변경되어 같은 기준으로 비즈니스 로직을 처리할 수 있습니다.

kafka event bus

RemoteApplicationEvent를 상속한 DeliveryServiceRemoteApplicationEvent를 추상클래스로 설정하고, 각 특성에 맞게 구현체를 구성하여 이벤트를 발행하여 필요한 곳에서 활용하고 있습니다. 서버군에 속한 서버들이 각자 인메모리로 저장하고 있는 값을 모두 초기화나 변경이 필요한 경우에 사용됩니다. 아래는 분배규칙 변경에 대해 RemoteApplicationEvent를 정의한 예시 코드입니다.

public abstract class DeliveryServiceRemoteApplicationEvent extends RemoteApplicationEvent {
    protected DeliveryServiceRemoteApplicationEvent(String destination) {
        super(SOURCE, ORIGIN, DESTINATION_FACTORY.getDestination(destination));
    }
}
// 분배규칙 CustomRemoteEvent
public class RouteRuleRemoteEvent extends DeliveryServiceRemoteApplicationEvent {
    public RouteRuleRemoteEvent() {
        super("delivery"); // destination: 배달서버
    }
}

아래는 분배규칙이 변경되어 새롭게 내려받아야 하는 경우, 서버에서 메서드를 수행하고 배달서버군 전체에도 변경된 규칙이 반영될 수 있도록 RemoteApplicationEvent를 발행하고, 소비하는 예시 코드입니다.

public void load() {
    routeRuleSetStore.load();
    remoteApplicationEventPublisher.publishEvent(new RouteRuleRemoteEvent());
}

@EventListener
public void handle(RouteRuleRemoteEvent event) {
    routeRuleSetStore.load();
}

딜리버리서비스팀에서 이벤트 버스 토픽은 하나의 파티션으로 관리하고 있습니다. 설정값을 변경하는 데 높은 처리량이 필요하지 않고, 같은 서버군은 같은 변경사항을 수신해야 하기 때문입니다. 파티션에서 같은 컨슈머 그룹은 오프셋을 공유하므로 모든 서버는 다른 컨슈머 그룹 아이디(consumer group id)를 가져야 합니다. 여러 컨슈머에게 개별적으로 소비될 수 있기 때문에 각 서버가 다른 컨슈머 그룹 아이디를 사용한다면 한 번의 이벤트 발행으로도 여러 서버군의 설정을 바꾸는 것이 가능합니다. 특수하게 컨슈머의 이름을 정하지 않으면, 스프링 클라우드에서는 anomymous라는 프리픽스를 붙여 랜덤하게 컨슈머 그룹 아이디를 설정합니다. 즉, 연결된 서버만큼 anonymous.{식별자} 형식의 컨슈머 그룹 아이디가 생성되고 있고, 시스템 모니터링 시에는 anomymous 컨슈머는 필터링하고 있습니다.

[3] 더 나은 배달을 위해 분석하자

미리보기

– 분석에 적합하게 가공된 형태로 데이터를 제공한다.
– 카프카 스트림즈를 활용하여 실시간 배달 정보를 집계하여 배달 상황을 파악할 수 있도록 한다.

배치 등을 사용하여 분석을 위한 데이터를 제공할 수도 있지만, 일정 주기로 배치를 수행하기 때문에 실시간 데이터를 반영하기 어려운 문제가 있습니다. 우리 팀에서는 실시간 혹은 준실시간에 해당하는 데이터를 조회하여 배달현황을 파악하고 서비스에 반영하기를 원했습니다. 요구사항을 만족시킬 기술로 카프카 스트림즈를 활용하고 있습니다.

카프카 스트림즈는 카프카에서 실행하는 이벤트별 데이터(레코드) 처리를 수행할 수 있게 하는 라이브러리입니다. 간단히 말하자면, 카프카 스트림즈는 메시지를 활용한 실시간 집계, 분석 시스템으로 실시간 데이터 스트리밍 및 분석 시스템에 적합한 플랫폼으로 폭넓게 활용되는 도구입니다. 카프카 스트림즈 애플리케이션이 처리하는 것은 데이터의 흐름입니다. 전처리 단계와 스트림 연결로 데이터 스트림을 입력받아 필요한 처리를 수행 후, 새로운 스트림을 생성하여 데이터를 처리하고 결과를 산출하는 방식으로 동작합니다.

분석용으로 가공한 데이터 제공

분석 서버에서는 배달 이벤트를 수신한 후 전처리 과정을 거쳐, 조회하기 편한 형태로 가공하여 분석 토픽으로 이벤트를 재발행합니다. 원본 이벤트를 가공하여 분석할 수 있도록 또 다른 토픽과 스트림으로 생성합니다. 목적이 다르기에 원본 토픽과 분석용 토픽을 분리하여 사용합니다. 서비스 토픽과 분석용 토픽은 서로 다른 데이터 처리량과 리소스가 필요하기에 토픽과 서버를 분리하여 특성에 맞는 리소스를 사용하고 조정할 수 있도록 구성하였습니다. 주요한 서비스 로직에 사용되는 토픽과 분석에 사용되는 토픽은 문제가 발행하더라도 영향범위를 분리하여 관리할 수 있습니다.

배달은 생성, 배차, 픽업, 완료 등 순서를 가지고 진행되며, 특정 행위마다 배달이벤트를 발행합니다. 분석이 필요한 경우, 배달의 이벤트를 하나하나 보는 것이 아닌 배달 건별로 정리된 정보를 확인하고 싶은 경우가 많습니다. 주요 정보는 어떻게 되는지, 언제 생성되어 배차, 완료가 되었는지 등 배달 한 건에 주요 정보를 집계해 확인하고자 하는 수요가 있었습니다. 분석하기 편하도록 전처리 과정을 거쳐 한 배달건에 대해 발생한 여러 이벤트를 하나로 모아 완료된 배달 건의 요약된 종합 정보를 제공하고 있습니다. 이때 Redis를 임시저장소로 활용하여 종합데이터를 관리합니다. 원본 배달 토픽에서 배달생성 이벤트를 수신하면 Redis에 주요한 주문과 배달 정보를 저장합니다. 이후, 배달 진행에 따라 발행된 이벤트를 수신하면 각 배달이벤트 시점 등 주요한 정보를 업데이트합니다. 완료된 배달은 Redis에서 삭제하고, 의미 있는 정보로 구성한 새로운 배달통합이벤트를 분석 토픽에 발행하여 배달 건별 종합데이터를 제공합니다.

S3 싱크 커넥터를 사용하여 분석토픽에 들어간 이벤트는 AWS S3 객체저장소에 보내 영구 저장하고 있습니다. 이벤트 영구 저장소와 비즈니스 로직을 처리하기 위한 저장소를 분리하여, 분석용 서비스와 비즈니스 서비스의 상호 영향을 최소화합니다. S3 객체저장소에 저장된 데이터는 AWS Athena를 사용해 비즈니스 서비스 저장소에 부하를 주지 않고 오래된 기록까지 조회할 수 있습니다. 데이터를 분석할 수 있는 도구를 연동하여 사업이나 운영 부서에서 지난 배달 건을 월단위로 분석하기도 하고, 정산에 활용하기도 합니다.

아래 그림은 통합배달이벤트 흐름과 이후 실시간 데이터 제공과 관련된 다이어그램입니다.
integrated delivery event and streams

실시간 데이터 제공

배차 대기로 남아있는 배달 건이 얼마나 되는지, 현재 배차에 시간이 얼마나 걸리는지, 주문서비스별 유입량은 어떻게 되는지 등 실시간 배달 데이터를 알고 싶었기에 스트림즈 애플리케이션을 활용하여 실시간 배달데이터를 집계하고 있습니다. 실시간 집계된 내용은 그라파나 대시보드로 시각화하여 운영 상황에 대응할 수 있도록 제공하고 있고, 배달인프라 상황을 파악하여 분석하는 데도 사용됩니다.

각 배달상태에 따른 배달 건수가 얼마나 되는지 실시간 집계하는 한 가지 예시를 들어보겠습니다. 분석용 배달토픽에 들어온 레코드 흐름(Stream)을 기반으로 최신 배달 상태저장소(latest-delivery)를 구축합니다. 상태저장소(statestore)는 키-값 임시저장소입니다. 최신 배달 상태저장소에는 레코드의 시간을 기준값으로 최신 배달을 판단하며, 키를 배달식별자로 하고 값을 배달데이터로 합니다. 최신 배달을 기준으로 배달 상태별 개수를 집계할 수 있습니다. 키는 배달상태, 값은 집계된 배달 상태별 개수로 배달상태별 상태저장소(count-per-status)를 구성합니다. 그 결과로 배달상태별 상태저장소에서 실시간으로 배달상태별로 집계된 결과를 빠르게 조회할 수 있습니다. 배달 상태별 개수를 조회하는 그라파나 게이지를 등록하여 조회한 결과를 대시보드로 시각화하여 나타내고 있습니다. 대시보드를 통해 하나의 배달 상태에 몰려있진 않은 지, 배달진행에 문제가 있는 건 아닐지 대시보드를 보며 추이를 실시간으로 파악할 수 있습니다. 아래는 베타 환경에서 구성한 대시보드 예시입니다.

beta grafana dashboard

이외에도 다양하게 집계되는 실시간 현황은 현재 배달상황을 파악하고 대응하는 데 도움이 됩니다. 다양하게 집계되는 데이터를 활용하여 다른 유용한 기능을 제공할 수도 있습니다. 실시간으로 이상 상황으로 감지되는 판단을 자동화하여 알람으로 빠르게 장애인지를 할 수도 있고, 큰 장애로 번지기 전에 주문유입을 최소화하여 장애 범위를 최소화하는 데 활용될 수도 있습니다.

끗!

지금까지 카프카의 개념과 특성을 간략하게 설명하고, 팀에서 카프카를 어떻게 활용하고 있는지 소개했습니다. 저는 개발자로 일한 지 갓 2년이 넘었고, 팀에서 사용하는 시스템 설계나 구현을 주도해본 경험은 아직 없습니다. 그래서 각 기술의 자세한 설명은 더 전문가들이 작성한 자료나 공식 문서를 참고하실 수 있게 마지막에 정리해 두었습니다.

이 글에서는 카프카와 관련된 기술을 상세히 다루기보다는 우리팀에서 카프카를 어떻게 사용하는지 전반적으로 소개하는 데 중점을 두었습니다. 스스로도 더 잘 이해하고 기술을 사용하고 싶었고, 사례를 공유하며 함께 더 알아가고 싶은 마음이었습니다. 이 글의 내용과 연관된 분들이 발표한 우아콘 영상이 있어 마지막 참고 자료 부분에 링크를 넣어두었으니 더 자세한 내용이 궁금하신 분들은 영상도 참고해 주시면 좋겠습니다.


참고 자료

링크

WOOWACON 2023 영상