대메뉴 바로가기 본문 바로가기

데이터 기술 자료

데이터 기술 자료 상세보기
제목 실시간 빅데이터 분산 처리 기술
등록일 조회수 8427
첨부파일  

실시간 스트리밍 데이터 처리의 이해

실시간 빅데이터 분산 처리 기술



빅데이터라는 단어가 왜 일반인들에게 익숙해졌을까. 10년 전, 20년 전 아니 그보다 훨씬 이전에도 우린 빅데이터 속에 살고 있었다. 그런데 지금에서야 이 단어가 모든 산업에서 큰 이슈로 자리잡은 건 하드웨어, 소프트웨어 기술이 발전해서다. 관념으로만 존재하던 빅데이터를 머리로 가늠하고 활용할 수 있는 시대가 온 것이다. 그리고 빅데이터 시대의 핵심은 데이터 분산 처리 기술이다.



사물인터넷(IoT) 기술의 특성상 로그를 빠르게 분석하고 기기 역시 실시간으로 반응하는 것처럼 보이게 하는 것이 과제가 됐다. 빅데이터 분석은 필수가 됐다. 의미가 없거나 혹은 단순한 의미만을 지닌 데이터로부터 실시간으로 의미있는 정보를 찾는 것 자체가 가치를 창출하는 일이다. 이번 글에서는 실시간 분석을 빅데이터에 적용하면 어떤 방식이 되는지 알아보자.



람다(Lamda) 아키텍처

거대한 양의 데이터가 매분 매초 쌓이는 상황에서 통계를 내야하고 이를 바탕으로 보고서를 작성해야할 일이 늘었다. 고객의 데이터 로그를 분석해 지금 왜 이런 일이 벌어지고 있는지 알아내라는 지시도 있었다. 하지만 하둡 배치 프로세스가 돌려면 저녁까지 기다려야 하고 수동으로 해도 1시간을 기다려야 하는 상황이다. 매일 저녁 처리되는 하둡 배치 프로세스 보고서를 기다릴 여유조차 사라진 것. 이 문제를 해결하기 위해 빅데이터 처리 아키텍처를 만들었다. 병렬 처리 분석 아키텍처인 Lamda Architecture(이하 람다 아키텍처)다. 이로써 기본 아키텍처만 지킨다면 큰 시행착오 없이 빅데이터 처리 시스템을 구축할 수 있게 됐다.

람다 아키텍처는 나단 마르츠(Nathan Marz)가 제안한 데이터 프로세싱 아키텍처다. 에러 수용적이고 확장성이 높으며 읽기와 업데이트 작업을 수행하는 데에 대기시간이 짧다. 에러 수용적이라는 표현은 영어 단어로 ‘Fault-Tolerant’인데, 사람 또는 기계에서 발생할 수 있는 모든 에러에도 불구하고 복구와 정상 동작이 가능하다는 것을 말한다. 그러면서도 특정 분야만이 아닌 다양한 분야의 분석을 목적으로 프로그래밍될 수 있어야 한다. 데이터의 빠른 읽기/쓰기를 지원하며 스케일아웃으로 확장성을 보장해야 한다는 것이다.



람다 아키텍처로 설계된 시스템에 입력된 모든 데이터(이벤트)는 2개의 레이어로 전달된다. 각각의 레이어는 그 목적이 다르다. 첫 번째는 변하지 않는 히스토리 데이터를 배치 형식으로 모아서 처리하는 ‘배치 레이어(Batch Layer)’다. 이는 하둡과 같은 기존 빅데이터 분산처리로 가능한 부분이다. 두 번째 레이어가 실시간 분석을 통해 실시간 정보를 만들어내는 ‘스피드 레이어(Speed Layer)’다.



스피드레이어를 담당하는 아파치 스톰(Storm)

스피드 레이어에서 실시간 빅데이터 분석을 위해 개발된 아파치 스톰에 대해 설명하겠다. 스톰은 실시간 스트리밍 데이터 분석 솔루션이다. ‘백타입(BackType)’에서 개발됐고 이후 트위터에 인수돼 오픈소스로 공개됐다. 분산, 회복, 실시간이 기본 특징이다. 람다 아키텍처와 기본적으로 비슷하다.



하둡이 배치 분석에 특화된 대용량 분산 처리 시스템이라면, 스톰은 실시간 분석에 특화된 분산 처리 시스템이다. 실시간 특징을 부각한 하둡이라고 하면 개념상 이해하기 쉬울 것이다. 마르츠 스톰 프로젝트 의장은 스톰을 “맵리듀스가 병렬 배치 프로세싱을 쉽게 작성하는 것처럼 실시간 분야의 구멍을 메우는 소프트웨어이며 실시간 프로세싱을 위해 수동으로 큐 네트워크와 워커를 자동으로 구축한다”고 소개했다. 스트림 분산 처리 아키텍처를 자동으로 구축/관리해주는 프레임워크라고 이해하면 쉽겠다. 그 밖에 분산 RPC 기능, 이벤트 처리 보장 기능 등을 지원하고 있다. 스톰의 경우 지속적인 버전업으로 성능과 기능 향상이 돼 가고 있다. 활발한 커뮤니티 활동, 실제 상용화한 레퍼런스를 보면 알 수 있다.





간단한 사용 예제

스톰을 이용할 경우 2회에 실린 하둡 맵리듀스를 이용한 ‘단어 개수를 세기’ 예제가 어떻게 변할 수 있는지 알아보자. 다음은 자바 샘플 코드다.



<리스트 1> 단어 수 세기 TopologyBuilder builder = new TopologyBuilder(); builder.setSpout("spout", new RandomSentenceSpout(), 5); builder.setBolt("split", new SplitSentence(), 8).shuffleGrouping("spout"); builder.setBolt("count", new WordCount(), 12).fieldsGrouping("split", new Fields("word")); Config conf = new Config(); conf.setDebug(true); StormSubmitter.submitTopologyWithProgressBar(args[0], conf, builder.createTopology());



샘플 코드를 통해 스톰을 사용하기 위해 알아야하는 개념을 파악할 수 있다. 위 샘플 코드에서는 ‘토폴로지 빌더(Topology Builder)’ 클래스, ‘setSpout’, ‘setBolt’, ‘shuffleGrouping’ 함수가 눈에 띈다. 이를 통해 스톰을 사용하기 위해서는 다음의 개념을 알아야 함을 알 수 있다.





스톰 기본 개념

스톰의 기본 개념들에 대해 알아보도록 하자. 스톰은 개발자들에게 실시간 분석 로직을 분산 처리 시스템에서 효과적으로 동작할 수 있도록 유도하는 프레임워크다. 즉, 스톰이 제공하는 클래스와 함수를 적절히 사용하면, 나머지 분산, 병렬 처리는 스톰이 알아서 해준다. 그러나 스톰 프레임워크를 정확히 이해한 사람만 누릴 수 있는 이점이라는 걸 명심하자.



Queue-Worker model

스톰이 데이터를 처리하는 기본 모델은 Queue-Worker Model(이하 큐-워커 모델)이다. 큐-워커 모델은 처리해야할 작업이 많을 경우에 이를 병렬로 처리할 수 있는 효과적인 데이터 처리 모델이다. 다수의 워커(Worker)를 생성하고, 이를 풀(Pool)로 관리한다. 처리해야할 작업을 우선 큐(Queue)에 쌓아 놓는다. 작업 관리자는 큐에 작업이 쌓여 있을 경우, 작업을 하고 있지 않는 워커에 해당 작업을 할당한다.



Tuple

스톰에서 처리되는 데이터 스트럭처를 가리킨다. 기본적으로 integers, longs, shorts, bytes, strings, doubles, floats, booleans, byte arrays 등으로 정의된다. 물론 유동적으로 사용자 타입으로 정의될 수 있다. 이 경우에는 스톰에서 Tuple을 어떻게 직렬화(Serialize)해야 하는지 정의해야 한다. 일반적으로 위 그림과 같이 비정형 데이터 형식인 Key, Value로 정의하여 사용한다. 외부 또는 내부의 데이터를 받아 스톰이 처리할 수 있는 단위인 Tuple로 나누어 사용하는 것이다.





Stream

스트림은 스톰에서 사용되는 중요 추상화 단위이다. 이는 연속적으로 들어오고, 나가는 Tuple의 모음을 가리킨다. 기본적으로 스트림은 끝없이 들어온다고 가정한다. 스톰이 "continuous computation"을 지원한다는 것은 스톰에서 처리 대상으로 하고 있는 스트림이 끓임없이 입력되는 데이터이기 때문이다. 끊임없는 데이터에서 실시간으로 유용한 데이터를 찾는 것이 스톰의 역할이다.





Spout

Spout는 스트림의 소스다. 즉, 스트림이 생성 또는 전달되는 곳이다. 보통은 외부 컴포넌트, 시스템으로 부터 데이터를 받아서 스톰에 전달해준다. Spout에 의해 스톰의 한 가지 특징인 ‘Reliability’다. Spout의 설정에 따라서 메시지가 처리되지 못했을 경우 이를 다시 처리할 것인지, 그냥 지나칠 것인지를 결정한다. 이때 설정값은 ‘메시지 타임아웃’ 값이다. 시간 내에 tuple에 대한 처리 성공여부를 수신 받지 못하게 될 경우, 실패한 tuple을 재실행해 신뢰성을 유지한다. Spout의 경우 스톰에서 지원하는 라이브러리를 통해 다른 솔루션과 함께 사용할 수 있다. 대표적인 것인 Kafka와 Kestrel이다. 대규모 메시지를 전달이 가능한 Kafka와 같은 솔루션을 함께 사용해 스톰 Spout로 데이터를 실시간으로 전달하는 것이 가능하다.





Bolt

Bolt는 스톰에서 프로세싱을 담당한다. 즉, 실제 데이터(Tuple)을 처리하는 부분이다. 데이터 처리 단계에서는 필터링, 기능, 어그리게이션, 조인, DB운영 등 프로그래밍 가능한 모든 로직을 담을 수 있다. Bolt를 사용하여 간단한 스트림 변형은 물론 다수의 Bolt와 Stream으로 복잡한 Stream transformation도 가능하다. Bolt는 처리할 데이터를 인풋 스트림을 통해서 받는다. 다수의 인풋 스트림을 수신할 수 있지만 일일이 정의해줘야 한다. 처리된 결과도 Stream으로 출력 가능하다. 이 때, ‘declareStream’을 이용해 1개 이상의 아웃풋 스트림을 정의하여 사용할 수 있다.





Topology

토폴로지는 spout와 bolt가 스트림 그룹으로 연결된 그래프를 말한다. 우리가 분석하려는 전체 로직이라고 생가하면 쉽다. 토폴리지를 어떻게 설계하느냐는 개발자의 몫이다. 하둡과 비교하자면 맵리듀스의 작업에 대응된다. 차이점은 맵리듀스 작업의 경우 끝이 있지만 토폴로지의 경우에는 끝나지 않고 계속 수행될 수 있다. 토폴로지의 입력단인 Spout에 데이터가 입력되는 한 끊임없이 토폴로지가 동작하면서 분석이 이뤄지는 것이다.





Stream Grouping

Bolt가 여러 개 존재할 때, 특정 Bolt에 특정한 종류의 Tuple을 보내야하는 경우, 즉 방향을 다시 정하는 것(Redirection)이 필요한 경우에 그루핑 기능을 활용하게 된다.





코드 구현

지금까지 스톰 프로그래밍을 하는데 있어서 필요한 주요 개념들에 대해서 알아보았다. 샘플 코드에 나오는 개념들을 두루 알아보았는데, 코드를 한 줄씩 리뷰해보면서 각각의 개념이 어떻게 코드로 구현되는지 간단히 알아보자.

TopologyBuilder builder = new TopologyBuilder();

토폴로지는 스톰을 통한 데이터 처리 로직이라고 하였다. 빌더를 이용하여 토폴로지를 정의하는 것이다. 빌더의 함수를 사용하여 토폴로지를 구성하는 ‘Spout’, ‘Bolt’를 정의하고, ‘Bolt’간에는 ‘StreamGrouping’을 이용해 스트림을 제어한다.

builder.setSpout("spout", new RandomSentenceSpout(), 5);

RandomSentenceSpout 클래스를 이용해 ‘Spout’를 정의했다. 첫 번째 파라미터는 Spout의 아이디를 의미하고, 마지막 파라미터는 병렬로 5개를 만들겠다는 것이다. RandomSentenceSpout 클래스는 랜덤하게 문자열을 생성해내는 코드를 넣었다. 그러나 이를 다르게 구성하여 파일로부터 로그를 읽어 들일 수도 있고, 트윗을 받아올 수도 있다. 데이터의 소스인 Spout를 다양하게 구성할 수 있다.

builder.setBolt("split", new SplitSentence(), 8).shuffleGrouping("spout");

SplitSentence 클래스를 이용하여 ‘Bolt’를 정의했다. 마찬가지로 첫 번째 parameter는 ‘Bolt’의 ‘ID’를 의미한다. 그리고 세 번째 파라미터는 ‘Bolt’를 8개 생성해, 병렬로 처리하겠다는 것이다. 해당 ‘Bolt’에는 ‘shuffleGrouping’ 함수를 이용해 그룹핑 방식을 선택했다. 코드에서는 ‘shuffle’ 방식, 즉 모든 ‘Bolt’에 ‘tuple’을 균등하게 분배할 것을 명시했다.



마치는 글

스톰은 데이터 스트림을 처리할 수 있는 프레임워크를 제공한다. 실시간으로 쏟아져 들어오는 데이터를 스톰의 Spout를 통해 받아들이고, 분석 로직이 구현된 Bolt에 입력하게 되면 우리가 원하는 분석 결과가 나오게 된다. 개발자가 해야 할 일은 Spout, Stream Grouping, Bolt로 구성된 토폴로지를 어떻게 구성할지 고민하는 것이다. 나머지 분산 처리는 프레임워크에 맡기면 된다. 또한 스톰의 분산 프로세스들이 중단없이 작동하기 위해서 스톰의 프로세스를 관리하는 다른 솔루션을 쓴다. 즉, 전 시간에 설명했던 분산 처리에서 쓰이는 클러스터 리소스 관리 프레임워크 위에서 스톰이 동작한다. 이는 ‘Zookeeper(주키퍼)’가 될 수도 있고, ‘Yarn’이 될 수도 있다. 스톰, 주키퍼와 같은 프레임워크 덕분에 하드웨어 오류는 물론 개발자의 코딩 실수까지 극복해가며 실시간으로 데이터를 처리하여 분석 결과를 알려 줄 것이다. 개발자, 기획자는 데이터를 분석하는 방법에만 집중하면 된다.



출처 : 마이크로소프트웨어 4월호

제공 : 데이터전문가 지식포털 DBguide.net