2P by GN⁺ | ★ favorite | 댓글 1개
  • 핀테크가 계좌 개설·결제·온보딩을 직접 은행 API처럼 붙일 수 있게 하는 banking-as-a-service 플랫폼이며, 2023년 3월 영국 은행 라이선스를 받아 규제 은행이 됨
  • 시스템은 Clojure on Kubernetes on AWS 위에서 동작하고, 대부분의 입력을 이벤트로 바꾸는 이벤트 소싱 구조와 FoundationDB 저장소를 결합함
  • FoundationDB는 strict-serializable key-value store로 트랜잭션과 동시 쓰기를 지원하며, Griffin은 Datascript를 포팅한 Datomic 유사 계층으로 원자적 읽기·쓰기를 구성함
  • 비즈니스 로직은 Clojure map을 받아 Clojure map을 내보내는 작은 log processor 중심으로 분리하고, 외부 시스템 접근은 프로토콜과 전용 proc로 제한함
  • 클로저의 불변성과 감사 로그 친화성이 금융 서비스 요구에 맞고, 원격 채용과 결합하면 작은 후보군에서도 높은 품질의 엔지니어를 찾기 쉽다고 봄

API로 제공하는 규제 은행 플랫폼

  • Griffin은 핀테크 기업이 은행 기능을 빠르고 안전하게 통합하도록 돕는 banking-as-a-service 플랫폼임
  • 2023년 3월 Financial Conduct Authority로부터 UK banking license를 받아 완전히 규제되는 영국 은행이 됨
  • Griffin은 자신을 “the bank you can build on”이라고 부르며, 은행을 위한 AWS 같은 기반을 목표로 함
    • 고객 온보딩 API
    • 은행 계좌 생성 API
    • 결제 API
  • 핀테크가 이런 기능을 제공하려면 법적으로 은행과 협력해야 하며, 현재는 메인프레임을 쓰는 기존 high street bank와 일하는 경우가 많음
  • Griffin은 은행 라이선스와 기술 플랫폼을 함께 제공해, 미래 핀테크가 그 위에 서비스를 구축할 수 있는 기반이 되려 함
  • 라이선스는 받았지만 당시에는 mobilization 단계에 있었고, 감사 완료·추가 자금 조달·코드 작성 완료 후 이 단계가 끝남
    • 목표 시점은 해당 연도 Q3 또는 Q4였음

클로저를 선택한 배경

  • 클로저는 불변성, 표현력, 감사 로그가 필요한 금융 서비스와의 적합성 때문에 플랫폼 언어로 선택됨
  • Allen Rohner는 2007년경 Rich Hickey의 Clojure 발표를 보고, 자신이 만들던 Lisp보다 더 낫다고 판단함
  • 2011년 CircleCI를 창업한 뒤 클로저를 장기간 사용했고, CircleCI에서도 잘 작동했으며 금융 서비스에도 맞는다고 봄
  • JVM에 대해서는 처음 몇 년간 장점을 충분히 인식하지 못했지만, 이후 큰 이점으로 평가가 바뀜
    • 다른 niche startup language는 라이브러리 부족, 컴파일러·런타임 성능 문제를 겪을 수 있음
    • JVM은 이런 위험을 줄이는 기반이 됨
  • 언어 선택은 회사의 성격을 드러내며, Python이나 Java보다 클로저가 더 강력한 선택이라고 판단함
  • niche language를 쓰면 후보 수는 줄어도 고급 인재 비율이 높아질 수 있다고 봄

FoundationDB로 만든 데이터 계층

  • Griffin 아키텍처는 Clojure, Kubernetes, AWS 위에서 동작하며 거의 전부 이벤트 소싱으로 구성됨
  • 데이터베이스는 FoundationDB를 사용함
  • FoundationDB는 트랜잭션을 지원하는 strict-serializable key-value store
    • Silicon Valley 스타트업으로 시작함
    • 2015년 Apple에 인수됨
    • 2018년경 Apple이 다시 오픈소스로 공개함
    • Apple은 iCloud 프로덕션에서 사용함
  • Apple은 FoundationDB가 초당 약 100만 트랜잭션으로 동작하는 벤치마크를 수행함
  • strict serializable은 데이터베이스 정합성에서 가장 높은 수준에 해당함
  • 기본 API는 get a key, set a key에 가까우며 SQL이 아님
  • Griffin은 Datascript를 FoundationDB에 포팅해 Datomic 유사 계층을 구성함
    • strict-serializable 데이터 저장소 위에서 원자적 쿼리가 가능함
    • 트랜잭션 기반 읽기와 쓰기를 지원함
  • FoundationDB는 single writer가 아니라 concurrent writes를 지원함
  • Griffin은 초당 1,000개 이상의 트랜잭션이 필요하며, 이 요구를 만족하고 있음

이벤트 소싱과 log processor

  • Griffin 시스템의 모든 입력은 이벤트가 됨
    • API request
    • 서드파티 webhook
  • 이벤트는 message log에 들어가며, Griffin에서 이벤트는 type 필드와 key/value, spec을 가진 Clojure map
  • 전체 시스템은 이벤트에 대한 반응으로 구성됨
  • 작은 log processor를 proc라고 부름
    • proc는 “message type A를 듣고, 반응으로 B 또는 C를 emit한다”는 식으로 동작함
    • 각 proc는 자체 private state를 가짐
  • 메시지 흐름은 그래프로 구성할 수 있고, 이벤트는 terminal node에 도달할 때까지 이동함
  • 예를 들어 웹 서버는 HTTP 이벤트를 받고 결제 요청을 기록한 뒤, payment created 또는 payment rejected 이벤트를 기다렸다가 클라이언트에 응답함
    • 이 흐름은 Netty asynchronous HTTP handler를 사용함
  • 모든 이벤트는 FoundationDB에 기록됨
    • 각 log processor는 FoundationDB 안의 자체 namespace 같은 private data를 가짐
    • proc는 특정 이벤트 타입이 기록되는 것을 감시하고, 자신의 이벤트를 FoundationDB에 다시 기록함
  • FoundationDB는 DB key 변경 감시 기능을 제공해 reactive system을 효율적으로 만들 수 있음
  • 데이터베이스와 별도 메시징 시스템을 함께 쓰면 race condition 가능성이 생김
    • 예를 들어 메시지 하나는 디스크로, 하나는 네트워크로 가는 상황에서 관찰자가 둘을 다른 순서로 볼 수 있음
    • Griffin은 단일 경로로 단순화하기 위해 FoundationDB에 기록하는 방식을 사용함

모노레포와 비즈니스 로직 격리

  • Griffin은 monorepo를 사용함
  • 현재는 효율을 위해 많은 log process가 같은 JVM에서 실행됨
    • 각각은 독립적이라 별도 JVM process로 실행할 수도 있음
    • 현재는 low hundreds 규모의 proc를 단일 JVM에서 실행함
  • 비즈니스 로직은 최대한 단순하고 깨끗하게 유지함
    • 개별 log processor namespace는 거의 전부 pure Clojure임
    • 서드파티 라이브러리가 거의 없음
    • side effect도 매우 적음
  • log processor는 Clojure map을 입력으로 받아 하나 이상의 Clojure map을 반환하는 함수에 가까움
  • proc state에는 protocol이 있어 반대편 구현을 몰라도 됨
    • 테스트 시 in-memory database로 쓸 수 있음
    • 실제 실행 시 FoundationDB에 쓸 수 있음
  • 외부 세계와의 인터페이스는 가능한 작게 유지함
  • 대부분의 proc는 자신의 내부 상태에 쓰고 메시지를 emit하는 것만 가능함
    • 네트워크 호출 불가
    • AWS 호출 불가
    • 그 외 외부 동작 없음
  • 외부 시스템과 통신해야 할 때는 전용 dispatch handler가 있는 특수 proc를 둠
    • AWS와 통신하는 proc
    • clearing bank와 통신하는 proc
    • 다른 API와 통신하는 proc

사용하는 클로저 생태계

  • 비즈니스 로직 내부에서는 라이브러리를 거의 쓰지 않음
  • API web server나 service gateway처럼 외부 세계와 맞닿는 영역에서는 다음을 사용함
    • ring
    • netty
    • reitit
  • Clojure spec을 광범위하게 사용함
  • AWS 연동에는 Cognitect aws-api 라이브러리를 사용함
  • 애플리케이션 구성과 리소스 관리는 closeable 블로그 글에 기반한 방식을 사용함
    • Component나 Integrant 없이 with-open으로 충분하다는 접근임
    • lexical scope를 얻고, binding 선언 순서가 구성 순서를 강제함
    • Closeable을 구현하지 않는 상태 객체나 stateless 객체를 with-open 블록에서 선언하기 위한 작은 helper를 사용함

채용과 팀 구성

  • Griffin은 클로저 채용이 후보 수는 적지만 좋은 후보 비율이 높다고 봄
    • Java 채용은 CV가 1,000개 와도 좋은 후보가 10명일 수 있음
    • Clojure 채용은 CV가 13개 와도 좋은 후보가 10명일 수 있다고 표현함
  • 작은 채용 풀에서는 원격 근무가 중요함
    • 지역 제약을 줄이면 전 세계, 3개 시간대 내, 유럽 등 더 큰 풀을 만들 수 있음
  • 짧은 기간에 엔지니어 100명을 뽑아야 하는 상황은 anti-pattern으로 봄
  • 회사 전체 인원은 약 70명임
  • Engineering은 약 22~24명임
    • 약 3분의 2는 UK
    • 약 3분의 1은 EU
    • 독일 4명, 스웨덴 4명, 아일랜드 1명 수준
    • 본사는 런던이지만 대부분의 개발자는 런던 밖 UK에 있음

은행 수준의 운영 복원성 테스트

  • Griffin은 은행으로서 operationally resilient해야 하며, 이는 다운타임이 없어야 한다는 요구에 가깝다고 봄
  • 돈을 다루기 때문에 문제가 생겨도 고객 돈을 잃지 않는다는 점을 실제로 증명해야 함
  • 관심 있는 테스트 방향은 FoundationDB 팀의 방식과 유사함
    • FoundationDB 팀은 데이터베이스 시뮬레이터를 구축함
    • 약 20개의 process type, 즉 cluster 내부 역할을 single-threaded C++ 앱으로 작성함
    • C++ 위에 actor-model concurrency compiler를 구축함
    • 모든 system call과 network call을 protocol을 통해 수행해 오류를 주입할 수 있게 함
    • multi-threading도 message sending 기반 actor model을 통해 처리함
  • 이 환경에서는 결정적으로 오류를 주입할 수 있음
    • 메시지 A와 B를 보냈지만 반대편에 B, A 순서로 도착하는 경우
    • 메시지 처리 중 디스크 쓰기 오류가 나는 경우
  • 이는 test.check의 generative testing과 비슷하게, 시스템의 모든 비결정성을 제어 가능한 단일 random number에서 seed하는 방식으로 볼 수 있음
  • 제어하고 싶은 대상은 disk errors, network errors, message reordering임
  • 현재 문제는 Java threading libraries, NIO, disk write의 동작을 제어할 방법이 없다는 점임
  • Jepsen과 같은 정신을 공유하지만 차이가 있음
    • Jepsen은 여러 VM을 두고 프로세스를 죽이는 식의 brute force에 가깝다고 봄
    • 데이터베이스 상태를 내부에서 검사하기 어려워 커버리지를 알기 힘듦
    • 완전히 제어 가능한 환경에서는 system call이나 메시지 interleaving을 열거하고, in-memory라 매우 빠르게 확인할 수 있음
  • FoundationDB 팀은 이런 테스트 환경을 초기에 만들었고, 이는 FoundationDB에 대한 신뢰를 주는 요소로 작용함
  • Griffin은 채용 중이며 Griffin careers page에서 정보를 확인할 수 있음

댓글과 토론

Hacker News 의견들
  • Griffin의 현 VP of Engineering인 James Trunk가 내가 본 것 중 가장 명확하고 재미있는 Clojure 기술 입문 발표를 했음. 추천함
    https://youtu.be/C-kF25fWTO8?si=PnjMNLdBLJ8zqSu-

  • 지금 문제는 기반이 되는 Java 스레딩 라이브러리, NIO, 디스크 쓰기 동작을 제어할 방법이 없다는 점인데, 그런 시스템의 성격상 앞으로도 불가능할 것 같음
    비결정적 요청 순서나 작업 스케줄링을 쓰는 시스템에서는 결정적 실행을 얻을 수 없음. 여러 OS 스레드를 항상 쓰거나 테스트에서 별도 프로세스를 여러 개 띄우면 그런 상황이 됨
    억지로 결정적으로 만들 수는 있겠지만, 애플리케이션 상태 기계의 모든 전이에 테스트가 제어할 수 있는 동기화 지점을 심어야 해서 매우 어려움
    실무적으로는 시스템의 핵심을 완전히 동기식으로 설계하고, 실행 시점에 더 높은 계층에서 동시성을 추가하는 방식밖에 없어 보임

    • 어렵긴 하지만 가능함. 가장 중요한 건 애플리케이션의 표면적을 줄이는 것임. 우리 비즈니스 로직은 거의 전부 순수 함수이고, procs는 Clojure 프로토콜(Java 인터페이스) 너머에서 일어나는 일을 제외하면 부작용이 없음
      그래서 테스트 중에는 모든 부작용을 스텁으로 대체할 수 있음. 우리 “사용자” 코드는 스레딩 라이브러리에 접근하지 못하고, 스레딩은 “커널” 코드에서 일어남
      실제로 이미 이런 방식이 구현된 좋은 예시는 https://www.youtube.com/watch?v=4fFDFbi3toc에서 볼 수 있음
    • 절대 안 된다고는 말하지 않겠음. Clojure/ClojureScript용 구조적 동시성 DSL이자 프로세스 감독을 구현하는 missionary를 수정하면 가능할 수도 있다고 봄
      이미 missionary 자체 테스트를 위해 missionary 흐름을 계측하고 상태 전이를 검증하고 있음
  • 두 창업자가 함께 Learning ClojureScript라는 책을 썼다는 게 꽤 멋짐
    https://www.packtpub.com/product/learning-clojurescript/9781...

    • 책의 세 번째 저자가 Allen Rohner인 걸 봄. Compass Labs에서 함께 일했는데, 엄청나게 재능 있는 개발자였음. 그는 CircleCI도 창업했음
  • “우리는 은행 면허를 가진 기술 회사라고 농담하곤 합니다”라는 문장은, 일이 잘못되면 나중에 굉장히 안 좋게 보일 수 있는 인용구임

    • 이런 태도의 은행은 쓰지 않을 것 같음. 기술 회사라는 딱지에는 코드를 쓴다는 이유만으로 모든 걸 잘한다고 착각하는 부당한 오만이 따라붙는 경우가 많음
      내 고용주는 스스로를 소프트웨어로 연구 성과를 상업화하는 교육 연구 회사라고 불렀고, 내게는 훨씬 더 납득됐으며 문화도 더 좋게 만들었음
    • 핀테크에서 배운 것 중 하나는, 은행들이 돌리는 COBOL 코드가 오래됐고 유지보수하기 어렵긴 해도 재구축하면 다시 배워야 할 귀중한 지식을 꽤 많이 담고 있다는 것임
      은행업에서 그런 지식을 다시 배우는 비용은 매우 비쌀 수 있음
  • 진지한 질문이고 거친 표현은 미안하지만, 내가 쓰는 서비스가 어떤 언어로 작성됐는지 왜 신경 써야 함? 왜 Clojure로 작성됐다는 게 중요함? 직업적으로 Clojure 개발자라서 이런 게 Clojure로 쓰인 걸 보는 건 멋지지만, 왜 내가 그걸 신경 써야 하는지 모르겠음
    이게 내가 커뮤니티에서 정말 싫어하는 부분 중 하나임. Clojure가 강력한 언어이고 나도 즐겁게 쓰지만, 커뮤니티에는 어떤 프로젝트에서 이 언어를 쓴다는 걸 남에게 말하고 정당화해야 한다는 가면 증후군 같은 게 있는 느낌이라 이상함

    • 이건 Clojure 회사가 다른 Clojure 회사를 인터뷰하면서 기술 스택에 초점을 맞춘 블로그 글임. 어떤 언어 생태계에서도 이런 글은 드물지 않고, 당연히 그 기술에 흥미를 느끼는 사람들이 쓰고 읽는 글임
      요점을 잘 모르겠음. 이게 문명사회에서 부적절한 행동이라도 된다는 건가?
      꽤 무지하게 들림. “관심 없다”면 굳이 관여하지 않아도 되고, 작성자가 쓰고 싶은 걸 쓰게 두면 됨
    • 보통 이런 이야기는 아직 충분히 받아들여지지 않아서 사용 허가를 걱정해야 하는 언어에서 가장 중요해짐
      90년대에 PHP와 Python 개발자들이 “왜 Microsoft ASP를 안 쓰냐” 같은 비즈니스 질문에 답하려고 이런 예시를 공유하던 기억이 남
    • 서버 쪽 트랜잭션 안에서 실행할 코드를 보낼 수 있는 구조라면, 그 API를 쓰려면 개발자도 Clojure로 개발해야 할 수도 있음
      아니면 자기 회사에 올 개발자를 끌어들이려는 걸 수도 있음
  • 이런 API 은행들은 왜 항상 영국에 있음? 몇 년째 curl로 은행 업무를 보고 싶었는데 미국에서는 아무도 제공하지 않음

    • 미국 은행업은 놀라울 정도로 뒤처져 있고, 기술이나 혁신 관점에서 수십 년 동안 세계를 이끌지 못했음
      반면 영국은 새 은행과 새 기술을 적극 장려해 왔음. 개인 계좌 간 즉시 무료 송금은 거의 20년 전부터 있었고, 비접촉 결제는 최소 10년, 모바일 뱅킹은 수십 년, 정부가 의무화한 은행 API는 거의 5년 됐음
      요컨대 영국은 은행 기준으로는 빠르게 혁신해 온 매우 활발한 은행 부문이 있고, 더 빠른 혁신을 위한 환경과 생태계가 잘 발달해 있음
      미국에서는 은행들이 수십 년 전 기술 혁신을 포기하고, 수수료와 고객에 대한 징벌적 대우에서 혁신하는 쪽을 선호한 것처럼 보임. 그래서 새로운 혁신 환경이 없고, 기존 은행들은 경쟁하기보다 경쟁자를 눌러버리는 편이 훨씬 쉬움
      영국도 최근까지는 독립적인 은행 수가 놀라울 정도로 적었는데 왜 같은 일이 벌어지지 않았는지는, 고객 권리를 많이 보장하고 이를 지키지 않는 은행을 적극 처벌하는 법과 규제의 성격 때문일 가능성이 큼
    • 미국에서 새 은행 인가를 받기는 어렵지만, 영국에서는 챌린저 은행이 되는 길이 비교적 명확함. Jarvis도 Griffin을 시작하려고 SF에서 런던으로 다시 옮겼음
      미국에서 API를 가진 은행들은 대형 핀테크 파트너십에 집중하는 경향이 있어서, 단순한 API도 일반 은행 계좌에 비해 비쌀 것임. 예를 들어 미국의 Grasshopper Bank는 일반 상업 은행 계좌 위에 API를 제공하는 몇 안 되는 은행 중 하나임
      나는 API를 제공하는 여러 미국 은행을 지원하는 Treasury Prime에서 일함
    • 2008년 금융위기와 그 뒤 이어진 은행 스캔들 이후, 납세자 돈으로 여러 유명 은행을 구제해야 했고 당시 영국 정부는 소규모 은행을 촉진하기 위한 일련의 조치를 도입했음
      개인 계좌 쪽에서는 Monzo와 Starling이 이른바 챌린저 은행 중 가장 잘 알려져 있음[1]
      [1]: https://en.wikipedia.org/wiki/Challenger_bank
    • 영국은 정부가 은행에 API 요구사항을 의무화함. 미국은 “자유 시장”에 맡겨져 있는데, 실제로는 Yodlee나 Plaid 같은 신뢰하기 어려운 제3자를 믿어야 한다는 뜻임
    • 이제 https://column.com이 있음. 작년에 여기서도 다뤘음
      Column – 개발자를 위한 인가 은행
      https://news.ycombinator.com/item?id=31109170
  • “오픈소스화해야 하는 추가 독점 기술이 하나 더 있다. Datascript를 FoundationDB로 포팅했다”라니, 제발 공개해 줬으면 함
    Datomic 대안으로 어떤 식으로 작동할지 궁금함

    • 글 전체가 “재미 삼아 프로젝트를 과잉 설계하는 법” 가이드처럼 읽혔음
  • “법적으로 핀테크는 이런 일을 하려면 은행과 협력해야 하고, 지금은 그게 메인프레임을 쓰는 전통 대형 은행을 뜻한다. Griffin은 미래의 모든 핀테크가 기반으로 삼을 은행이자 기술 플랫폼이다”라는 문장은 2016년에 쓴 건가 싶음
    시장은 이미 움직였음. Griffin은 좋아 보이지만 많은 곳보다 몇 년 뒤처져 있고, ClearBank 같은 확립된 업체에서 이미 은행 API를 잘 제공하고 있음
    더 많은 업체가 들어올 여지는 있으니 Griffin의 시장 진입은 반갑지만, 피치가 이렇게 약하진 않았으면 함

    • 시장에 선택지가 아직 엄청 많지는 않음. ClearBank는 실제로 괜찮은 상품을 가진 세 은행 중 하나임
      그리고 좋은 API만으로는 부족함. 고객층과 맞는 운영 모델 전체가 필요하고, 이걸 구축하는 쪽이 훨씬 더 어려움
    • “미래의 모든 핀테크가 기반으로 삼을”이라는 표현은 단일 장애점처럼 들리고, 경쟁이 환상에 불과해지는 후기 자본주의의 문제를 그대로 보여주는 것 같음
  • 아직은 아님. “감사를 완료하고, 자금을 더 조달하고, 코드 작성을 마치면 보조 바퀴를 뗄 것이다. 올해 3분기나 4분기쯤일 것이다”라고 되어 있음

  • 글이 “스타트업에서는 사용할 수 있는 가장 강력한 언어를 써야 하며, 그게 Clojure다”로 시작하면 정말 싫음
    그건 그냥 당신의 견해일 뿐임. 스타트업에서는 팀이 MVP를 가장 빨리 만들고 출시해서 첫 고객이나 투자를 얻을 수 있는 언어를 써야 함. 일반적인 스타트업이라면 로우코드나 노코드 플랫폼일 수도 있음, 핀테크에서는 아닐 가능성이 높지만
    굳이 말하자면 LLM과 머신러닝 때문에 Python이 가장 강력한 언어라고도 할 수 있고, 나는 보통 PHP 개발자임. Python은 supposedly Python을 36000배 더 빠르게 만든다는 Mojo 덕분에 더 강력해질 수도 있음
    하지만 어떤 언어 X가 스타트업에서 쓸 유일하고 가장 강력한 언어라고는 절대 말하지 않겠음. 그건 완전한 거짓이자 견해일 뿐임

    • 당연히 견해임. 누가 뭔가를 말할 때마다 그건 그 사람의 견해임
      예를 들어 내 견해로는 그 견해에 동의함 :-) 내 1인 창업 사업은 Clojure와 ClojureScript 없이는 불가능했을 것이고, 이건 이 언어의 “힘”을 보여줌
      한 명의 개발자가 복잡한 앱을 수년간 작성하고 유지보수할 수 있게 해주기 때문에 나는 이 언어를 “강력하다”고 봄. 내게 힘을 줌
    • 그 문구는 JUXT가 Nubank를 제외하면 Clojure 전문 회사 중 가장 유명하고, Clojure 주제와 조금이라도 관련된 거의 모든 콘퍼런스 하단에 로고를 올리는 회사라는 점을 생각하면 훨씬 이해가 됨
      Clojure는 Python이나 PHP처럼 더 대중적인 언어보다는 다른 Lisp들과 더 많이 겹치는, 꽤 내부지향적인 커뮤니티가 있음. 그래서 Clojure가 가장 강력한 언어라는 클리셰는, 어느 정도 사실이 있긴 하지만 안 쓰는 사람에게는 놀랍게 들릴 수 있음
      우리 Clojure 개발자들은 이미 익숙하고, 이제는 우월함을 전제로 말하는 게 거의 인사말 수준이 됐음
    • Python은 특히 2023년 기준으로 정말 강력함. 하지만 이상하게도 나는 LLM과 확산 모델을 Clojure로 조율함
      LLM 출력을 다루는 데도 Clojure를 더 선호함. 물론 Python이 딱 맞는 곳에서는 여전히 Python을 씀