# 금융 시스템 구축을 위한 엔지니어링 원칙

> Clean Markdown view of GeekNews topic #15794. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=15794](https://news.hada.io/topic?id=15794)
- GeekNews Markdown: [https://news.hada.io/topic/15794.md](https://news.hada.io/topic/15794.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2024-07-12T09:43:18+09:00
- Updated: 2024-07-12T09:43:18+09:00
- Original source: [substack.wasteman.codes](https://substack.wasteman.codes/p/engineering-principles-and-best-practices)
- Points: 34
- Comments: 2

## Summary

금융 시스템 구축 시 혼란을 줄이고 정확성, 감사 가능성, 적시성을 보장하는 방법을 설명합니다. 데이터의 불변성, 세분화된 기록, 멱등성 등의 엔지니어링 원칙을 강조하며, 실무에서 발생할 수 있는 문제와 해결책을 제시합니다. 또한, 금융 금액을 정수로 표현하고 일관된 반올림 방법을 사용하는 등의 사례 소개를 통해 실질적인 조언도 제공합니다.

## Topic Body

- 회계는 지난 수백 년 동안 크게 변하지 않았음  
- 그럼에도 불구하고, 금융 시스템을 위한 소프트웨어를 구축하는 올바른 방법에 대해 많은 혼란이 있음  
- 이 글에서는 대기업에서 금융 시스템을 구축한 경험을 바탕으로 한 교훈을 공유  
- 회계 시스템 구축에 초점을 맞추겠지만, 이 원칙들은 더 일반적인 금융 시스템에도 적용됨  
  
#### 기본 금융 용어 정의  
* **일반 원장 (General Ledger, GL)**: 특정 기간 동안의 모든 금융 거래를 요약한 회사의 주요 회계 기록. 이는 해당 하위 원장의 집계로 생각할 수 있음  
* **보조 원장 (Sub-ledger)**: 특정 GL과 관련된 모든 개별 거래에 대한 세부 정보를 포함. 보조 원장의 레코드에는 일반 원장보다 훨씬 더 세분화된 데이터가 포함되어 있음 (예: 특정 고객, 주문의 특정 항목 등). 보조 원장과 GL 간의 데이터 차이는 비즈니스 유형과 작업 중인 데이터 양에 따라 달라짐. 일부 소규모 기업은 보조 원장 없이 운영할 수 있지만, 규모가 작은 경우 맞춤형 소프트웨어가 필요할 가능성은 별로  
* **재무 기록 (Financial Record)**: 일반 원장과 보조 원장을 통칭  
* **중요성 (Material)**: 재무제표의 정보 왜곡이 합리적인 이해관계자의 의사 결정에 영향을 미치는지 여부를 나타냄. 이 정의는 의도적으로 다소 애매모호한데, 서로 다른 기업은 서로 다른 중요성 기준을 가지고 있기 때문. 예를 들어 연 매출 25만 달러를 버는 기업에게 중요한 것이 연 매출 10억 달러를 버는 기업에게는 중요하지 않을 수 있음. 설계 관점에서 이 개념의 주요 가치는 다양한 범주의 재무 데이터를 분류하는 것임  
  
#### High Level Data Flow   
  
**Business System** --(Financial Events)--> **Sub Ledger(s)** --(Summarized Accounting Entries)--> **General Ledger**  
  
#### 회계 시스템의 세 가지 주요 목표  
1. **정확성 (Accurate)**: 재무 기록은 비즈니스의 알려진 상태를 반영해야 함  
  - 예: $9.99의 제품 10개를 판매한 경우, 해당 재무 기록의 합계는 $99.90이어야 함  
  - 이는 명백해 보이지만 수천, 수백만 건의 거래를 집계할 때 시스템 간 단순 합산이나 반올림 오류로 인해 중대한 부정확성이 발생할 수 있음  
  - > **Wasteman의 노트**  
    > * 사람들은 명명(naming)이 컴퓨터 과학에서 가장 어려운 문제라고 하지만, 덧셈이 그 다음으로 어렵다고 생각함  
    > * 지난 몇 년 동안 대규모 금융 시스템에서 일하면서, 아주 작은 버그가 데이터에 큰 차이를 유발한 경우를 셀 수 없이 많이 봄  
    > * float에 대한 합계는 얘기도 꺼내지 말 것. 항상 정수를 사용해야 하는 이유를 힘들게 배움  
  - 재무 기록은 **완전 (complete)** 해야 함  
    - 더 구체적으로, 보조 원장과 일반 원장은 특정 시점에 발생한 모든 비즈니스 활동을 완전히 표현해야 함  
    - 발생했지만 재무 기록에 없는 이벤트가 있다면 시스템이 완전하지 않은 것  
    - 이는 최종 일관성 (eventual consistency)이 허용되지 않음을 의미하지는 않음  
    - 데이터가 언제 완전해질지 알아야 이해관계자에게 데이터가 확정되었음을 알릴 수 있음  
  - > **Wasteman의 노트**  
    > * 완전성을 보장하는 것도 놀라울 정도로 어려운 문제임   
    > * 시스템이 확장됨에 따라 데이터가 여러 시스템을 거치면서 실수로 변형되거나 누락될 수 있음  
2. **감사 가능성 (Auditable)**: 이해관계자가 오류를 감지하고 비즈니스 성과를 정확하게 측정할 수 있도록 재무 기록을 쉽게 감사할 수 있어야 함   
3. **적시성 (Timely)**: 회계 시스템은 비즈니스의 특정 요구 사항을 충족해야 함  
  - 소규모 기업은 월말에 모든 숫자를 덤프하는 것으로 충분할 수 있지만, 대기업은 일반적으로 실시간에 가까운 시스템을 원함  
     - 이를 통해 한 달 내내 재무 상태를 모니터링하고, 재무 데이터에 기반한 의사 결정을 더 빠르게 내리며, 월/분기 초에 마감하기 위한 촉박함을 줄일 수 있음  
  - 그 필요가 무엇이든, 우리의 회계 시스템은 비즈니스의 요구 사항을 충족해야 하며, 그들에게 **적시**가 의미하는 바 그대로여야 함  
  - > **Wasteman의 노트**  
    > * 사람들은 적시성과 관련하여 배치 대 스트리밍 시스템에 대한 대화에서 길을 잃는 경향이 있음  
    > * 내 견해로는 대부분의 시스템에서 이것이 중요한 구분이 아님  
    > * 초 단위에서 분 단위에 이르는 매우 짧은 지연 시간에 대해 신경 쓴다면 이것이 중요함  
    > * 그러나 소비자가 하루에 몇 번 이상 업데이트를 볼 필요가 없을 때 사람들이 어떤 것을 해야 할지에 대해 논쟁하는 것을 듣는 경우가 놀라울 정도로 많음  
    > * 요청했다고 해서 반드시 필요한 것은 아님  
  
#### 회계 시스템이 지켜야 할 세 가지 주요 엔지니어링 원칙   
1. **데이터의 불변성 (Immutability)과 내구성 (Durability)**  
  - 감사 가능성을 허용하여 디버깅과 정확성에 도움이 됨  
  - 데이터가 불변하면 언제든지 시스템의 상태를 기록할 수 있음   
  - 이는 이전 상태에서 세계를 재계산하는 것을 정말 쉽게 만듦. 어떤 상태도 잃어버리지 않기 때문  
  - 한 번 재무 기록에 명시된 데이터는 삭제할 수 없음  
  - 시스템에 대한 모든 수정 사항은 새로운 금융 거래로 표시되어야 함  
    - 예: 시스템에 버그가 있어 $900이어야 할 서비스가 실수로 $1000에 판매된 것으로 보고된 경우  
    - 이 실수를 바로잡으려면 먼저 실수에 해당하는 회계 항목을 취소하고 정확한 금액으로 회계 항목을 다시 기술해야 함  
2. **데이터는 가장 작은 단위로 표현되어야 함(Data recorded at the smallest grain)**  
  - 위의 원칙과 유사하게, 이것은 또한 명확한 감사 추적을 가능하게 하는 데 매우 중요함  
  - 재무 보고서와 일반 원장이 집계되더라도, 그것들은 더 세분화된 이벤트에서 계산됨  
  - 데이터가 이해되지 않을 때, 문제가 무엇이었는지 디버깅하기 위해 가장 세분화된 데이터가 필요함  
  - 가장 낮은 수준의 세분성으로 데이터를 저장하면 해당 데이터셋에서 파생된 데이터를 수정하는 것도 매우 쉬워짐  
    - 단일 불변 데이터셋이 해당 데이터의 모든 뷰에 대한 진실의 핵심 소스인 경우,   
    - 뷰를 수정하려면 데이터를 수정한 후 해당 뷰를 생성하는 파이프라인을 다시 실행하기만 하면 됨  
  - 이와 유사하게 회계사가 장부를 마감할 준비를 할 때,   
    - 그들은 장부가 정확한지 검증하기 위해 발생한 모든 거래와 계정 잔액을 조정함  
    - 불일치가 발견되면 문제를 일으키고 있는 정확한 거래를 파고들 수 있음  
3. **멱등성 (Idempotency)이어야 함**  
  - 모든 재무 이벤트는 한 번만 처리될 수 있으며, 재무 기록의 중복은 명백한 부정확성을 야기할 것임  
  - 이러한 이유로 재무 기록을 생성하는 모든 코드는 멱등원 (idempotent)이어야 함   
    - 멱등원이란 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미  
    - 즉, 재무 이벤트를 여러 번 처리하더라도 결과는 처음 처리한 것과 동일해야 함  
  
#### 모범 사례  
* **금융 금액을 나타내기 위해 정수를 선호할 것**: 산술 연산이 훨씬 쉬워짐. float는 피할 것  
* **통화 변환 시 정밀도 손실을 최소화할 수 있도록 금융 금액의 세분성을 지원할 것**  
  - 달러만 다루는 경우 센트 단위로 표현하는 것으로 충분할 수 있음  
  - 글로벌 비즈니스의 경우 마이크로 단위나 `DECIMAL(19, 4)`와 같은 소수를 선호  
  - 금융 시스템에서 소수 선택이 인기가 있지만, 광고 금융 시스템에서는 마이크로가 표준  
* **일관된 반올림 방법을 사용할 것**: 반올림 방식에 따라 예상 금액과 중요한 차이가 발생할 수 있음  
  - 모든 값을 5 이상은 다음 유효 숫자로, 4 이하는 내림하는 방법  
  - 항상 반올림하는 방법 등  
  - 중요한 것은 전체적으로 일관성을 유지하는 것 (거래당 1센트씩 차이나는 경우 1천만 건이면 $100k 차이)  
* **가능한 한 통화 변환을 지연시킬 것**: 통화를 미리 변환하면 정밀도 손실이 발생할 수 있음  
  - 현지 통화로 집계가 발생한 후까지 통화 변환을 지연  
* **시간의 정수 표현 사용**: 약간 논란의 여지가 있지만 강력 추천  
  - 타임스탬프를 객체로 파싱하는 다양한 라이브러리들이 각각 다르게 처리함  
  - 이러한 골치 거리를 피하고 정수를 사용하는 것이 좋음  
  - Unix 타임스탬프나 UTC 기반 정수 datetime도 완벽하게 작동  
  - 시스템 간 데이터 변환이 적을수록 좋음  
  - > **Wasteman의 노트**  
    > * 일광 절약 시간제 관련 버그는 언급조차 하지 않았음. 증가하는 정수를 사용하면 이를 완전히 피할 수 있음  
    > * datetime을 고집한다면 적어도 UTC를 사용할 것. 매우 큰 기업들이 UTC가 아닌 타임스탬프를 사용하는 경우가 놀라울 정도로 많음

## Comments



### Comment 27175

- Author: kandk
- Created: 2024-07-12T10:40:36+09:00
- Points: 2

이거 진짜 유용하네요. 아무 생각 없이 형변환(decimal float double),반올림을  현업 논의 없이 그냥 해버리면 큰일 납니다.

### Comment 27161

- Author: neo
- Created: 2024-07-12T09:43:18+09:00
- Points: 2

###### [Hacker News 의견](https://news.ycombinator.com/item?id=40933110) 
- 일관된 반올림 방법론 사용의 중요성 강조
  - 비즈니스 도메인 코드에서 반올림 전략을 국가 코드별로 관리할 필요성 언급
- 시간을 정수로 표현하는 방법 추천
  - Unix 타임스탬프나 정수 기반 UTC 날짜시간 사용 권장
  - 과거 또는 미래의 특정 시간에 대해 유효함
  - 예: 48시간 취소 정책을 가진 회사의 경우 미래 타임스탬프 계산 가능
  - 국가별 세금 연도 종료 시간 등은 시간대 저장 필요

- 회계 시스템에서 관계형 데이터베이스 사용 권장
  - ACID 특성 제공
  - 임의 정밀도 숫자 데이터 타입과 검증된 연산 및 반올림 모드 제공
  - SQL을 통한 계산 및 보고 가능
  - SQL 전문가 고용 시 우아한 보고서 작성 가능
  - 고속 성능 및 재해 예방 및 복구 도구 제공
  - 다국적 기업의 금융 시스템 구축 경험 공유

- 회계 시스템의 주요 목표는 정확성, 감사 가능성, 적시성임
  - 일관성도 중요한 요소로 언급
  - 여러 시간 차원이 존재하며, 각 차원에 따라 일관된 뷰 제공 필요
  - 예: 거래가 완료되었지만 정산되지 않은 경우 프론트 오피스 회계에만 포함

- 회계 시스템의 완전성에 대한 의견
  - 모든 거래가 제때 처리되지 않음을 가정
  - 여러 계층의 원장을 통해 거래를 처리하고 조정 프로세스 필요

- 글로벌 비즈니스의 경우 최소 8자리 소수점 사용 권장
  - 환율 변환을 가능한 한 지연시킬 필요성 강조
  - 환율 변환은 법적 및 회계적 의무의 일부임

- 사용자 인터페이스(UI)의 중요성 언급
  - 회계 소프트웨어의 UI에 대한 실망감 표현
  - 더 나은 UI 솔루션 필요성 강조

- 배치 처리와 스트리밍 처리의 차이점 설명
  - 두 시스템의 설계가 완전히 다름
  - 대량의 기존 데이터를 처리하는 데 어려움 존재

- TypeScript를 사용한 송장 시스템 구축 경험 공유
  - 반올림 오류 방지 방법 설명
  - 관련 링크 제공

- 표준 라이브러리의 클래스 사용 권장
  - Java의 BigDecimal 및 Python의 Decimal 사용 추천
  - 동일한 스케일을 유지하거나 스케일을 저장하는 표준 적용 필요성 강조

- 반올림 및 데이터 공유의 어려움 설명
  - 두 자리 소수점만 처리할 수 있는 시스템과의 데이터 공유 문제

- 미국 상위 10대 은행의 API 작업 경험 공유
  - 이자율 저장 방식의 일관성 문제 언급
  - 일관성의 중요성 강조

- Martin Fowler의 "Accounting Patterns" 추천
  - 금융 이벤트 관리 시스템 구축 경험 공유
  - 관련 링크 제공
