GS리테일 DX 블로그

Digital Transformation으로 고객 생활 가치의 이노베이션을 꿈꾸는 IT 사람들의 이야기

Cloud&Security

Kafka 도입 스토리 - 홈쇼핑 방송영역 활용 사례

joel Lee 2023. 2. 20. 10:47

들어가며...

  개발자 온라인 커뮤니티 중 하나인 DZone의 2022년 리서치에 의하면 개발자의 마이크로서비스를 운영하는 비율이 93%라고 합니다. 마이크로 서비스에 대한 부정적 의견들도 나오고 있지만 2021년 74%에 비하면 계속적으로 증가하는 추세입니다.

  마이크로서비스를 설계한다는 것은 통합환경에서 분산환경으로의 전환을 의미합니다. 이는 어플리케이션간의 상호 의존성(결합도)을 적절하게 관리하는것이 중요합니다.  샘뉴먼의 "마이크로서비스 도입, 이렇게 한다" 는 책에서는 분산환경하에서 중요한 coupling의 종류를 4가지로 들고있습니다. Implementation Coupling, Temporal Coupling, Deployment Coupling, Domain Coupling 입니다. 자세한 설명은 해당 도서를 참조 바랍니다.

  분산환경에서의 시스템간 상호작용하는 방법으로는 Query, Command, Event가 있습니다. Query 나 Command는 목적지를 갖고 동기식으로 통신하는 것을 의미하는데 반해, 이벤트 방식은 특정 목적지 없이 비동기식으로 통신하는 구조입니다. 통합구조의 어플리케이션을 업무도메인으로 분할하여 API를 통해 Query&Command식 통신으로 구현했다면 Implementaion coupling은 최소화 했지만 Temporal Coupling은 해결하지 못한 것입니다. 이에 반해 Event방식은 Temporal Coupling까지 최소화할 수 있습니다. 그렇다고 무조건 Event 방식이 최선은 아니며, 상황에 맞게 Query, Command, Event를 적절히 활용해야 합니다. 

 아무튼 마이크로서비스로 전환하는 작업을 하면서 Coupling을 최소화 하는 방안으로 이벤트구조는 필수적이며, 이벤트 구조를 적절히 구현해 줄 솔루션이 필요합니다. 이를 위해  Apach Kafka를 선택하여 적용하게 되었습니다. Kafka에 대한 간단한 설명 후, 당사 적용 케이스에 대해 소개하고자 합니다.


Kafka 개요

<그림1>에서 보는 바와 같이 카프카는 메시지를 저장하는 브로커, 브로커에 메시지를 발행하는 Producer, 그리고 브로커로부터 메시지를 구독하여 업무적으로 처리하는 Consumer로 구성됩니다.

1대 이상의 브로커로 클러스터를 구성하고, 주키퍼에 의해 상태가 관리됩니다.  여러 대의 브로커로 클러스터를 구성하여 부하를 분산하는 효과와 데이터를 복제하여 장애에 대비하는 효과를 볼 수 있습니다. 

브로커를 구성하는 방법은 OS가 설치된 서버 인스턴스를 준비한 후 Apache Kafka S/W를 다운받아 설치하거나, 카프카 클러스터 전문 관리 업체의 솔루션을 도입할 수도 있습니다. 대표적인 업체로는 카프카 개발자들이 설립한 Confluent사나, managed카프카 서비스를 제공하는 클라우드 공급사들이 있습니다.

 

<그림1> Kafka 기본 구조

<그림2>에서와 같이 브로커에 메시지를 전달하는 방법은 Kafka Producer Client를 활용하거나 Kafka Connect(Source커넥트)를 활용하는 방법이 있습니다. Producer Client를 활용하는 경우, 개발자가 소스 코드상에서 비즈니스 로직을 처리한 후, 카프카 브로커로 메시지를 전송하는 소스코드 프로그래밍을 해야합니다. 반면에 Kafka Connect를 활용하는 경우, 소스코드 프로그래밍 없이 parameter 설정만으로 메시지를 브로커로 전달할 수 있습니다. 

 브로커에서 메시지를 구독하여 처리하는 방법은 Kafka Consumer Client를 활용하는 방법, 메시지를 연속되는 스트림으로 읽여들여 처리하는 Kafka Streams, 그리고 Kafka Connect(Sink커넥트)를 활용하는 방법이 있습니다. Consumer Client를 이용하여 브로커에서 메시지를 읽어와 이벤트 목적에 맞게 로직 처리를 위해 소스코드 프로그래밍을 해야합니다. Kafka Streams를 이용하는 경우에도 로직처리를 위해 프로그래밍이 필요합니다. 이들과는 다르게, Sink커넥터를 활용하면 Source커넥트와 유사하게 프로그래밍 없이 parameter설정만으로 처리가능합니다. 로그 데이터 처리나 CDC(Change Data Capture) 형식의 데이터 동기화 구현시 Kafka Connect를 많이 활용합니다.

<그림2> Kafka 제품군(Kafka API)

1) Broker 및 Topic

브로커에 메시지를 저장하기 위해서는 RDBMS의 테이블과 유사한 개념의 Topic을 생성합니다. 토픽을 생성하는 방법은 CLI환경에서 명령어를 수행하거나, Kafka Admin Tool을 통해 GUI환경에서 생성할 수 있습니다. 이때 적절한 Parameter값을 설정할 수 있고,  카프카는 특정 브로커를 할당하여 토픽을 저장합니다. 토픽은 부하분산 및 병행처리를 위해 Partition으로 분할하여 저장할 수 있고, 정확히는 이 파티션별로 브로커를 할당받아 저장합니다. <그림3>은 3개의 브로커로 구성된 클러스터에 "주문" 토픽을 4개의 파티션으로 생성했을 경우 저장되는 예시입니다.

<그림3> Broker별 Partition 할당

브로커를 할당받아 저장된 파티션은 장애시 대응을 위해 Replication Factor를 설정하여 파티션을 복제해 둘 수 있습니다. 이는 기존 파티션과는 별도의 브로커에 저장함으로써 한 브로커가 장애 발생시 복제된 데이터로 서비스를 계속할 수 있도록 지원합니다.<그림4>는 <그림3>에서 생성된 파티션을 Replication Fator를 2로 설정하였을 경우 저장되는 예시입니다. 만약 여기서 브로커0 이 다운되어 서비스 불가능한 경우, 파티션 중 Leader인 주문P0은 서비스 불가하므로  브로커1의 주문P0 복제본이 Leader가 되어 브로커1, 브로커2 만으로 정상적으로 서비스 가능합니다.

<그림4> Replication Factor의 설정

2) Producer Client

Kafka Producer Client를 다운받아 이벤트를 발행할 때 내부적으로는 <그림5>와 같은 절차로 이루어집니다. 비지니스 로직 처리 후 토픽명, Partition Key, 메시지를 parameter로 설정하여 Send Mehtod를 호출합니다. 이후 Serializer는 Object를 네트워크 전송을 위해 직렬화하고, 파라미터로 전달받은 Partition Key를 이용하여 저장될 토픽의 파티션을 선정합니다. 선정된 파티션별로 메시지는 버퍼에 저장되고 Sender는 버퍼에 쌓인 메시지를 브로커로 전달을 합니다. 이때 Serializer 와 Partitioner는 필요시 직접 개발하여 추가할 수 있습니다.   

<그림5> Kafka Producer Client

  Producer는 토픽에 메시지를 전달하고 Offset 값을 증가시킵니다. 좀더 상세히 말하면 토픽의 파티션에 메시지를 저장하고, 파티션별로 Offset 값을 관리합니다. 이 Offset값은 컨슈머에 의해 순차적으로 읽어들여 처리되도록 활용됩니다. 즉 한 파티션내의 메시지들은 발생순서에 의해 처리될 수 있습니다.

  파티션키 값이 명시 되지 않은 경우, 파티션의 할당은 Round-robin 방식으로 이루어집니다. 이는 특정 메시지의 순차적 처리를 보장할 수 없습니다. 하지만 파티션키를 명시한 경우에는, 해당 키의  Hash값으로 파티션을 할당합니다. 즉 여러번 발생한 메시지더라도, 파티션키를 동일한 키를 사용하는 경우에는 동일한 파티션에 할당되어 이벤트 발생 시간 순으로 처리가능합니다. 예를 들어 주문번호 A가 생성 -> 수정 -> 취소 순으로 이벤트가 발생했다고 가정한다면, 파티션키를 명시하지 않은 경우의 주문 메시지는 서로 다른 파티션에 할당되고, 이는 이벤트 발생 시간 순으로 처리 되지 않고 수정 -> 취소 -> 생성 순으로 처리될 수 있습니다. 이로인해 해당 주문의 최종상태가 원주문의 상태와 동일함을 보장할 수 없습니다. 

<그림6>파티션키 유무에의한 파티션 할당

 Producer는 acks 설정을 통해 메시지 전송의 전송보장 수준을 지정할 수 있습니다. "all" 로 설정하여 leader파티션 뿐만아니라 복제된 모든 팔로우 파티션에도 저장 성공시에 전송 성공이라고 체크하여 전송보장의 수준을 높일수도 있고, "1" 로 설정하여 leader파티션에만 저장되어도 전송 성공이라고 판단할 수 있습니다. "0" 으로 설정하여 아무런 체크없이 전송시도만으로 전송 성공으로 판단할 수 있습니다. 이 설정값은 데이터의 중요도에 따라 유사시 데이터의 유실 가능성으로 판단하여 설정합니다. 

3) Consumer Client

  Consumer Client는 지정된 토픽의 파티션으로 부터 메시지를 읽어 오고 Offset값을 관리합니다.  Producer가 증가시킨 오프셋 값과 Consumer가 읽어들인 오프셋 값의 차를 LAG 으로 관리하여 모니터링 합니다. LAG 이 증가한다는 것은 해당 토픽의 컨슈머가 느리거나 다운되었을 가능성을 내포합니다. 그러므로 LAG은 주요 모니터링 지표중의 하나입니다.

<그림7> Offset 과 LAG 개념

  여러 파티션으로 구성된 토픽을 구독하기 위해서는 컨슈머도 여러 대가 필요합니다. 물론 하나의 컨슈머로 여러 파티션을 구독할 수 있지만 성능면에서 불리합니다. 한 토픽을 구독하는데 여러 대의 컨슈머로 구성하고, 이를 그룹으로 묶어 Consumer Group 으로 관리합니다. 즉 하나의 토픽을 구독하는것은 컨슈머그룹이고, 컨슈머 그룹은 여러대의 컨슈머로 구성할 수 있습니다. 파티션 갯수에 따라 컨슈머 갯수를 어떻게 구성하냐에 따라 성능면에서 차이가 날 수 있습니다.  컨슈머의 부하가 작은 작업으로 이루어진 경우 한 컨슈머로 여러 파티션을 구독할 수 있고, 그렇지 않은 경우에는 1:1로 구성하는게 유리합니다. 컨슈머의 갯수를 더 많이 구성할 수 있지만 이는 성능에는 영향을 미치지는 못합니다. 다만, 운영중인 컨슈머 하나에 장애 발생시에는 rebalancing 에 의해 곧바로 컨슈머로 참여할 수 있어 장애 복구 시간을 감소시킬 수 있습니다.

<그림8> 파티션과 컨슈머의 구성

4) Kafka Streams

특정 토픽으로부터 메시지를 읽어와 비즈니스 로직 처리 후 다시 토픽으로 메시지를 보내야 하는 Data Pipe-Line을 구성하는 경우에는, 컨슈머와 프로듀서를 적절히 사용하여 프로그래밍 가능합니다. 하지만 Streams를 사용 시에는 프로그래밍 하는 코딩 작업을 줄일 수 있습니다. Source토픽으로 부터 메시지를 읽어와 Sink토픽으로 메시지를  전달하는 방식으로 프로그램 코딩을 최소화하여 개발할 수 있습니다. 토픽간의 Join 이나 Aggregation, 스케줄링 기능 및 상태 기반 처리 기능 등을 활용한 프로그래밍도 가능합니다.

<그림9> Kafka Streams

5) Kafka Connect

  Kafka Connect는 소스코드 작성 없이 카프카에 메시지를 전송하거나 수신하여 처리가능하도록 합니다. 브로커에 메시지를 전달하는 소스커넥트와 브로커로부터 메시지를 읽어들여 처리하는 싱크커넥트로 구분할 수 있습니다. DB나 파일등의 데이터의 소스에 접근할 수 있게 해주는 Connector를 설치하여 소스코드 없이 브로커로 메시지를 전달하거나 수신할 수 있도록 합니다. 다만, 커넥터가 존재하지 않은 경우에는 직접 커넥터를 개발해야하는 수고가 있습니다. 

<그림10> Kafka Connect

지금까지 카프카의 기본개념들에 대해 알아봤습니다. 위에 설명한 producer, consumer, streams, connect API 외에,  Mirror Maker, KSQL 등 다양한 기능과 API들이 생겨나고 있습니다. 타 솔루션들과 마찬가지로, 무조건적으로 솔루션을 적용하는것 보다는 기본 개념을 익히고 적절한 비즈니스 케이스를 찾아 적용하는 것이 성공의 키입니다.

  현재 포춘 선정 100대 기업 80%가 카프카를 사용중에 있다고합니다. 제조, 금융, 보험, 통신등의 다양한 산업분야에서 자사에 맞는 카프카API 를 적용하고 있습니다.  메시지 처리를 위해 사용하거나, 웹사이트 Activity Tracking,  Event Sourcing 및 로그수집 으로 활용하고 있습니다. 당사에서도 여러 분야에서 사용하기위해 준비중이며 처음으로 도입한 사례에 대해 소개할까 합니다.


당사 활용 사례

홈쇼핑 비즈니스는 일반 커머스에 방송 등의 특정 비즈니스가 추가된 범위를 갖습니다. 현재 홈쇼핑의 Back Office 시스템의 일부분인 방송영역에 대해 Application Mordernization 작업을 진행중입니다. 인프라환경, 시스템의 구조, 개발 방식 및 개발 툴등 어플리케이션 개발과 관련된 전체적인 부분에서 현대화를 진행하고 있습니다. 그중에서 기존 Monolithic 구조의 어플리케이션을 여러 업무 도메인으로 분할하여 마이크로서비스로 전환하는 업무를 하고 있습니다. 커다란 하나의 어플리케이션을 작은 마이크로서비스로 분할하여 분산환경을 만드는 작업이므로 상호 서비스간의 결합도를 낮추는 작업이 중요합니다. 기존 시스템은 데이터의 원천은 그대로 두고 타 시스템에 의존성을 갖고 개발하거나 대부분 Join SQL을 통해 개발된 상태입니다.
 당사의 방송시스템은 별도의 데이터베이스로 구성된 구조이긴 하나 그 자체로도 커다란 모노리스 구조의 어플리케이션입니다. 데이터 의존도 또한 core 데이터베이스에 DB Link를 통해 연결하거나 데이터소스를 통해 직접 연결하여 구현되어 있습니다.

적절한 비즈니스 케이스 선정

 방송시스템을 사용하는 사용자는 방송을 제작하는 직군과 상품 소싱을 담당하는 MD 직군이 주를 이룹니다. 방송 직군 중 PD는 방송 영상을 제작하는 주요 사용자 직군 중의 하나입니다. 하나의 방송 진행을 위해 상품공급업체, 쇼핑호스트 , 방송스탭 등이 모여 상품에 대한 정확한 이해와 방송진행 준비를 합니다. 방송 시작과 함께 PD는 준비된 상품을 노출하여 고객들의 콜 및 인입주문을 모니터링합니다. 이때 시스템적으로는 core데이터베이스의 주문을 계속적으로 읽고 있어 부하를 줍니다. 주문이 많은 상품인 경우에는 조회되는 주문건수도 많아 적잖은 부하를 주게됩니다. 집계주기를 좀더 리얼타임에 가깝게 줄이고자 해도 부하로 인해 한계가 있습니다. 또한 실적집계하는 프로그램도 DB에 의존적인 프로시져로 되어있어 주문 테이블이 변경되는 경우, 실적집계 시스템에도 영향을 주게되어 항상 해당 프로그램의 active 여부를 관리해야 합니다.

<그림11> 기존 방송실적 집계 구조

이러한 문제점을 해결하기위해 주문데이터를 복제해서 독립된 데이터베이스에서 집계하기로 결정하였습니다. 주문 데이터를 데이터의 원천으로 사용하는 다양한 프로그램도 있기에 주문 생성을 이벤트 방식으로 처리하는 방법이 최적이라 판단했습니다. 방송실적 집계를 위해서는 생성되는 모든 주문 중에 방송에 해당하는 주문만 걸러내고, 주문 수량, 매출, 이익 등의 추가적인 실적 집계도 필요합니다. 데이터 복제를 위해 주문발생 시(생성,수정,취소,반품,교환 등) 이벤트 기반으로 메시지를 전송하여 처리 가능한 카프카를 적용하기로 결정하였습니다. 카프카를 적용하는 절차는 크게 아래의 4단계를 거쳐 수행하였습니다.

 

<그림12>방송실적집계 Data Flow

1 ) 카프카 클러스터의 구성

앞서 설명했듯이 카프카의 클러스터(브로커)를 구성하는 방법은 오픈소스를 활용하여 직접 구축하거나, 전문관리업체의 솔루션을 활용하는 방법이 있습니다. 사내에 처음 도입하는 기술이므로 어느 정도의 지식과 경험이 쌓기 전까지는 전문업체의 솔루션을 활용하는 방법이 유리하다고 판단했습니다. 그래서 전문업체 솔루션 중의 하나인 AWS의 MSK를 도입하기로 결정했습니다. 전문업체의 솔루션을 선택했을 경우에도 기본적인 개념 이해를 바탕으로 설정 작업을 진행해야합니다. 브로커는 몇개로 구성할지, AZ은 어떻게 배치할지, 메시지 보관 기간을 얼마로 할지, 디스크는 얼마나 할당할지 등 수많은 설정값들이 존재합니다. 대부분 Default 설정값을 제공해주지만, 주요한 설정값들은 반드시 정확히 이해하고 직접 설정을 해주어야 합니다. 

  브로커가 준비되면 이벤트가 저장되는 단위인 토픽을 생성해야 합니다. 토픽 생성 시 토픽명, 파티션의 갯수, Replication Factor 갯수, ISR 등 여러 설정값이 존재합니다. 엔터프라이즈 환경에서 토픽은 조직간에 메시지를 주고 받는 저장소 역할을 하게 되므로, 명확한 관리 거버넌스가 필요합니다. 토픽을 만들고 이벤트를 발행하는 조직에서 오너십을 갖는게 적절하다고 판단했습니다. 이 오너십을 갖고 있는 조직에서 토픽의 설정값 및 스키마를 관리해야 합니다. 이를 위해서 토픽명만으로 관리조직이나 이벤트의 특성을 유추할 수 있도록 명명하는게 좋습니다. 당사에서는 "이벤트발행서비스명" + "." + "이벤트명" 형식으로 토픽 명명 규칙을 선정하였습니다.  

2 ) 이벤트 발행

브로커와 토픽이 준비되면 이제 브로커에 이벤트를 발행해 줄 프로듀서를 준비해야 합니다.  Producer Client 라이브러리를 다운로드하여 비즈니스 로직 프로그램 내에 카프카로 메시지를 전송해 주는 방법과, 소스코드 프로그래밍 없이 저장된 데이터를 읽어들여 브로커로 메시지를 전송해주는 커넥트를 이용하는 방법이 있습니다.  초기 개발시에는 가장 일반적인 형태인 Kafka Producer Client 라이브러리를 이용하여 주문이 생성되는 시점에 브로커로 이벤트를 발행하도록 개발 하였습니다. 이 방식은 시험운행 초기에는 잘 작동하였스나, 갑자기 브로커로의 호출이 완료되지 않고, 주문 생성 서버에 누적되는 현상이 발생하였습니다. 결국은 주문생성 서버가  Hang 상태로 전환되어 정상 서비스를 할 수 없는 상태가 되었습니다. producer client의 연결 오류시 재 시도 횟수를 설정하는 값을 설정 하였음에도 발생한 상황이었습니다. 설정값중 Acts = 0 으로 설정하면 회피할 수 있는 상항이었으나, 실적 집계라는 데이터의 특성상 데이터 손실이나 전송 속도면에서 중간 수준에 해당하는 "1" 로 설정하였습니다. 브로커의 구축을 전문관리업체의 솔루션을 활용한 것도 문제를 해결하는데는 크게 도움이 되지 않았습니다.  브로커 로그상으로는 "정상" 이라는 결과만을 보고할 뿐이었습니다. 뚜렷한 원인을 찾지 못한 상태에서 이러한 경우를 아울러서 회피할 수 있는 방안을 팀원이 제안해왔습니다.  주문발생 시 곧바로 브로커로 이벤트를 발행하지 않고, 해당 페이로드를 로그파일에 적재후 주문생성 트랜잭션은 종료하고, 별도의 카프카 컨넥터를 활용해 브로커로 이벤트를 발행하는 안이었습니다. Outbox패턴의 일종이었습니다. 제안된 안은 성공적이었습니다. 더이상 이벤트를 발행하는  프로듀서측에서 Hang 걸리는 상황은 발생하지 않았습니다.

3) 방송 주문 필터링

주문은 현재 방송 상품뿐만아니라, 쇼핑몰에서 판매되는 상품 주문과 이전 방송상품에 대한 주문들이 동시에 생성됩니다. 방송중 실적만을 집계하기 위해서는 현재 방송 주문만을 필터링해야 합니다. 이를 위해서는 컨슈머를 활용하여 방송주문필터링 및  주문내역 저장을 한번에수행하거나, 스트림즈를 활용하여 방송주문만을 신속히 필터링후 타 토픽으로 이벤트를 발행하는 방법이 있습니다. 처리 속도 및 필터링 로직상 Kafka Streams 활용이 유리하다고 판단하였습니다. 스트림즈 프로그램에서 필터링과 동시에 실적 대상 방송을 주문내역에 설정하여, 실적집계 작업시 시간을 단축하였습니다.  모든 주문을 저장하는 토픽에 비해 필터링된 방송 주문은 데이터량도 적어서 파티션의 갯수도 원주문의 파티션에 비해 절반으로 구성하였습니다.

4) 방송주문 적재

방송 주문만을 저장한 토픽을 구독하는 컨슈머를 구현하여 주문 내역을 임시 테이블에 적재하였습니다. 방송주문 토픽을 구독하는 컨슈머를 구성하기 위해서는 컨슈머 그룹을 설정합니다. 이는 컨슈머 구동시 그룹명을 명시하는것만으로 가능합니다. 컨슈머 그룹 단위로 토픽에 저장된 메시지들의 offset을 관리합니다. 컨슈머 재구동 시 컨슈머그룹별로 관리하는 offset을 통해 어디부터 메시지를 읽어들일지 결정합니다. 즉 그룹명을 변경하여 컨슈머 재 구동시, 첫 메시지부터 읽어오는 등의 의도하지 않은 결과를 가져올 수 있습니다. 구동시 어디부터 읽어 들일지는 설정값으로 설정 가능합니다. 

  관리 거버넌스 상 토픽 명명 규칙이 중요하듯 컨슈머그룹 명명 규칙도 중요합니다. 브로커 모니터링 중 토픽명이나 컨슈머그룹명을 자주보게 되는데, 이름만으로 토픽 관리 조직과 컨슈머 관리 조직을 유추 할 수 있어야합니다. "이벤트구독서비스명" + "." + "이벤트명" + "id" 로 명명하여 관리하고 있습니다. 

카프카 개발/운영 환경 구성

새로운 기술 도입 시 , 개발자로 하여금 자유롭게 개발해 보고 테스트해 볼 수 있는 환경을 제공하는 것은 중요합니다. 개발자가 로컬 개발환경에서 시험삼아 토픽을 생성하고 이벤트 발행 및 구독을 자유롭게 할 수 있게 제공 해야하고, 타 개발자와 공유하는 환경은 적절한 거버넌스 체계로 운영되어야 합니다. 최소한의 비용으로 개발자에 테스트 배드를 제공하기위해 토픽명을 통해 구분되도록 관리하고있습니다.

  또한 파티션과 컨슈머의 연결 관계 특성으로, 개발자가 개발하고 테스트하는데 많은 방해를 받을 수 있습니다. 예를들어, 특정 서비스를 여러명이 개발 중인 환경에서, A개발자는 1개의 파티션으로 구성된 토픽에 대한 컨슈머 프로그램을 개발하고 테스트하기위해 로컬ide에서 소스코드를 개발하고 build 및 구동을 할것입니다. 그 당시 동료 개발자인 B개발자는 본인의 주어진 기능 개발을 위해 동일한 서비스를 실행중일 수 있습니다. 먼저 실행중인 B개발자의 구동 프로그램이 해당 토픽의 파티션을 구독하고 있는 경우에는 A개발자는 테스트를 할 수 없고, B개발자는 쓸모없는 로그들을 콘솔상에 보게 됩니다. 이를 해결하기위해 컨슈머의 자동 수행 여부를 설정을 통해 제어할 수 있습니다. 비슷한 이유로 이벤트 발행 또한 개발자의 설정으로 제어 가능하도록 설정해 두는게 좋습니다.   

<그림13> 카프카 클러스터 환경

모니터링 및 관리툴 선정

안정적인 카프카의 운영을 위해서는 적절한 모니터링 툴이 필요합니다. 주요 Metric을 설정하고 모니터링 하여 가용성이나 성능상의 이상유무를 신속히 감지할 수 있습니다. 전문업체의 브로커 관리 솔루션을 사용시에는 모니터링 툴도 포함되는 경우도 있으며,  elastic스택등을 이용하여 구성할 수 있습니다. 당사에서는 Grafana를 활용해 유관부서에서 직접 구현하여 모니터링하고 있습니다. 

<그림14> 브로커 모니터링

브로커의 상태 뿐만 아니라 브로커의 설정 내역이나 브로커에 등록된 토픽목록, 토픽의 설정사항, 토픽에 저장된 메시지 내용확인 및 때로는 토픽 생성/삭제 및 메시지 발행을 할 수 있는 툴을 준비해야합니다. 오픈소스도 여러가지가 있으니 검색해서 적절한 툴을 선정해야합니다.

<그림15> 카프카 관리 툴

향후 과제

  카프카를 학습해 가면서 엔터프라즈 시스템에 적용 하기에는 철저한 준비와 용기가 필요합니다. 비교적 단순한 사례로 첫 적용사례를 만들고 점차 확대해나갈 계획으로 시작하였습니다. 마이크로서비스 전환 프로젝트가 본격적으로 진행됨에 따라 Event Driven Architecture를 적극 활용하기위한 카프카 적용 사례를 확대해 나갈 계획입니다. 시스템간의 인터페이스나 어플리케이션 구조를 단순화하거나, 비동기 처리가 요구되는 곳에 적합한 솔루션이 될것입니다.

  또한 비즈니스 트랜잭션과 이벤트 발행 트랜잭션의 무결성 확보를 위한 Outbox 패턴의 구조를 준비중입니다. 누락된 메시지를 추적하거나, 네트워크 다운이나 브로커 다운 등의 비정상 상황에서도 비즈니스 트랜잭션과 비동기로 처리되어 견고한 시스템을 확보할 수 있을것으로 기대됩니다. 

  이벤트 스키마는 송신하는 측과 수신하는 측의 데이터 구조를 약속하는 역할을 합니다. 카프카의 활용 사례가 늘어나면서 토픽의 수도 많아지고 취급하는 데이터의 특성도 다양해질 것입니다.  토픽의 수가 증가함에 따라 이벤트 스키마의 관리도 복잡해질것이기 때문에 보다 효율적 관리 방법을 찾을 예정입니다. 


마치며...

엔터프라이즈 어플리케이션으로 구성된 조직의 서비스에 신규 기술을 도입하기 위해서는 부서간의 긴밀한 협업이 중요시됩니다. 이번 사례에서도 이벤트 발행은 주문을 담당하는 팀에서, 브로커 설치 및 모니터링 툴 설정은 인프라를 담당하는 팀에서 수고해주셨습니다.  이 자리를 빌어 감사의 말씀을 전합니다.

  Kafka라는 용어의 어원에 대해 아시나요? 카프카 개발자이며 Confluent사의 공동 창업자인 Jey Kreps가 답변한 적이 있습니다.( Quora )  "쓰기" 에 최적화된 시스템이기에 작가의 이름을 붙였으면 하던 차, 좋아하던 작가인 "Franz Kafka" 에서 따왔다고 합니다. 하지만 아이러니하게도 "카프카적인" 의미의 "kafkaesque"라는 단어의 다른 뜻은 "부조리하고 절망적인, 악몽같은" 이라고 합니다. 준비없이 kafka를 적용했다가는 악몽같은 상황을 맞을 것이라는 얘기로 받아들여집니다.

  첫 시작이라 카프카의 많은 부분을 다루진 못했지만, 두서없이 써내려간 지극히 카프카적인 첫번째 카프카 활용기였습니다.  

 

이주열 Joel    |    디지털서비스본부 > 홈쇼핑서비스부문 > 방송서비스팀

홈쇼핑 백오피스 Application Mordernization ( MSA 전환 ) 업무를 담당하고 있습니다.

새로운 기술을 습득해 비즈니스에 적용하는 것에 관심이 많습니다.