데이터 파이프라인, Kirin API 서비스 개발기
본 글은 Qraft Technologies의 How we built our data pipeline, Kirin API 를 번역한 글입니다.
저희 크래프트 테크놀로지스에서는 데이터 API 서비스, Krin API 를 리팩토링하고 있습니다. Kirin API 프로젝트는 AI Research 팀에서 처음 개발되었으며 금융쪽에서 잘 알려져 있는 S&P Global Compustat 미국 증시 데이터베이스나 톰슨로이터 Datastream 그리고 FRED 나 Quandl 같은 경제 지표 API 와 연동하여 여러 데이터를 하나의 endpoint 에서 제공합니다.
이 프로젝트에 대한 내부적, 그리고 외부적 수요가 커지면서 하나의 저희 (Research Platform) 팀이 맡아서 내부 pilot 프로젝트에서, 확장성과 가용성을 고려한 커머셜 프로젝트로 확장하게 되었습니다.
데이터 플로우
우선 아래 그림과 같은 가장 간단한 구조로 시작했습니다.
각기 다른 금융 데이터를 데이터베이스에 업로드하고 백엔드 레이어에서 각각의 API 를 클라이언트에서 제공하는 식입니다. 여기에서 클라이언트는 현재로써는 파이썬과 같은 개발언어에서 API를 호출하는 유틸 라이브러리 이며, 추후에 다른 언어 및 다른 플랫폼에도 지원할 계획을 가지고 있습니다.
이 구조에는 결정적인 문제들이 몇가지 있습니다.
현재로써는 사용자의 대다수가 저희 내부적으로 데이터를 활용하는 파이썬 개발자들이지입니다만, 추후에 파이썬 사용자뿐만 아니라, R사용자, 엑셀 플러그인 사용자 등 다른 인터페이스형태로도 지원이 되어야 할테니 말이죠. 또 다른 문제는 각 클라이언트의 버전들이 업데이트 되면서, 이것을 단일점에서 대응하려면 이에 따른 유지보수가 점점 늘어날 것이라는 점입니다.
추상적인 서비스 레이어 의 필요성
클라이언트 그룹들은 데이터를 가져오는 각기 다른 방식의 요구사항들을 가지고 있습니다. 따라서 백엔드 레이어는 필연적으로 그러한 복잡한 요구사항들은 만족해야만 하는데, 이로 인해 팀내에서는 프로젝트를 진행하면서 기민하게 대처할 수 없게 되고, 유지보수에 많은 노력을 쏟게 됩니다.
이와 같은 문제들을 해결한 마이크로 서비스 디자인 패턴 및 솔루션이 존재하는데 바로 Backend-For-Frontend(BFF) 패턴과 GraphQL 입니다.
BFF 그리고 GraphQL
BFF 디자인 패턴은 저희가 API 서비스에 벤치마킹햇던 하나의 모델이었습니다. 세부적인 내용은 여기에서 다룰 수는 없지만, 요점은 포괄적인 백엔드 서비스 대신, 비즈니스 로직을 공유하는, 실질적으로는 백엔드보다는 클라이언트에 해당되고 그에 맞춰진 API 를 개발하는 방식입니다.
BFF 가 클라이언트 관점에서 문제를 해결했다면, GraphQL 은 다른 한편으로 해당 구현체를 서버측에 그대로 구현할 수 있게 해줍니다. GraphQL 공식 문서 에 따르면, GraphQL 은 다음과 같이 정의되어 있습니다.
GraphQL is a query language for your API and a server-side runtime for executing queries by using a type system you define for your data.
GraphQL 클라이언트가 각자 원하는 특정한 리소스를 질의할수 있는 쿼리 언어를 제공함으로써 백엔드 서버의 구현에 간편함을 줍니다.
BFF 와 GraphQL, 두개 모두 하나의 API layers 에서 여러 클라이언트로부터의 다른 요구사항들을 만족 할 수 있는 방법을 제공합니다. 가장 큰 차이점은 BFF 는 (BFF 컴포넌트와 클라이언트가 하나의 모듈화된 컴포넌트로 쌍으로 이루기 때문에) 풀스택 구현에 초점이 맞춰져 있고, GraphQL 은 백엔드의 복잡성을 포괄할 수 있는 쿼리로 클라이언트 요청 자체에 자유도를 제공합니다. 저희는 GraphQL 을 사용하게 되었습니다.
왜 GraphQL 을 사용했을까?
가장 먼저 BFF 는 적용하는데에 여러가지 문제점들이 있을 수 있습니다.
- BFF 와 client 파트간의 비효율적인 협업프로세스(저희팀은 두 역할이 구분되어 있습니다.)
- 각 클라이언트별 수요량을 예측하기 어려움.
(특히나 많은 양의 유가증권 일별/월별 데이터를 가져와야 할 때) - 단일 장애점 문제
- 부수적인 디플로이의 복잡성.
다른 한편으로 GraphQL 은 클라이언트에 데이터요청에 자유도를 줌으로써 변화하는 API를 대응하는데에 도움을 줄 수 있습니다. 각 클라이언트 그룹은 AST(Abstract Syntax Tree) 구조로 데이터를 요청만 하면 되니깐 말입니다.
구현
현재 Kirin API 서비스는 GraphQL 을 적용하여 다음 그림 과 같은 구조를 지니고 있습니다.
각 클라이언트 그룹은 API 게이트웨이(GraphQL 서버)에 데이터 요청을 보내고 그에 해당하는 resolver 가 데이터를 원본 데이터 소스로부터 데이터를 가져옵니다. 데이터를 가져오면, 후처리 작업은 비동기 service worker 들로 인해 진행이 된 후에 클라이언트에 결과값을 보내게 됩니다.
저희의 CICD 에 해당하는 자동화 파이프라인은 스케쥴 배치를 돌려 데이터 원본의 데이터를 체크해서 데이터의 무결성과 각 클라이언트가 호환되는 버전을 유지할 수 있도록 해줍니다.
캐시 정책
GraphQL 의 resolver들은 각자 독립적으로 실행되기 때문에, 요청간 중복된 데이터가 있는지 사전에 체크되어야 합니다. 먼저 cache 에 데이터가 있는지 조회를 하고 만약 데이터가 없다면 fallback 하여 데이터 원본으로 부터 데이터를 가져올 수 있게 되어 있습니다.
— — — — — — — — — — — — — — — — — — — — — — — — — —
현재 저희 팀은 이 서비스가 좋은 제품이 될 수 있도록 개발에 박차를 가하고 있습니다. 이 첫 서비스가 많은 퀀트 그리고 금융쪽에서 AI 연구하시는 분들께 도움이 되고, 훗날 저희 리서치 플랫폼의 좋은 기반되었으면 좋겠네요.
혹시 Qraft Kirin API 에 관심이 있으신 분들이 있으시다면, 저희 Research Platform은 같이 일할 열정적인 분들을 찾고 있습니다. 쉽게 배울 수 있습니다.
어서 지원해주세요.
믿어주세요.
We believe highly-efficient data modification and research techniques can innovate the global finance business.
Join now!
Qraft Technologies