brunch

You can make anything
by writing

C.S.Lewis

by 티맵모빌리티 Dec 23. 2021

실시간 운전점수를 위한 Apache Flink

티맵 개발자 SSUL 4편- 실시간 운전점수 데이터 스트림의 비밀 

Chap1. 티맵 운전습관 서비스 이야기

1-1. TMAP 운전습관이란?

1-2. 과거의 TMAP 운전습관

1-3. 현재의 실시간 운전습관

Chap2. 실시간 운전습관에 사용된 Apache Flink

2-1. Apache Flink란?

2-2. Session Windows

2-3. Checkpoint

Chap3. 향후 과제


Chap1. 티맵 운전습관 서비스 이야기


1-1. TMAP 운전습관이란?

TMAP 운전습관 이용해 보셨나요? 운전습관은 운전자가 티맵으로 길안내 서비스를 받을 때, 주행이력을 기록해 과속을 얼마나 하고 있는지, 급 브레이크를 밟았는지, 급하게 가속을 했는지 등을 분석합니다. 운전자 자신도 모르고 지나칠 수 있는 운전습관을 관리해주는 서비스인거죠.


이를 이용해 운전자는 운전습관의 개선포인트를 알 수 있게 되고, 운전점수와 등수 등의 재미요소들로 더 좋은 운전습관을 가지려고 노력하게 됩니다. 나아가 운전점수가 높으면 자동차 보험 할인 혜택까지 누릴 수 있으니 누이좋고 매부좋은 서비스라고 할 수 있습니다.


더 나아가서는 수천억원의 사회적 가치를 창출합니다. 효율적인 운전습관은 교통사고를 줄일 뿐만 아니라 이산화탄소 배출량을 줄여 환경에 기여하거든요. 최근 전세계적인 화두인 ESG를 실천하는 티맵모빌리티의 자랑스러운 대표 서비스죠. 운전습관의 ESG 가치에 대한 내용은 아래에서 더 자세히 보실 수 있습니다.  

너무 서비스 자랑만 했나요? 이제 슬슬 기술의 이야기로 넘어가려고 합니다. 다음 보시죠~


1-2. 과거의 TMAP 운전습관

과거의 운전습관은 실시간이 아닌 배치 방식으로 개발되었습니다. 이 방식은 주행이력이 쌓이면 12시간 마다 배치가 돌아서 과거 주행에 대한 운전습관 결과를 남기는 방식이었는데요. 

잠깐 부연설명을 드리자면, 운전습관은 데이터, 서비스 2가지 파트로 분리해서 관리하고 있습니다. 데이터는 주행이력을 분석하여 사용자의 운전습관을 추출하는 파트이고, 서비스는 추출한 데이터를 가지고 사용자에게 서비스할 수 있는 구조로 가공하는 파트로 생각해주시면 됩니다.


과거의 동작방식은 티맵으로 길안내를 받으면 앱에서 주기적으로 주행정보를 올려주어 Kafka 에 적재하고 이를 Hadoop(HDFS) 에 저장하여 Hive 쿼리를 12시간마다 실행시켜 운전습관을 분석하고, 그 결과를 적절하게 가공하여 서비스 DB에 적재해서 운전습관 서비스를 제공하도록 개발됐습니다.

그런데 이 구조의 문제는 주행이 끝났을 때 바로 운전습관 정보를 확인하고 싶어도 배치가 도는 시간이 도래할 때까지 최대 12시간 동안은 새로운 주행에 대한 정보를 볼 수 없었어요. 12시간 동안 모인 대용량 데이터를 Hive 쿼리 작업으로 운전습관을 분석하고 추출하는 시간이 오래 걸리기도 했습니다.


1-3. 현재의 실시간 운전습관

운전습관 서비스의 이용자가 늘면서 실시간 분석에 대한 필요성이 증가하게 됐고, 이를 해결하기 위해 스트리밍 처리가 가능한 Apache Flink(https://flink.apache.org/) 를 도입하게 되었습니다.


Flink 는 앱에서 올려주는 메시지를 Kafka에서 실시간으로 consume 하여 주행정보 분석을 진행하는 역할을 담당합니다. 

Flink의 기능 중에 Session Windows 기능을 활용하여 사용자의 주행 별로 데이터를 쌓게 하고, 해당 세션의 데이터를 분석하면 하나의 주행이 분석이 되는 구조로 설계됐습니다.


과거의 운전습관에서는 모든 주행정보를 Hadoop(HDFS) 에 저장하고 이를 분석한 반면, 실시간 운전습관에서는 현재 주행 중이라고 판단이 되는 주행정보만 메모리에 보관하고, 주행이 종료되었다는 판단이 될 때 분석을 종료시키고 분석된 결과를 Kafka 에 produce 하는 구조로 변경하였습니다.


그럼 운전습관에서 사용하고 있는 기술인 Flink 에 대해서 좀 더 알아보실까요?


Chap2. 실시간 운전습관에 사용된 Apache Flink


2-1. Apache Flink란?

Apache Flink 다들 들어보셨나요? 아직까지는 국내에서 많이 사용하고 있지 않아서 생소하신 분들이 많을 것 같습니다. flink는 분산 스트림 처리를 하는 엔진으로 상태가 있는 스트림 처리를 하는 데 적합한 프레임워크입니다.

(공식홈페이지에 가시면 Flink를 활용한 서비스 소개를 하고 있는데요. 티맵 운전습관에 대한 내용도 보실 수 있습니다. https://flink.apache.org/poweredby.html - SK telecom 서비스로 소개됨.)


스트림 처리를 지원하는 프레임워크 중에 Spark, Kafka Streams, Storm 등이 있지만 마이크로 배치로 스트림을 처리하는 Spark는 최저 지연을 추구하는 운전습관의 목적에 맞지 않고, Kafka Streams는 데이터 소스가 Kafka만 지원되기 때문에 다양한 서비스를 이용하는 데 어려움이 있고, Storm은 Exactly Once 이벤트 처리를 지원하지 않는 문제를 가지고 있습니다.


Flink 는 배치의 시간을 짧게 가져가서 실시간 처리를 하려고 하는 마이크로배치가 아닌 Native 방식으로 처리하여 이벤트가 발생하는 즉시 처리를 하기 때문에 지연을 최소화하는데 유리합니다. 또한 Kafka 뿐만 아니라 다양한 커넥터를 지원하여 AWS의 Kinesis, RabbitMQ 등 여러 시스템을 사용할 수 있는 장점을 가지고 있습니다.

출처: flink 공식 홈페이지

그리고 Exactly Once 를 보장하기 때문에 장애가 나더라도 복구 시점에 유실없이 모든 데이터를 처리할 수 있는 메커니즘을 가지고 있습니다.


2-2. Session Windows

실시간 운전습관은 수백만의 주행 데이터를 모아서 분석하지 않고, 주행별로 데이터를 분리하여 다른 주행의 데이터가 분석 결과에 영향을 끼치지 않게 Flink의 Session Windows를 사용하여 주행의 라이프 사이클을 관리하고 있습니다. 

이 방식은 주행별로 세션을 생성하여 주행데이터가 들어오면 해당 세션에 할당되고 세션당 주행 분석 로직을 수행하여 하나의 주행에 대해서 빠른 분석을 할 수 있게 합니다. 또한 스트림 데이터가 네트워크 지연이나 터널 통과 등의 지연이 될 수 있는 상황에서 순서가 뒤바뀔 수 있는 가능성이 존재하는데, 세션 단위로 주행 데이터를 관리하게 되면 이러한 상황에서도 이벤트 발생 순서대로 정렬해서 분석을 할 수 있도록 상태 관리를 쉽게 할 수 있도록 도와주게 됩니다.


2-3. Checkpoint

Exactly Once를 보장하기 위해 Flink는 내부적으로 checkpoint 를 도입하였습니다.


대부분의 서비스가 그러하겠지만 운전습관 역시 운전습관 분석 시스템 장애 시에도 데이터가 유실되지 않고, 서비스가 정상화 되는 시점에 장애 상황에 발생한 데이터도 완벽하게 처리되는 것이 중요합니다. 또한 Flink 를 운영하면서 버전 업그레이드나 클러스터의 구성 변경시에도 서비스에 영향을 주지 않는 것이 중요합니다.


이와 같은 기능을 제공하기 위해 flink는 checkpoint, savepoint 가 존재합니다. checkpoint의 기본적인 동작 방식은 다음과 같습니다.

1. checkpoint 시점에 인입을 정지시키고
2. 처리 중인 데이터가 있다면 완료할 때까지 대기합니다.
3. 처리가 완료되면 각 태스크의 상태를 복사해서 외부의 저장소로 checkpoint를 복사합니다.
4. 정지한 인입을 재시작 합니다.


여기서 좀 더 나아가 flink는 stop-the-world 문제를 해결하기 위해 Chandy-Lamport 알고리즘 기반으로 분산 스냅샷 체크포인트를 구현했습니다. 이 알고리즘은 전체를 정지하지 않고 checkpoint와 데이터 처리를 분리하여 일부 태스크는 상태를 저장하고 일부 태스크는 데이터를 계속 처리하게 됩니다.


좀 더 자세히 들어가면 체크포인트 배리어라는 레코드를 사용하여 레코드 스트림에 체크포인트 배리어를 주입합니다. 이 배리어는 다른 레코드를 추월할 수 없고 추월 당할 수 없어 이 체크포인트 배리어 레코드가 어떤 체크포인트에 속해 있는지를 식별하게 됩니다. 

출처: flink 공식 홈페이지

이 배리어를 기준으로 현재 체크포인트 포함될 상태와 다음 체크포인트에 포함될 상태를 구분하게 됩니다. 

출처: flink 공식 홈페이지

하나의 스트림으로 데이터는 들어오지만 빠른 데이터 처리를 위해 여러 파티션에서 데이터가 처리되게 되는데, 이 때 파티션의 테스크 상황에 따라 늦게 처리되는 파티션이 존재할 수 있고 빠르게 처리되는 파티션이 존재할 수 있습니다. 이 때 flink는 체크포인트 배리어 레코드가 모든 파티션에서 정렬이 될 때까지 대기를 하게 됩니다. 정렬이 끝나면 체크포인트가 시작되고 체크포인트 상태를 외부 저장소에 저장하고 다시 데이터 처리를 시작합니다.


flink 에 장애가 발생하여 일정시간이 지나 복구되었을 때는 외부 저장소에 저장되어 있던 체크포인트를 가져와서 체크포인트 시점의 상태을 복구하고, 체크포인트 시점으로 데이터 소스의 offset 을 조절하여 데이터 스트림을 재처리 하게 되는 구조입니다. 만약에 데이터 소스를 Queue 와 같이 데이터가 소비되면서 데이터가 삭제되는 시스템에서는 이 구조가 불가능한데요. 그래서 일반적으로 Kafka나 Kinesis 같은 여러번 소비를 할 수 있는 브로커를 연결하여 사용합니다.


그리고 checkpoint로 복구가 되는 상황에서 상황에 따라 일부 레코드는 여러 번 sink(결과를 produce) 가 될 수 있는데, 이를 위해 동일한 데이터를 여러번 저장해도 동일한 내용을 저장하는 멱등성을 보장하도록 저장 방식이 구성되어 있어야 합니다.


이렇게 flink를 사용하면 Exact Once 가 보장되어 데이터 안정성을 확보할 수 있습니다.


Chap3. 향후 과제


티맵모빌리티는 2020년 12월에 SK텔레콤에서 분사하여 작은 조직이 되었습니다.


지금까지 On-Premise(IDC) 환경에서 시스템을 구축해서 사용하였는데 분사로 인해 관리와 운영 조직이 작아져 운영의 최적화를 위해 AWS로 이전을 계획하고 있습니다. AWS의 Kinesis Data Analytics 에서 Flink를 지원해서 이 서비스로 On-Premise의 Flink를 이전하고, Kafka 를 Kinesis Data Streams로 대체하는 작업까지 프로토타입을 만들어 진행하였고 가능성을 확인한 단계입니다.


가능성을 확인하는 용도로 만든 프로토타입이기 때문에 아직 남은 과제들이 많지만 클라우드 서비스로 전환하게 되면 예상치 못했던 트래픽이 급증한 상황에서도 유연하게 대처할 수 있고 좀 더 유연하고 안정적인 서비스를 할 수 있어 향후 과제로 삼고 있습니다.


앞으로도 계속 진화 발전하는 티맵 운전습관을 지켜봐 주시고 사랑해 주셨으면 합니다~! 감사합니다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari