레버리지가 필요해!

안녕하세요, 언베일드 CTO Min 입니다. 지금은 동료 소프트웨어 엔지니어들이 생겼지만 창업 초기엔 대표와 저, 이렇게 두명이 회사 구성원의 전부였습니다. 제품을 만들기 위해 혼자 작업해야 했는데 그때 생각하고 경험했던 이야기를 공유하도록 하겠습니다. NFT 스크리너/애그리게이터인 Oraqle.xyz 를 만들며 다양한 작업이 필요했습니다. 이 과정에서 어떤 도구들을 활용했는지 또한 저희 제품은 크게 어떤 구조를 가졌는지 확인하실 수 있습니다.

레버리지?

Archimedes lever, Engraving from Mechanics Magazine, published in London in 1824
Archimedes lever, Engraving from Mechanics Magazine, published in London in 1824

혼자 제품을 만들기 시작했을 때 마침 Effective Engineer 라는 책을 읽고 있었는데 그 책에서 강조하는 것이 레버리지 Leverage의 개념이었습니다. 시간을 사용하고 노력을 들일 때 메타 인지를 활용하여 투입 자원 대비 효용이 가장 큰 작업부터 처리해야 한다는 것이 주제였습니다. 이때 제가 필요했던 것도 레버리지 였는데 소프트웨어 엔지니어분들이라면 이해하시겠지만 혼자서 할 수 있는 작업은 팀의 작업과 비교하기 어려울만큼 적습니다. 그만큼 투입 자원 대비 산출물의 양과 질을 키워야하는데 이런 의미에서 레버리지가 필요했습니다. 사실 레버리지라고 굳이 이름 붙이지 않아도 소프트웨어 엔지니어에겐 일상적인 작업이 이 레버리지를 활용하는 것입니다. 모든 기능을 직접 만드는 대신, 곧 바퀴를 다시 만드는 대신 적합한 라이브러리를 활용하여 필요한 기능을 구현하는 일 역시 레버리지를 활용하는 일입니다. 저 역시 제품 개발에 오픈 소스를 십분 활용하여 시스템을 만들었고 그동안의 업무 경험에서 익힌 기술들이 큰 도움이 되었습니다.

어떤 지렛대를 사용해볼까

대기업에서 나와 두번의 초기 스타트업을 거치면서 다양한 업무를 경험했습니다. 인프라를 준비하는 작업, 코드 작성 및 배포에 관한 작업들 그리고 분산 시스템에서의 어플리케이션 개발과 트러블슈팅 작업 등이었습니다. 초기 스타트업에서 한 사람의 엔지니어는 일당백을 해야하는데 저희 언베일드의 경우 Platform/DevOps 엔지니어, 백엔드-프론트엔드 엔지니어, 데이터 엔지니어 등의 업무가 필요했습니다.

가장 먼저 필요한 건, 서비스가 운영될 자원을 준비하는 일입니다. 대부분의 스타트업처럼 저희 역시 상용 클라우드 서비스를 사용했습니다. 예전 회사에서 Amazon의 AWS를 주로 사용했고 투자 유치 후 받은 혜택으로 AWS 크레딧도 있었기 때문에 큰 고민없이 AWS를 선택했습니다. 클라우드 서비스를 사용하며 겪었던 어려움은 인프라의 상태 추적과 재현 가능성이었는데 예전 회사에선 CloudFormation 라는 AWS 자체 서비스를 사용하고 있었습니다. 하지만 너무 방대한 JSON 파일들을 수작업으로 관리하는 일은 또 하나의 부담이었기 때문에 가급적 클라우드 자체 서비스에 기대지 않고 인프라를 준비하고 싶었습니다. 마침 얼마전까지 Kubernetes를 기반으로 MLOps 제품을 만들던 경험이 있어 Kubernetes를 사용하기로 정했습니다. 대부분의 클라우드 서비스에선 Managed Kubernetes Cluster 서비스를 제공하기 때문에 특별한 종속성 없이 제품을 만들어 나갈 수 있었습니다.

AWS EKS에서 Kubernetes Cluster를 하나 만들었으면 이제 제품을 위한 인프라를 배포해야 합니다. ArgoCD 같이 Kubernetes를 지원하는 다양한 GitOps 도구들이 있습니다. 하지만 빠른 개발을 위해 이 부분은 Bash Script + K8s YAML (Kustomize) + Helm Chart의 조합으로 구현했습니다. 설치와 관리가 필요없는 쉘 스크립트를 사용한다 하더라도 최소한 인프라를 배포할 때 Kubernetes의 Declarative 속성을 이용하고 싶었습니다. 이런 속성이 없다면 인프라 배포가 중간에 중단되었을 경우, 어떤 단계에서 작업이 멈추었는지 인프라는 어디까지 준비되었는지 등을 수작업으로 확인한 다음 작업을 이어나가야 합니다. make infra-setup 라는 명령을 실행하면 현재 설정된 값들 (K8s Context, Namespace, Kustomize target 등)을 보여준 다음, 필요한 요소들을 설치합니다. 이때 설치는 최종적으로 Kubernetes Resource YAML의 형식을 가지므로 스크립트를 여러번 재실행해도 동일한 결과를 얻을 수 있습니다. 이렇게 멱등적 Imdempotent 수행을 가능하도록 하여 인프라 배포에서 마주할 수 있는 어려움을 줄일 수 있습니다.

데이터베이스, 메모리 캐시 등 필요한 요소를 배포한 후엔 실제 서비스 코드를 작성하고 배포해야 합니다. 여기선 Skaffold라는 도구를 활용했습니다. Skaffold 명령행 도구를 실행하면 코드 변경을 감지하여 컨테이너 이미지를 만들고 Kubernetes로 배포합니다. Helm, Kustomize 등의 형식을 지원하기 때문에 다양한 상황에 맞추어 배포할 수 있습니다. 프론트엔드의 배포는 AWS S3 static site hosting + CloudFront를 활용했습니다.

마지막으로 시스템 및 서비스의 상태를 모니터링하는 작업이 필요합니다. 먼저 메트릭 수집을 위해 Prometheus를 활용했습니다. 저흰 워크플로 관리를 위해 Airflow를 사용하는데 이 경우 Metric Server를 따로 띄우지 않기 때문에 Pull 방식의 Prometheus와 잘 어울리지 않습니다. 이를 해결하기 위해 Statds Exporter를 사용했습니다. DAG 실행 시 Statsd 클라이언트 라이브러리로 메트릭을 보내면 Statds Exporter는 이를 Metric Server의 형태로 노출시킵니다. Prometheus는 다른 타겟과 다를바 없이 같은 방식으로 Statds Exporter의 메트릭을 가져갑니다. 수집한 메트릭을 보여주기 위한 대시보드로는 Grafana를 사용했습니다. 마지막으로 로그를 저장하는 방법이 필요했는데 Grafana Labs에서 만든 Loki를 사용했습니다. ELK 스택처럼 무겁지는 않지만 저희가 원하는 기본 기능을 수행할 수 있습니다. Promtail이란 도구가 K8s 클러스터를 구성하는 노드들에서 실행되며 모든 Pod의 로그를 수집하여 설정한 스토리지로 저장합니다. 스토리지를 따로 준비하고 관리하는 것 역시 수고롭기 때문에 저흰 AWS S3에 저장하도록 하였습니다. 이렇게 저장된 로그는 Grafana로 들어가 태그와 시간 구간을 지정하여 조회할 수 있습니다.

NFT 스크리너를 위한 시스템

여기선 간단히 저희 시스템에 대해 설명드리겠습니다. NFT 스크리너 서비스를 위해 각 NFT 프로젝트의 정량적 정보를 구해야 합니다. 정량적 정보의 예시를 들어보면 바닥가, 최신 거래가, 거래량, 일일 거래 수, 소유지갑 분포, 평균 보유기간, 매물 등록 비율 등이 있습니다. 그럼 이 정보를 얻기 위한 데이터 원천과 방법에 대해 얘기해보겠습니다.

먼저 데이터의 원천은 크게 두가지인데 하나는 블록체인이고 다른 하나는 마켓플레이스 입니다.

저희가 다루는 Ethereum 체인 상의 NFT는 ERC-721 규약을 따라 구현된 스마트 컨트랙트들입니다. 따라서 NFT의 발행, 소유권 이전 등의 이벤트는 Smart Contract Call을 통해 이루어지며 이 결과 또한 블록체인 상에 기록됩니다. 그리고 이런 NFT들의 거래를 지원하는 마켓플레이스 역시 최종적으로는 그들의 스마트 컨트랙트를 통해 NFT의 거래를 일으키므로 이 역시 블록체인 상에 기록됩니다. 따라서 NFT의 거래, 소유에 대한 데이터는 블록체인에서 찾아볼 수 있습니다.

그럼 블록체인에서 찾을 수 없는 정보는 무엇일까요? 블록체인 곧 On-chain이 아닌 Off-chain에 저장되는 데이터로 NFT의 매물 정보가 있습니다. OpenSea, BLUR 등의 마켓플레이스들은 온전한 dApp이라기보단 하이브리드 앱이라 볼 수 있는데 서비스를 위한 백엔드와 개별적인 데이터베이스가 존재하여 고객과 매물 정보를 저장하고 관리합니다. 사용자가 자신이 소유한 NFT를 판매하려고 매물을 올리는 행위는, NFT 거래용 스마트컨트랙트에 보낼 수 있는 Call data를 만들고 서명하는 행위입니다. 이 정보를 백엔드에 저장하고 있다가 웹페이지를 통해 접속한 다른 사용자가 NFT 구매를 원하는 경우, 이 매물 정보를 전달하여 거래용 스마트 컨트랙트 함수를 호출하도록 하는 식입니다. 이런 이유 때문에 매물에 대한 정보는 마켓플레이스에서 얻을 수 밖에 없습니다.

다음으로 데이터 수집 방법 입니다. 이 역시 크게 두가지인데 하나는 블록체인 데이터, 다른 하나는 외부 API 입니다. 앞서 설명드린 것처럼 매물 정보는 마켓플레이스에서 얻어야 합니다. 마켓플레이스 API를 직접 사용하거나 Reservoir 같은 서비스의 API를 이용하여 매물 정보를 얻을 수 있습니다. 저희 서비스의 경우, 실제 NFT 구매를 지원하기 때문에 매물 정보에는 NFT 구매를 위한 정보도 포함되어야 합니다. OpenSea의 경우, 스마트 컨트랙트 함수 호출 정보를 제공하는 API Endpoint가 따로 존재하여 매물을 구입하는 경우 해당 엔드포인트를 이용하여 스마트 컨트랙트 데이터를 준비합니다.

매물 이외의 정보는 블록체인 데이터를 통해 수집할 수 있습니다. 여기에도 도전적인 부분이 존재하는데 블록체인 데이터가 워낙 방대하기 때문에 이를 잘 저장하고 해석하는 작업이 필요하기 때문입니다. Alchemy, NFTGo 등의 회사에서는 NFT 혹은 블록체인 데이터를 조회할 수 있는 API를 제공하는데 블록체인 데이터를 수집하고 가공하기 위한 인프라가 없는 경우에 활용할 수 있습니다. 그 밖에 블록체인 데이터 분석 분야에선 Dune Analytics 라는 회사가 두각을 나타내고 있습니다. 이 회사는 사용자들이 직접 블록체인 데이터를 조회할 수 있도록 SQL문의 작성과 실행을 지원하고 이를 기반으로 대시보드를 만들어 공유할 수 있게 해줍니다. 저희도 외부 API를 활용하고 있는데 현재 Dune을 벤치마킹하여 독자적인 블록체인 데이터 가공 플랫폼을 구축하고 있습니다.

그럼 마지막으로 시스템 구성도를 간단히 공유하도록 하겠습니다.

  1. 실시간 블록체인 데이터 추출 및 처리 - 저희가 제공하는 데이터 중 어떤 데이터들은 지연시간 없이 실시간으로 제공되어야 합니다. 그 중 대표적인 것으로 바닥가, 최신 거래가가 있습니다. 블록체인을 모니터링하는 서버가 있어 블록이 생성될 때마다 NFT 거래 내역을 확인하고 최신 거래가를 갱신합니다. 또한 마켓플레이스의 이벤트를 모니터링하여 매물 등록/취소, 판매 이벤트가 발생함에 따라 바뀔 수 있는 바닥가를 업데이트 합니다. NFT 거래 정보는 내부 시계열 데이터베이스에 저장하여 시간 기반의 2차 정보를 구할 때 활용합니다.

  2. 워크플로 기반의 데이터 수집 배치 작업 - 저희 스크리너에서는 다양한 범주의 정량적 데이터를 제공합니다. 각각의 데이터들은 서로 다른 주기로 수집하거나 계산될 수 있고 이런 작업들의 성공 여부를 추적해야 합니다. 저흰 Airflow 도구를 이용해 데이터 수집 및 가공 작업을 수행하고 있습니다. Twitter/Discord 같은 소셜 미디어의 정보를 API로 수집하거나 Ethereum 노드에 접속하여 스마트 컨트랙트 함수를 실행하는 등의 작업을 수행합니다.

  3. 프론트엔드를 지원하는 백엔드 서버 - 스크리너의 동작은 웹페이지에서 백엔드 서버로 API 요청을 보내서 수행합니다. 스크리너 동작 자체는 단순히 조건을 부과하여 데이터베이스를 조회하는 일입니다. 이렇게 데이터를 업데이트하는 부분과 조회하는 부분을 나눔으로써 데이터 업데이트 부분의 장애가 실제 사용자 경험을 해치지 않도록 만들었습니다.

자, 이렇게 NFT 스크리너를 만드는 여정의 첫 순간을 그려보았습니다. 그 이후 여러 문제를 만나고 개선하며 이곳에 다 적지 못한 이야기들이 많이 쌓였습니다. 그건 차차 다음 글들을 통해 전해보도록 하겠습니다. 거인의 어깨에 올라서라는 너무 자주 인용된 문구가 있지요. 이번 글에서 말씀드린 것처럼 저 역시 다양한 오픈소스의 힘을 빌려 서비스를 만들었습니다. 오픈소스 그리고 Web3의 마음가짐이라면 거인보다는 다같이 손잡고 이끌어주며 나아가는 모습이 더 어울릴 것 같습니다. 저희 언베일드도 누군가의 레버리지를 위한 도구를 만들어 손을 빌려줄 수 있는 회사가 되길 바라봅니다 :)

Subscribe to Unveiled Engineering Blog
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.
More from Unveiled Engineering Blog

Skeleton

Skeleton

Skeleton