핀테크 엔지니어링 핸드북
핀테크 엔지니어링 핸드북 (Fintech Engineering Handbook)
Fintech Engineering Handbook — Voytek Pitula가 6년간의 금융 소프트웨어 엔지니어링 경험을 바탕으로 집필한 ~25페이지 분량의 무료 핸드북. 돈(money)을 시스템의 핵심 상태(core state)로 다루는 소프트웨어를 설계할 때 필요한 패턴과 원칙을 정리했다. 세 가지 핵심 원칙(No invented data, No lost data, No trust) 아래 idempotency, double-entry bookkeeping, funds reservation, reconciliation, event sourcing, 웹훅 처리 등 핀테크 엔지니어링의 실질적 주제를 다룬다.
---
원문 요약
세 가지 기본 원칙 (Three Principles)
핸드북의 모든 내용은 세 가지 원칙에 귀결된다:
- No invented data (데이터를 창조하지 말 것) — 돈은 무(無)에서 생겨날 수 없다. 중복, 임의의 잔고 업데이트를 허용하지 않는다. idempotency, deduplication, reconciliation으로 강제한다.
- No lost data (데이터를 잃지 말 것) — 돈에 일어나는 모든 일은 추적되고 영속화되어야 한다. full precision, at-least-once delivery, event sourcing, audit trail, immutability로 보호한다.
- No trust (아무 것도 믿지 말 것) — 외부 제공자, 내부 컴포넌트, 세상 그 어느 것도 신뢰하지 않는다. 웹훅 검증, 데이터 교차 확인, 깨진 가정에 대한 fail-fast로 유지한다.
금액 표현 (Representing Money)
금액 표현 방식은 네 가지가 있으며, 시스템의 책임에 따라 선택하되 서로 배타적이지 않다:
- Floating-point (float/double) — 가장 빠르지만 정밀도 손실이 예측 불가능. 거의 항상 나쁜 선택.
- Arbitrary precision (Java BigDecimal 등) — 정밀도를 명시적으로 제어. FX나 가격 계산 같은 중간 연산에 적합.
- Minor-units precision (정수) — ISO 4217에 따라 최소 단위 정수로 저장 (€12.34 → 1234). 암호화폐는 자산별 정밀도가 다르고 64비트를 넘을 수 있어 arbitrary-width 정수가 필요.
- Rational numbers — 정밀도 손실이 전혀 허용되지 않을 때. 가장 느리다.
JSON 직렬화 시 금액을 숫자가 아닌 문자열("12.34")이나 최소 단위 정수로 보내야 한다. JSON number는 대부분의 파서에서 IEEE-754 double로 파싱되기 때문.
반올림 전략 (Rounding Strategies)
- 반올림은 불가피하며 명시적으로 수행해야 한다.
- 비즈니스 결정이다. 전략에 따라 법적/세무적 영향이 다르다.
- 가능한 한 적게 반올림하고, 마지막 순간에 한 번만 한다.
- 반올림의 축적 효과를 모니터링해야 한다. 특히 spread나 fee처럼 반대 방향으로 상쇄되는 항목이 있다면 더욱.
통화 처리 (Currency Handling)
- 통화끼리 직접 산술 연산하지 않는다. EUR + USD는 항상 명시적 환율 변환을 거쳐야 한다.
- 통화의 식별자는 코드뿐 아니라 네트워크, 컨트랙트 주소까지 포함할 수 있다 (특히 스테이블코인).
- 환율(quote)은 방향성이 있다. EUR→USD와 USD→EUR는 역수가 아니라 별개의 가격이며 bid/ask spread가 존재한다.
- 참조 환율(reference rate)과 거래 환율(transactional rate)은 다르다.
원장 (The Ledger)
복식 부기 (Double-entry bookkeeping): 모든 금융 거래는 두 개의 계정(차변/대변)에 기록된다. Total debits = Total credits로 항상 균형이 맞는다. 잔고(balance)는 절대 저장되지 않고 움직임(movements)에서 도출된다.
Value time vs Booking time vs Settlement time: 거래가 인식되는 시점(booking), 금전적 가치가 효력을 발휘하는 시점(value), 자금이 실제로 이동하는 시점(settlement)은 서로 다르다.
Audit trail (감사 추적):
- Event sourcing: 상태를 저장하지 않고 상태 변경 이벤트를 저장. 전체 히스토리 보존, 시점 조회 가능, 감사에 강함.
- Immutability: 변경 불가능한 로그. PII와 금융 데이터를 분리하면 개인정보 삭제 요청(GDPR 등)을 금융 기록 보존 의무와 충돌 없이 처리 가능.
- Reversals and corrections: 실수는 "되돌리지(undo)" 않고 보정(compensating entry)으로 대응. 원래 항목은 immutable하게 남겨둔다.
자금 관리
자금 예약 (Funds Reservation): 송금 전에 자금을 예약(hold)하여 이중 사용을 방지. Authorization과 capture/capture의 분리. 예약은 만료될 수 있으며, 만료 후 재시도 가능.
오버드래프트 (Overdraft): 잔고가 마이너스가 되는 상황. 의도적(credit product) vs 비의도적. "balance ≥ 0"을 타입 레벨에서 강제(UNSIGNED, CHECK 제약)하지 말고 실행 시점과 사후 모니터링으로 처리해야 한다. 클램핑(clamping)은 돈을 창조하는 행위.
Idempotency (멱등성)
분산 시스템에서 exactly-once delivery는 불가능하므로 모든 호출은 재시도 가능해야 하고, 중복 실행은 한 번의 효과만 내야 한다.
- 명시적 키(explicit idempotency key) 가 비즈니스 파생 멱등성보다 낫다.
- 에러 재생(replay) vs 재처리(reprocess) 결정이 필요.
- 대규모에서는 동시성(idempotency barrier가 atomic해야 함)과 시간 윈도우(24h 제한은 정확성을 희생) 이슈를 고려.
- 양방향(호출 시/수신 시) 모두 멱등성을 유지해야 한다.
완전 재개 가능성 (Full Resumability)
금융 플로우는 단일 단계로 완료되지 않는다. 모든 단계 사이에 장애가 발생한다고 가정:
- 진행 상태를 메모리가 아닌 durable storage에 저장.
- 중단된 플로우를 재개하는 독립적인 드라이버 필요.
- 모든 단계는 재실행 가능해야 함 (idempotent).
- 외부 효과는 rollback 불가능 → roll forward하거나 saga 패턴으로 보상.
외부 세계 (External World)
API 소비:
- 스키마를 신뢰하지 말고 검증하되, 필요 없는 부분은 검증하지 말아라 (불필요한 장애 방지).
- 모든 호출은 실패한다고 가정. 재시도와 타임아웃 필수.
- 모든 요청과 응답을 저장하라.
- 서킷 브레이커는 대개 선택 사항 (과부하 서버에 대한 예의).
- 샌드박스를 신뢰하지 말고 프로덕션에서 테스트하라 (canary release).
웹훅 (Webhook):
- 순서, 유효성, 전달, 단일 전달을 가정하지 말라.
- idempotent하게 처리하고, 빨리 acknowledge한 후 비동기 처리.
- 원시 페이로드를 저장하고, HMAC 서명을 raw bytes에 대해 검증.
- 웹훅을 트리거로만 보고 실제 상태는 API로 확인하라.
- 분실 웹훅에 대비한 독립적인 reconciliation 프로세스 필요.
Reconciliation (조정)
외부 시스템 데이터와 내부 원장을 주기적으로 비교하는 안전망:
- 일방향이 아닌 모든 거래 방향을 비교.
- 예상되는 시차(T+X settlement)를 고려한 alert 임계값 설정.
- 다대일 매칭(하나의 settlement가 여러 거래를 커버) 지원.
원자적 배포 (Atomic Deployment)
데이터베이스 스키마 변경과 애플리케이션 코드 변경은 원자적으로 배포되어야 한다. 그렇지 않으면 구버전 코드가 신규 스키마와 충돌하거나 그 반대 상황이 발생. 마이그레이션은 항상 이전 버전과 호환되어야 함.
부지런한 아키텍처 (Diligent Architecture)
거래(Transaction)를 적극적으로 모델링하라: 락, 경합, 교착 상태, 불변식 위반을 초기 설계 단계에서 고려. 트랜잭션 격리 수준과 locking 전략을 시스템 전체 일관성 요구사항에 맞게 선택.
나가며: 세 가지 흐름(Flow) 예시
핸드북은 세 가지 구체적 흐름으로 개념을 종합한다:
- 암호화폐 출금 (Crypto Withdrawal) — 가격 책정 → 잔고 확인 → 자금 예약 → 블록체인 브로드캐스트(재시도+멱등성) → 확인 대기 → 원장 전기 → 야간 reconciliation. 수수료 추정과 실제 수수료 차이가 오버드래프트를 유발할 수 있음.
- 카드 입금 (Card Deposit) — PSP 승인(authorization) → 웹훅(신뢰하지 않고 API로 확인) → clearing 계정을 통한 전기 → 배치 정산 → reconciliation → 차지백. 모든 단계가 "no trust" 원칙의 적용.
- 앱 내 환전 + 캐시백 (In-app Conversion with Cashback) — 방향성 환율 → 자금 예약 → 통화 간 산술 금지 → 전체 정밀도 유지 후 한 번 반올림 → 복식 부기로 spread/캐시백 각각 수익/비용 계정에 전기 → outbox를 통한 안정적 알림.
---
Hacker News 커뮤니티 반응
Story ID: 48696982 (작성자: signa11) Points: 480 | Comments: 159 (2026-06-27 게시, 2026-06-28 업데이트) 원문: https://w.pitula.me/fintech-engineering-handbook/
1. AI 생성 의혹과 저자 신뢰성 논쟁
주장: 이 핸드북이 AI 생성(slop)일 가능성이 있다. 요즘은 직접 물어봐야 한다. 근거: dc_giant가 "Sorry have to ask these days. Is this carefully written down information from years of experience or AI slop?"라고 질문. traceroute66은 더 강하게 "honestly, I think this handbook was mostly written by an LLM"라고 주장하며, PII 분리 권장 문구를 KYC/AML 규제와 충돌한다고 지적. 반론/보충: thewisenerd가 저자의 Mastodon 게시물을 인용해 "6 years of tears, sweat and swears"에서 나온 결과물이라고 전달. 저자 krever 본인이 직접 등장해 "at least 80% organic artisanal writing, maybe 20% AI for grammar/completeness"라고 해명. 실제로 검토한 사람들은 zipy124("doesn't read like slop"), manwithopinions("accurately represents the real world, has substance"), cirrhosis("same lessons I learned during my 5 years in fintech"), jyounker("looks like solid advice") 등 대부분이 내용 자체는 타당하다는 입장. 대표 작성자: dc_giant, traceroute66, krever(저자), zipy124, cirrhosis
2. 금액 표현 방식: 정수 vs BigDecimal vs 실수(float/double)
이 주제가 전체 댓글에서 가장 큰 비중을 차지하며 깊게 논쟁되었다.
2a. 정수(minor-units)는 절대적으로 옳은가? 주장: 금액은 반드시 정수(Integer)로만 저장해야 한다. 다른 방식은 모두 틀렸다. 근거: xlii는 "If I ever see a monetary value stored in something else than integers I'm going to run away screaming"이라고 강력하게 주장. antonymoose(HFT 경험자)는 "Use integer cents. It's practically an industry standard and it works just fine." DetroitThrow는 "You can have the blockchain team be an expert in converting integer cents... You don't want to require every team to have expertise in float math." skipants도 "there's only One Right Way to store money (as integers) and it should have been explicit about that"라고 지적. 반론: lxgr가 가장 활발하게 반박 — "Don't use it as an interchange/API data format. It'll bite you incredibly hard if you ever stumble upon an edge case." 정수 방식이 "implied decimal digits per currency"가 모든 이해관계자 간에 일관되게 정의되지 않을 때 깨지기 쉽다고 주장. fvdessen(20년 경력)은 "The whole avoid floats thing just isn't true. Most of it used doubles."라고 주장하며, doubles가 15자리 정밀도 내에서는 완벽한 십진 정밀도를 유지할 수 있고 Excel도 doubles를 사용한다고 반박. 대표 작성자: xlii, antonymoose, lxgr, fvdessen, skipants, DetroitThrow
2b. 스트링 직렬화 vs 구조화된 금액 표현 주장: JSON에서 금액은 숫자가 아니라 문자열로 보내야 한다. 근거: lxgr는 JSON number가 IEEE-754 double로 파싱되어 정밀도가 손실되는 문제를 지적하며, 문자열이 이 문제를 완전히 우회한다고 주장. ivanmontillam도 동의. 반론: jameshart는 문자열 "10.00"의 의미가 모호하다고 반박 — "10"과 같은가? "10.000"과 같은가? "10.001"과 같은가? 명시적으로 decimal_places 필드를 포함한 구조화된 표현({amount: 1000, decimal_places: 2, currency: "USD"})을 제안. noitpmeder는 가수(mantissa)와 지수(exponent)를 별도 정수로 보내는 것이 "유일하게 진정한 해결책"이라고 주장. 대표 작성자: lxgr, ivanmontillam, jameshart, noitpmeder
2c. HFT vs 일반 핀테크의 절충 주장: 금액 표현 방식은 도메인에 따라 완전히 달라야 한다. 근거: antonymoose(HFT)는 정수가 가장 빠르고 실용적이라고 주장. zackwu는 "A HFT system programmer thinks about how to colocate their prod machines... while a crypto wallet app developer spend more time designing cool UI"라며 도메인별로 관심사가 완전히 다름을 지적. Maxatar는 "BigDecimal should be used by almost everyone except for HFT since they're really slow"라고 정리. 반론: lxgr는 "Big decimals are widely available and don't require any expertise but avoid many of the footguns of implied decimal integers"라고 주장. 다만 Maxatar가 "Imagine advising someone who explicitly said they work in HFT to use big decimals"라고 반박하는 등 HFT 영역은 예외로 인정됨. 대표 작성자: antonymoose, zackwu, Maxatar, lxgr
3. 규제 준수와 실무 관행: "Just comply" vs 적극적 엔지니어링
주장: 규제 산업에서는 내부 핸드북과 법무팀의 가이드를 따를 뿐, 외부에서 가져온 랜덤 핸드북을 참고하지 않는다. 근거: traceroute66이 가장 강력하게 제기 — "People going to work in a Fintech should not be relying on a random 'Handbook' written by an unknown person in an unknown jurisdiction." "Unless it's your job to architect stuff, in a financial firm you don't go looking around for ideas and practices. You comply with your employer's practices end of story." 반론: lxgr가 논리적으로 반박 — 규제는 "outcomes"에 관심이 있을 뿐 BigDecimal vs Integer 같은 기술적 선택을 지시하지 않는다. "What if you're the employer ('first engineer' etc.), and there are no practices yet?"라는 질문으로 스타트업 맥락에서 이 핸드북의 가치를 정당화. "Not thinking, just complying isn't the panacea for good outcomes"라고 지적하며, 이 태도가 일부 국가에서 은행/결제 시스템이 화석화된 이유라고 주장. 보충: Scubabear68은 "This sounds great until your counterparties, banks, the government, customers and others complain bitterly that your monetary amounts are off"라며 규칙을 무시할 때의 현실적 위험을 경고. bayarearefugee는 Synapse의 재앙을 언급하며 "Kind of wild nobody has gone to jail for that"라고 덧붙임. 대표 작성자: traceroute66, lxgr, Scubabear68, bayarearefugee
4. 핸드북의 깊이와 범위에 대한 평가
주장: 핸드북은 핀테크 입문자에게 유용하지만, 경험자에게는 새로운 내용이 거의 없다. 일부 영역은 너무 얕게 다루거나 결정적으로 중요한 주제를 생략했다. 근거: zipy124는 "nothing new here for me"라고 평가. benashford는 "most of this applies to software engineering generally, not just fintech"라며 retry, idempotency, event ordering 등은 금융이 아닌 시스템에도 일반적으로 적용된다고 지적. jappgar는 "Very little in here specifically applies to fintech except the ledgering and rounding parts, which are pretty light"라고 평가하며, "I would prefer to read a defense of something more radical like 'database per account'"라고 제안. belmarca(핀테크 CTO 출신)는 많은 내용이 다른 곳에서도 찾을 수 있지만 모아둔 것은 실용적이라며, DDIA(Designing Data-Intensive Applications)를 권장. 또한 event sourcing을 피한 자신의 결정과 데이터 계보(data lineage) 주제가 빠진 점을 지적. 반론: dahart는 "Being unable to gloss over some complexity is not good for learning"이라며 입문자를 위한 개괄적 접근의 가치를 옹호. 대표 작성자: zipy124, benashford, jappgar, belmarca, dahart
5. 부동소수점(floats) 사용 가능성에 대한 깊은 논쟁
주장: Float를 금융 계산에 사용하는 것은 원칙적으로 잘못되었다. 근거: worik가 가장 단호함 — "Never use floats for financial calculations. Because hard won experience. Floats are simulations of Real Numbers, and Reals are uncountable. Not what you want for finance, where everything is counted." 반론: oddthink가 금융의 다양한 하위 도메인을 구분할 필요성을 제기 — 몬테카를로 옵션 가격 책정, 리스크 메트릭(duration, convexity, vega) 계산에는 doubles가 완전히 적합하며 "How are you going to force exp(-rt)cashflow to be an integer?"라고 반문. ViscountPenguin도 "I've not once seen an interest rate swap priced in anything other than float/double"이라고 뒷받침. fvdessen(20년 경력)은 doubles의 15자리 정밀도를 적절히 관리하면 완벽하게 쓸 수 있다고 주장. 대표 작성자: worik, oddthink, ViscountPenguin, fvdessen, quibono
6. 기타 — 웹훅 사용성, 리소스 추천, 언어 논쟁
웹훅 실사용 논의: jgalt212가 웹훅을 실제로 본 적이 없다고 하자, intelcoders, weatherlight, f3408fh가 결제 게이트웨이에서 웹훅이 주요 상태 업데이트 수단이라고 반박. Stripe 예시를 들며 웹훅이 "everywhere"라고 설명.
자본시장(Capital markets) 리소스: koliber가 주식/옵션/FX/채권/원자재 트레이딩을 위한 유사 핸드북을 요청. mhh__가 "Pricing Money" by JDA Wiseman과 "Trading and Exchanges"를 추천.
"For whom" vs "For who": penguin_booze가 핸드북에서 "For whom?"을 쓴 점을 칭찬하며 "The often-seen, stupid way is 'who is this book for'"라고 논평.
대표 작성자: jgalt212, intelcoders, koliber, mhh__, penguin_booze
종합 평가
전체적으로 HN 커뮤니티는 핸드북의 내용 자체는 대부분 타당하다는 데 동의하면서도, 표현 방식(특히 금액 표현에서 정수만을 강하게 권장하지 않은 점)과 AI 생성 의혹에 대한 논쟁이 두드러졌다. 저자 krever가 직접 커뮤니티에 참여해 투명하게 해명하고 피드백을 수용한 점은 긍정적으로 평가되었다. lxgr가 가장 활발하고 깊이 있는 댓글을 남겼으며, 금액 표현, 규제 준수, 시스템 설계 전반에 걸쳐 다양한 관점에서 핸드북을 보완하는 논의가 이루어졌다. HFT, 일반 핀테크, 규제 준수, 학계 등 다양한 배경의 실무자들이 각자의 경험에서 나온 통찰을 공유하며 핸드북의 내용을 풍부하게 확장했다.