AWS 기술 블로그

Nexthink가 Amazon Managed Service for Apache Flink를 사용하여 실시간 알림을 구축한 방법

이 게시물은 Nexthink의 Nikos Tragaras와 Raphaël Afanyan이 공동 작성했습니다.  이 글은 AWS Big Data Blog에 게시된  ‘How Nexthink built real-time alerts with Amazon Managed Service for Apache Flink’ 을 한국어 번역 및 편집하였습니다. 

이 게시물에서는 NexthinkAmazon Managed Service for Apache Flink을 사용하여 새로운 실시간 알림 시스템을 구현한 과정을 설명합니다. 우리는 아키텍처, 주요 기술 선택의 근거, 그리고 확장 가능하고 효율적인 솔루션을 가능하게 한 Amazon Web Services(AWS) 서비스들을 살펴봅니다.

Nexthink는 디지털 직원 경험(DEX) 분야의 선구적인 리더입니다. IT 팀의 역량을 강화하고 직장 생산성을 향상시키는 것을 목표로, Nexthink의 Infinity 플랫폼은 최종 사용자 환경에 대한 실시간 가시성, 실행 가능한 인사이트, 강력한 자동화 기능을 제공합니다. Infinity는 실시간 분석, 선제적 모니터링, 지능형 자동화를 결합하여 조직이 최적의 디지털 작업 공간을 제공할 수 있도록 지원합니다.

지난 5년 동안 Nexthink는 하루에 수조 개의 이벤트를 처리하고 초당 5GB 이상의 집계된 처리량에 도달하는 완전한 클라우드 플랫폼으로 전환을 완료했습니다. 내부적으로 Infinity는 Amazon Managed Service for Apache Kafka(Amazon MSK)를 통해 데이터 수집 및 서비스 간 통신을 위해 Apache Kafka의 성능을 활용하는 300개 이상의 마이크로서비스로 구성되어 있습니다. Nexthink 생태계는 Amazon Elastic Kubernetes Service(Amazon EKS)에 배포된 수백 개의 Micronaut 기반 Java 마이크로서비스를 포함합니다. 대부분의 마이크로서비스는 Kafka Streams 프레임워크를 통해 Kafka와 상호 작용합니다.

Nexthink 알림 시스템

Nexthink의 새로운 실시간 알림 솔루션을 향한 여정을 이해하기 위해, 우리는 먼저 기존 시스템과 새로운 솔루션을 찾게 된 진화하는 요구사항들을 살펴보겠습니다.

Nexthink의 기존 알림 시스템은 준실시간 알림을 제공하여 사용자들이 중요한 이벤트를 신속하게 감지하고 대응할 수 있도록 도와줍니다. 이 시스템은 효과적이었지만, 확장성, 유연성, 실시간 처리 능력에서 한계가 있었습니다.

Nexthink는 수천 명의 고객 노트북에서 CPU 사용량, 메모리, 소프트웨어 버전, 네트워크 성능 등을 포함하는 원격 측정 데이터를 수집합니다. Amazon MSK와 ClickHouse가 이 데이터 파이프라인의 중추 역할을 합니다. 모든 엔드포인트 데이터는 Kafka 멀티테넌트 토픽으로 수집되어 처리된 후 최종적으로 ClickHouse 데이터베이스에 저장됩니다.

현재 알림 시스템을 사용하면, 클라이언트들은 Nexthink Query Language(NQL)로 모니터링 규칙을 정의할 수 있으며, 이는 15분마다 데이터베이스를 폴링하여 준실시간으로 평가됩니다. 클라이언트가 정의한 임계값이나 장기 기준선에 대해 이상이 감지되면 알림이 트리거됩니다. 이 프로세스는 아키텍처 다이어그램에 설명되어 있습니다.

처음에는 데이터베이스 폴링이 복잡한 알림을 평가하는 데 있어 큰 유연성을 제공했습니다. 하지만 이러한 접근 방식은 데이터베이스에 큰 부담을 주었습니다. 회사가 성장하고 더 많은 엔드포인트와 모니터를 가진 대규모 고객을 지원하게 되면서, 데이터베이스는 점점 더 큰 부하를 겪게 되었습니다.

새로운 사용 사례로의 진화: 실시간 알림

Nexthink가 가상 데스크톱 인프라(VDI)를 포함하도록 데이터 수집을 확장함에 따라 실시간 알림의 필요성이 더욱 중요해졌습니다. 5분마다 이벤트가 수집되는 노트북과 같은 전통적인 엔드포인트와 달리, VDI 데이터는 30초마다 수집되어 데이터의 양과 빈도가 크게 증가했습니다. 기존 아키텍처는 15분 간격으로 실행되는 데이터베이스 폴링에 의존하여 알림을 평가했습니다. 이 접근 방식은 30초마다 도착하는 메시지에 대해 거의 실시간으로 알림을 평가해야 하는 새로운 VDI 사용 사례에는 적합하지 않았습니다. 단순히 폴링 빈도를 높이는 것은 데이터베이스에 과도한 부하를 주어 성능 병목 현상과 확장성 문제를 야기하므로 이상적인 옵션이 아니었습니다. 이러한 새로운 요구사항을 효율적으로 충족하기 위해, 우리는 Kafka 토픽에서 직접 실시간 알림 평가로 전환했습니다.

기술 옵션

실시간 알림 시스템을 위한 솔루션을 평가하면서, 우리는 Apache Kafka StreamsApache Flink라는 두 가지 주요 기술 옵션을 분석했습니다. 각 옵션에는 고려해야 할 장단점이 있었습니다.

당시까지 모든 Nexthink 마이크로서비스는 Apache Kafka Streams를 사용하여 Kafka와 통합되었습니다. 실제로 다음과 같은 여러 이점을 관찰했습니다:

  • 경량화되고 원활한 통합. 추가 인프라가 필요 없음.
  • RocksDB를 로컬 키-값 저장소로 사용하여 낮은 지연 시간 실현.
  • 팀 전문성 : Nexthink 팀은 오랫동안 Kafka-streams로 마이크로서비스를 작성해왔고 사용이 매우 익숙함.

하지만 일부 사용 사례에서 다음과 같은 중요한 제한사항을 발견했습니다:

  • 확장성 – 마이크로서비스의 병렬 처리와 Kafka 토픽의 파티션 수 간의 긴밀한 결합으로 인해 확장성이 제한되었습니다. 많은 마이크로서비스가 이미 소비하는 토픽의 파티션 수에 맞춰 확장되어 있어 추가 확장이 제한되었습니다. 한 가지 해결책은 파티션 수를 늘리는 것이었습니다. 하지만 이 접근 방식은 특히 다른 도메인이 소유한 토픽을 소비하는 마이크로서비스와 관련하여 상당한 운영 부담을 초래했습니다. 전체 Kafka 클러스터의 재조정이 필요했고 여러 팀 간의 조정이 필요했습니다. 또한 이러한 수정은 상태 저장 처리의 신중한 재구성이 필요한 다운스트림 서비스에 영향을 미쳤습니다. 대안적 접근 방식은 작업량을 재분배하기 위해 중간 토픽을 도입하는 것이었지만, 이는 데이터 파이프라인의 복잡성을 증가시키고 Kafka의 리소스 소비를 증가시켰을 것입니다. 이러한 과제들로 인해 더 유연하고 확장 가능한 접근 방식이 필요하다는 것이 분명해졌습니다.
  • 상태 관리 – 메모리에 대규모 KTable을 생성해야 하는 서비스는 시작 시간이 증가했습니다. 또한 내부 상태의 볼륨이 큰 경우, 내부 상태 생성 중에 Kafka 클러스터에 상당한 부하가 발생했습니다.
  • 지연 이벤트 처리 – Windowing 작업에서 지연 이벤트는 코드베이스를 복잡하게 만드는 기술로 수동 관리해야 했습니다.

현재 시스템이 제기하는 과제들을 극복할 수 있는 대안을 찾으면서, 우리는 Flink를 평가하기로 결정했습니다. 강력한 스트리밍 기능, 확장성, 유연성으로 인해 Kafka 토픽 기반의 실시간 알림 시스템을 구축하기에 탁월한 선택이었습니다. 다음과 같은 여러 장점으로 인해 Flink가 특히 매력적이었습니다.

  • Kafka와의 네이티브 통합 – Flink는 Nexthink 생태계의 중심 구성 요소인 Kafka용 네이티브 커넥터를 제공합니다.
  • 이벤트 시간 처리 지연 이벤트 지원 – Flink는 메시지가 순서가 맞지 않게 도착하더라도 이벤트 시간(즉, 실제 이벤트가 발생한 시간)을 기준으로 처리할 수 있습니다. 이 기능은 실시간 알림의 정확성을 보장하므로 매우 중요합니다.
  • 확장성 – Flink의 분산 아키텍처를 통해 Kafka 토픽의 파티션 수와 독립적으로 수평 확장이 가능합니다. 파티션 수에 대한 의존성이 지금까지 우리 플랫폼의 큰 제한사항이었기 때문에 이 기능은 의사 결정에 큰 영향을 미쳤습니다.
  • 장애 허용성 – Flink는 체크포인트를 지원하여 관리되는 상태를 지속시키고 장애 발생 시 일관된 복구를 보장합니다. 장기 상태 지속성을 위해 Kafka 자체에 의존하는(클러스터에 추가 부하 발생) Kafka Streams와 달리, Flink의 체크포인팅 메커니즘은 독립적으로 작동하고 대역 외에서 실행되어 효율적인 상태 관리를 제공하면서 Kafka에 대한 영향을 최소화합니다.
  • Amazon Managed Service for Apache Flink – Amazon Managed Service for Apache Flink는 실시간 데이터 처리를 위한 Flink 애플리케이션의 배포, 확장, 관리를 단순화하는 완전 관리형 서비스입니다. AWS는 Flink 클러스터 관리의 운영 복잡성을 제거함으로써 조직이 실시간 분석 및 이벤트 기반 애플리케이션을 효율적으로 구축하고 실행하는 데 집중할 수 있게 합니다. Amazon Managed Service for Apache Flink는 우리에게 상당한 유연성을 제공했습니다. 이를 통해 평가 프로세스가 간소화되어 내부 Flink 클러스터 관리의 복잡성 없이 빠르게 개념 증명 환경을 설정할 수 있었습니다. 또한 클러스터 관리의 오버헤드를 줄임으로써 Flink를 실행 가능한 기술 선택으로 만들고 제공 일정을 앞당겼습니다.

솔루션

두 옵션을 신중히 평가한 후, 우리는 우수한 확장성, 강력한 이벤트-시간 처리, 그리고 효율적인 상태 관리 기능을 갖춘 Apache Flink를 우리의 솔루션으로 선택했습니다. 다음은 우리가 새로운 실시간 알림 시스템을 구현한 방법입니다.

다음 다이어그램은 솔루션 아키텍처입니다.

첫 번째 사용 사례는 VDI의 문제를 감지하는 것이었습니다. 하지만 우리의 의도는 현재 폴링을 통해 구현된 기존 사용 사례들을 향후 온보딩할 수 있는 옵션을 제공하는 일반적인 솔루션을 구축하는 것이었습니다. 우리는 모니터링 조건을 구성하는 공통된 방식을 유지하고, 모니터링되는 장치 유형에 따라 폴링과 실시간 모두에서 알림 평가를 가능하게 하고자 했습니다.

이 솔루션은 여러 부분으로 구성됩니다:

  • 모니터 구성 – Nexthink Query Language (NQL)를 사용하여 알림 관리자는 다음과 같은 사항을 지정하는 모니터를 정의합니다:
    • 데이터 소스 – VDI 이벤트
    • Window – 30초마다
    • 메트릭 – 데스크톱 풀별로 그룹화된 평균 네트워크 지연 시간
    • 트리거 조건 – 5분 동안 지속적으로 300ms를 초과하는 지연 시간

이 모니터 구성은 내부적으로 개발된 문서 저장소에 저장되고 Kafka 토픽으로 다운스트림에 전파됩니다.

  • Generic Stream Services 사용한 데이터 처리 – 엔드포인트에 설치된 에이전트인 Nexthink Collector는 설치된 VDI 엔드포인트에서 다양한 종류의 활동을 캡처하고 보고합니다. 이러한 이벤트들은 Nexthink의 프로덕션 가상 사설 클라우드(VPC) 중 하나에 있는 Amazon MSK로 전달되고, Nexthink 내의 여러 도메인에 속한 Amazon EKS에서 실행되는 Java 마이크로서비스에 의해 소비됩니다.

그 중 하나가 Generic Stream Services로, 수집된 이벤트를 처리하고 30초 단위로 버킷에 집계하는 시스템입니다. 이 컴포넌트는 Nexthink의 모든 기능 팀을 위한 셀프 서비스로 작동하며 NQL 쿼리에서 데이터를 조회하고 집계할 수 있습니다. 이를 통해 알림이 어떻게 평가되는지와 관계없이 NQL을 사용하는 모니터 구성에서 통일된 사용자 경험을 유지할 수 있었습니다. 이 컴포넌트는 두 가지 서비스로 나뉩니다:

  • GS 프로세서 – 원시 VDI 세션 이벤트를 소비하고 초기 처리를 적용
  • GS 집계기 – 모니터 구성에 따라 데이터를 그룹화하고 집계
  • Flink 사용한 실시간 모니터링 – 정적 임계값 알림은 시간이 지남에 따라 반복되는 패턴을 따르는 데이터의 변동을 식별하는 계절적 변화 감지는 VDI 문제에 대해 우리가 제공하는 두 가지 유형의 감지입니다. 시스템은 두 애플리케이션 간에 처리를 분할합니다:
    • 베이스라인 애플리케이션 – 시간대별 이상 감지 알고리즘을 사용하여 계절성을 가진 통계적 베이스라인을 계산합니다. 예를 들어, VDI 클라이언트 위치별 지연 시간이나 데스크톱 풀의 CPU 대기열 길이 등입니다.
    • 알림 애플리케이션 – 예기치 않은 값이 시간이 지나도 변하지 않을 때는 사용자 정의 임계값을 기준으로, 메트릭이 예상 패턴에서 벗어날 때는 베이스라인 기반의 동적 임계값을 기준으로 알림을 생성합니다.

다음 다이어그램은 Apache Flink 내에서 VDI 메트릭과 모니터 구성을 결합하고, 슬라이딩 윈도우를 사용하여 데이터를 집계하고, 임계값 규칙을 평가하는 방법을 보여줍니다. 이 프로세스에서 생성된 알림은 알림 소비자에 의해 추가 처리되기 전에 그룹화되고 필터링됩니다.

  • 알림 처리 알림 – 알림이 트리거되거나(임계값 초과 시) 또는 복구되면(메트릭이 정상 수준으로 돌아올 때), 시스템은 영향 처리 모듈을 통해 대응의 우선순위를 정하기 위해 그 영향을 평가합니다. 그 후 알림은 이메일이나 웹훅을 통해 메시지를 전달하는 알림 서비스에 의해 소비됩니다. 알림 및 영향 데이터는 그 다음 시계열 데이터베이스에 수집됩니다.

새로운 아키텍처의 장점

폴링 대신 스트리밍 기반 접근 방식을 채택 한 주요 장점 중 하나는, 특히 3명의 엔지니어로 구성된 작은 팀에게 구성과 관리가 용이하다는 것이었습니다. 클러스터 관리가 필요하지 않았기 때문에, 서비스를 프로비저닝하고 코딩을 시작하기만 하면 되었습니다.

Kafka와 Kafka Streams에 대한 우리의 이전 경험과 관리형 서비스의 단순성이 결합되어, 복잡한 인프라 설정의 오버헤드 없이 새로운 알림 시스템을 신속하게 개발하고 배포할 수 있었습니다. Amazon Managed Service for Apache Flink를 사용하여 몇 시간 만에 개념 증명을 구축할 수 있었고, 이는 팀이 클러스터 관리와 관련된 걱정 없이 비즈니스 로직 정의에 집중할 수 있다는 것을 의미했습니다.

처음에는 여러 Kafka 토픽을 조인하는 것에 대한 과제를 우려했습니다. 이전 Kafka Streams 구현에서는 조인된 토픽에 동일한 파티션 키가 필요했는데, 이는 co-partitioning이라고 알려진 제약사항이었습니다. 이는 특히 서로 다른 비즈니스 도메인 간의 토픽을 통합할 때 유연하지 않은 아키텍처를 만들었습니다. 각 도메인은 자연스럽게 자체적으로 최적화된 파티셔닝 전략을 가지고 있어, 어려운 타협을 강요했습니다.

Amazon Managed Service for Apache Flink는 내부 데이터 파티셔닝 기능을 통해 이 문제를 해결했습니다. Flink가 조인 중에 클러스터 전체에 데이터를 재배포할 때 여전히 일부 네트워크 트래픽이 발생하지만, 오버헤드는 실질적으로 무시할 만한 수준입니다. 결과적으로 나온 아키텍처는 (토픽이 특정 처리량 요구사항에 따라 독립적으로 확장될 수 있어) 더 확장 가능하고, 복잡한 파티션 정렬 문제 없이 유지보수가 더 쉽습니다.

이는 아키텍처를 깔끔하고 효율적으로 유지하면서 실시간으로 VDI 성능 저하를 감지하고 대응하는 우리의 능력을 크게 향상시켰습니다.

Lesson Learned

모든 새로운 기술과 마찬가지로, 실시간 처리를 위해 Flink를 도입하는 것에는 자체적인 과제와 통찰이 따랐습니다.

우리가 직면한 주요 어려움 중 하나는 Flink의 내부 상태를 관찰하는 것이었습니다. 내부 상태가 기본적으로 Kafka 토픽에 의해 백업되어 그 내용을 시각화 할 수 있는 Kafka Streams와 달리, Flink의 아키텍처는 실행 중인 작업 내부에서 무슨 일이 일어나고 있는지 검사하기가 본질적으로 어렵습니다. 이로 인해 실행 중에 발생하는 일을 더 잘 이해하고 문제를 효과적으로 디버깅하기 위해 강력한 로깅과 모니터링 전략에 투자해야 했습니다.

또 다른 중요한 통찰은 지연 이벤트 처리, 특히 윈도우의 경계 내에 있지만 해당 윈도우가 닫힌 후에 도착하는 타임스탬프를 가진 이벤트를 관리하는 것과 관련하여 나타났습니다. Amazon Managed Service for Apache Flink는 내장된 워터마킹 메커니즘을 통해 이 과제를 해결합니다. 워터마크는 특정 시간 이전의 모든 이벤트가 도착했다고 Flink가 판단해야 할 시점을 나타내는 타임스탬프 기반 임계값입니다. 이를 통해 시스템은 윈도우 집계와 같은 시간 기반 작업을 처리할 시기에 대해 정보에 기반한 결정을 내릴 수 있습니다. 워터마크는 스트리밍 파이프라인을 통해 흐르면서, 순서가 맞지 않는 이벤트가 있더라도 Flink가 이벤트 시간 처리의 진행 상황을 추적할 수 있게 합니다.

워터마크가 지연 데이터를 관리하는 메커니즘을 제공하지만, 서로 다른 속도로 작동하는 여러 입력 스트림을 다룰 때 과제가 발생합니다. 워터마크는 단일 소스의 이벤트를 처리할 때는 잘 작동하지만, 속도가 다른 스트림을 조인할 때는 문제가 될 수 있습니다. 이는 의도하지 않은 지연이나 조기 데이터 폐기를 초래할 수 있기 때문입니다. 예를 들어, 느린 스트림이 전체 파이프라인의 처리를 지연시킬 수 있고, 유휴 스트림이 윈도우를 조기에 닫게 할 수 있습니다. 우리의 구현에는 처리의 적시성과 데이터 완전성의 균형을 맞추기 위해 워터마크 전략과 허용 가능한 지연 매개변수를 신중하게 조정해야 했습니다.

Kafka Streams에서 Apache Flink로의 전환은 처음 예상했던 것보다 더 순조로웠습니다. Java 배경과 Kafka Streams 사용 경험이 있는 팀은 Flink의 프로그래밍 모델이 직관적이고 사용하기 쉽다는 것을 발견했습니다. DataStream API는 친숙한 개념과 패턴을 제공하며, Flink의 더 고급 기능은 필요에 따라 점진적으로 도입할 수 있었습니다. 이러한 점진적인 학습 곡선은 우리 개발자들이 상태 관리와 지연 이벤트 처리와 같은 더 고급 개념으로 넘어가기 전에 먼저 핵심 스트림 처리 작업에 집중하면서 빠르게 생산성을 높일 수 있는 유연성을 제공했습니다.

Nexthink에서의 Flink의 미래

실시간 알림 시스템이 현재 프로덕션에 배포되어 고객들이 사용할 수 있게 되었습니다. 이 프로젝트의 주요 성공 요인은 매우 적은 관리 요구사항으로, 보장된 확장성, 데이터 관리의 유연성, 그리고 비슷한 비용으로 Kafka streams의 대안으로서 새로운 기술을 성공적으로 도입했다는 점입니다.

Nexthink 알림 시스템에 미친 영향은 상당했습니다. 더 이상 데이터베이스 폴링을 통한 단일 알림 평가에 의존하지 않게 되었기 때문입니다. 따라서 우리는 이미 다른 알림 사용 사례들을 Flink를 통한 실시간 평가로 전환하기 위한 일정을 평가하고 있습니다. 이를 통해 데이터베이스 부하를 줄이고 알림 트리거의 정확성도 향상시킬 수 있을 것입니다.

하지만 Flink의 영향은 Nexthink 알림 시스템에만 국한되지 않습니다. 이제 우리는 소비하는 토픽의 파티션 수로 인해 확장성이 제한된 서비스들을 위한 검증된 프로덕션 레벨의 대안을 보유하게 되었습니다. 따라서 우리는 더 유연한 확장이 가능하도록 더 많은 서비스를 Flink로 전환하는 옵션을 적극적으로 평가하고 있습니다.

Amazon Managed Service for Apache Flink는 Nexthink의 실시간 알림 시스템에 혁신적인 변화를 가져왔습니다. AWS가 복잡한 인프라 관리를 처리함으로써, 우리 팀은 한 달도 안 되는 기간 내에 정교한 스트리밍 솔루션을 배포할 수 있었고, Flink 클러스터 관리보다는 비즈니스 가치 제공에 집중할 수 있었습니다.

Flink의 기능들은 단순히 Kafka Streams의 대안이 되는 것 이상임이 입증되었습니다. 새로운 프로젝트와 기존 기능 리팩토링 모두에서 매력적인 첫 번째 선택지가 되었습니다. 윈도우 처리, 지연 이벤트 관리, 상태 저장 스트리밍 작업을 통해 복잡한 사용 사례를 놀라울 정도로 간단하게 구현할 수 있게 되었습니다. 우리 개발팀이 계속해서 Flink의 잠재력을 탐구함에 따라, 앞으로 Nexthink의 실시간 데이터 처리 아키텍처에서 중심적인 역할을 할 것이라는 확신이 더욱 커지고 있습니다.

Amazon Managed Service for Apache Flink를 시작하려면, 시작하기 리소스와 실습 워크샵을 살펴보세요. Nexthink의 더 넓은 AWS 여정에 대해 알아보려면, Nexthink의 MSK 기반 아키텍처에 대한 블로그 포스트를 방문하세요.

Jaemin Jung

Jaemin Jung

정재민 Solutions Architect는 고객이 AWS와 함께 성공적인 Cloud 여정을 시작하기 위해 최적의 아키텍트를 구성하고 지원하는 역할을 하고 있습니다.