다국적 재무팀은 결국 똑같은 벽에 부딪힙니다. ERP는 모든 해외 거래, 모든 통화 쌍에 대해 매일 환율이 필요한데, 여전히 누군가가 이를 수작업으로 입력하고 있다는 것입니다. ERP용 환율 API는 이 문제를 해결합니다. 매일의 환율 로드를 회계팀이 출근하기 전에 실행되는 예약 작업으로 바꾸는 것입니다. 이 가이드에서는 NetSuite, SAP S/4HANA, Microsoft Dynamics 365 Finance가 각각 어떻게 환율을 받아들이는지, 이 세 시스템 모두에 데이터를 공급하는 단일 환율 파이프라인을 구축하는 방법, 그리고 제대로 처리하지 않으면 월말 결산을 조용히 망가뜨리는 예외 상황들을 다룹니다.
ERP 시스템에 외부 환율 피드가 필요한 이유
다중 통화 기능이 켜진 모든 ERP는 자체 환율 테이블을 보유합니다. NetSuite에는 Currency Exchange Rates 목록이, SAP에는 (OB08 트랜잭션으로 유지 관리하는) TCURR 테이블이, Dynamics 365 Finance에는 Currency exchange rates 페이지가 있습니다. 총계정원장(GL)의 그 무엇도 시장 피드를 직접 읽지 않습니다 — 전표는 바로 이 내부 테이블을 참조합니다.
이러한 설계는 의도적인 것이며 옳은 방식입니다. 재무 전표는 재현 가능해야 합니다. 감사인이 3월의 분개를 다시 실행하면 3월에 나온 것과 같은 숫자가 나와야 합니다. 날짜가 기록되고 변경되지 않는 환율 테이블은 이를 보장합니다. 실시간 시장 호출은 그렇지 않습니다.
문제는 이 테이블을 어떻게 채우느냐입니다. 실무에서는 세 가지 방법이 흔히 쓰입니다.
- 수동 입력. 누군가 ECB나 은행 사이트를 열어 환율을 복사해 직접 입력합니다. 느리고 오류가 발생하기 쉬우며, 제대로 감사하기가 사실상 불가능합니다 — 그 숫자가 어디서 나왔는지 기록이 없습니다.
- ERP 내장 제공자. NetSuite, SAP, Dynamics는 모두 어떤 형태로든 내장 피드를 제공합니다. 작동은 하지만, 벤더가 선택한 통화 커버리지, 환율 소스, 업데이트 일정을 그대로 받아들여야 하며, 다른 시스템과 대조하기가 어렵습니다.
- 예약 작업에 데이터를 공급하는 전용 환율 API. 소스, 타이밍, 통화 목록, 감사 추적을 직접 통제할 수 있으며, 동일한 피드가 청구 플랫폼, 데이터 웨어하우스, ERP에 동시에 서비스를 제공할 수 있습니다.
이 가이드에서 다루는 것은 세 번째 방법입니다. 결정적인 장점은 시스템 간 일관성입니다. Stripe 청구, BI 대시보드, ERP가 모두 동일한 스냅샷을 사용하면 수익 대조에서 설명할 수 없는 환차손익이 더 이상 발생하지 않습니다.
ERP 등급 환율 피드의 요구 사항
모든 환율 API가 회계에 적합한 것은 아닙니다. 트레이딩 지향 피드는 지연 시간을 최적화하고, ERP용 피드는 재현성을 최적화합니다. 실제로 중요한 것은 다음과 같습니다.
틱 데이터가 아닌 일별 스냅샷
GL에는 1초 미만 단위의 환율이 필요하지 않습니다. 필요한 것은 통화 쌍당 하루에 하나의 공식 환율이며, 일관된 시점에 채취되어 일관되게 적용되어야 합니다. 호출한 시점(초)에 따라 조금씩 다른 값을 반환하는 피드는 장점이 아니라 부채입니다. 필요한 것은 다시 가져와도 같은 값이 나오는 안정적인 일일 종가입니다.
완전한 백필이 가능한 과거 데이터 엔드포인트
과거 환율은 끊임없이 필요합니다. 장애 이후 데이터를 채우거나, 이전 기간 잔액을 재평가하거나, 3주 전 전표를 수정하거나, 감사 요청에 대응할 때 말이지요. 몇 년치를 거슬러 올라가는 과거 환율 API는 타협할 수 없는 요건입니다. 제공자가 "최신 값"만 제공한다면, 장난감을 산 것입니다.
소수 통화 쌍까지 포함하는 폭넓은 통화 커버리지
주요 통화 쌍은 쉽습니다. ERP 로드를 망가뜨리는 것은 나이로비 자회사나 베트남 공급업체가 청구서를 발행하는 통화 쌍입니다. 결산 도중 공백을 발견하기 전에, 제공자가 롱테일 통화까지 커버하는지 확인하세요 — Finexly는 170개 이상의 통화를 지원합니다.
결정적이고 문서화된 반올림 규칙
ERP는 고정된 정밀도로 환율을 저장하며, 시스템마다 그 정밀도가 다릅니다. 환율 정밀도 오류는 수천 건의 전표에 걸쳐 누적됩니다. 반올림 규칙을 한 번 정해서 문서화하고 어디서나 동일하게 적용하세요 — 통화 반올림과 소수 자릿수 가이드에서 관련 함정을 자세히 다룹니다.
직접 소유하는 감사 추적
로드한 각 환율에 대해 소스, 기준 통화와 상대 통화, 환율, 적용일, 조회 시각, 작업 실행 ID를 기록해 두는 것이 좋습니다. 감사인은 "이 숫자는 어디서 왔는가", "누가 이를 변경할 수 있었는가"를 묻습니다 — "ERP 내장 제공자였던 것 같습니다"라는 답변은 설득력이 약합니다. 이는 세무 보고에서의 환율에서 더욱 중요합니다. 과세 당국은 지정된 소스에서 나온 환율을 기간 내내 일관되게 적용할 것을 요구하는 경우가 많기 때문입니다.
각 ERP가 환율을 받아들이는 방식
파이프라인은 공유되며, 최종 전달 단계만 시스템마다 다릅니다.
NetSuite
NetSuite는 세 가지 경로를 제공합니다. 내장 기능인 Currency Exchange Rate Integration(Setup > Company > Enable Features에서 활성화)은 통합된 제공자로부터 하루에 한 번 자동으로 환율을 업데이트합니다. Import Assistant는 환율 CSV 파일을 받아들입니다. 그리고 SuiteScript는 환율 레코드를 직접 작성할 수 있는데, 이는 직접 소스와 일정을 원할 때 선택할 경로입니다.
API에서 데이터를 가져와 currencyrate 레코드를 생성하는 예약 SuiteScript 2.x 스크립트는 완전한 통제권을 제공합니다.
/**
* @NApiVersion 2.1
* @NScriptType ScheduledScript
*/
define(['N/https', 'N/record', 'N/runtime'], (https, record, runtime) => {
const fetchRates = (base, symbols) => {
const res = https.get({
url: `https://api.finexly.com/v1/latest?base=${base}&symbols=${symbols.join(',')}`,
headers: { Authorization: `Bearer ${runtime.getCurrentScript().getParameter({ name: 'custscript_fx_key' })}` }
});
if (res.code !== 200) throw Error(`Finexly returned ${res.code}`);
return JSON.parse(res.body);
};
const execute = () => {
const base = 'USD';
const symbols = ['EUR', 'GBP', 'JPY', 'CAD', 'AUD', 'CHF', 'SEK', 'MXN'];
const payload = fetchRates(base, symbols);
Object.entries(payload.rates).forEach(([quote, rate]) => {
const rec = record.create({ type: 'currencyrate' });
rec.setValue({ fieldId: 'basecurrency', value: currencyIdFor(base) });
rec.setValue({ fieldId: 'transactioncurrency', value: currencyIdFor(quote) });
rec.setValue({ fieldId: 'effectivedate', value: new Date(payload.date) });
rec.setValue({ fieldId: 'exchangerate', value: rate });
rec.save();
});
};
return { execute };
});방향에 특히 주의하세요. NetSuite의 exchangerate 필드는 일부 설정에서는 기준 통화 단위 대비 거래 통화 단위로 환율을 기대하고, 서브시디어리 설정에 따라 다른 경우에는 그 반대를 기대합니다. 한 쌍을 수동으로 로드하고 GL에서 나오는 결과를 확인해 방향을 맞추세요 — 이것이 겉으로는 깔끔하게 실행되지만 실제로는 반대 방향으로 전표가 기록되는 환율 로드의 가장 흔한 원인입니다.
SAP S/4HANA와 ECC
SAP는 환율을 TCURR에 저장하며 여러 로드 경로를 제공합니다. OB08 트랜잭션은 환율을 수동으로 유지 관리합니다. TBD4 트랜잭션은 시장 데이터 제공자로부터 자동 업데이트를 받는 표준 경로입니다. BAPI_EXCHANGERATE_CREATE는 프로그램 방식으로 환율을 기록하며, 대부분의 커스텀 통합에서 사용하는 방법입니다. 일부 팀은 대신 SAP의 표준 임포트가 기대하는 형식의 시장 데이터 파일을 생성해 애플리케이션 서버에 두고 예약 작업이 처리하도록 합니다.
존중해야 할 SAP 고유 개념 두 가지가 있습니다.
- 환율 유형. SAP는
M(표준 환산 환율, 대부분의 전표에서 사용),B(은행 매입율),G(은행 매도율), 그리고 계획이나 예산 환율을 위한 커스텀 유형을 구분합니다. 대개는M유형만 로드하는 것이 올바른 출발점입니다. 실제로 해당 인스턴스에 어떤 유형이 구성되어 있는지 FI 팀과 확인하세요. - 환율 팩터.
TCURF는 통화 쌍에 대한 from/to 팩터를 저장합니다. 기준 통화와의 수치 비율이 큰 통화(EUR나 USD 대비 JPY, KRW, IDR, VND)의 경우 팩터가 1:100 또는 1:1000인 경우가 많습니다. 해당 팩터를 맞추지 않고 원시 환율을 그대로 로드하면 금액이 두세 자릿수만큼 어긋나며, 더 나쁜 것은 얼핏 봐서는 그럴듯해 보여 간단한 검토를 통과해 버린다는 점입니다.
일반적인 패턴은 API에서 로드 파일을 생성한 뒤 예약된 ABAP 작업이 이를 소비하도록 하는 것입니다.
import csv
from datetime import date
import requests
API = "https://api.finexly.com/v1/latest"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
BASE = "EUR"
SYMBOLS = ["USD", "GBP", "JPY", "CHF", "PLN", "CZK", "SEK", "NOK"]
RATE_TYPE = "M"
def build_tcurr_load(target: date, path: str) -> None:
r = requests.get(API, headers=HEADERS,
params={"base": BASE, "symbols": ",".join(SYMBOLS)}, timeout=15)
r.raise_for_status()
payload = r.json()
with open(path, "w", newline="") as fh:
w = csv.writer(fh, delimiter=";")
for quote, rate in payload["rates"].items():
# SAP expects the rate at the precision configured for the pair;
# 5 decimals is a safe default for majors.
w.writerow([RATE_TYPE, BASE, quote,
target.strftime("%Y%m%d"), f"{rate:.5f}"])
build_tcurr_load(date.today(), "/interface/fx/tcurr_load.csv")Microsoft Dynamics 365 Finance
Dynamics 365 Finance는 exchange rate provider 프레임워크와 주기적 작업인 Import currency exchange rates를 함께 제공하며, 이는 일정에 따라 구성된 제공자로부터 데이터를 가져옵니다. 기본으로 몇몇 중앙은행 제공자가 포함되어 있습니다. 이 프레임워크는 확장 가능합니다. X++로 커스텀 제공자를 구현하면, 재무팀이 이미 사용하는 것과 같은 UI에서 자체 API를 정식 옵션으로 사용할 수 있습니다.
X++를 작성하고 싶지 않다면, 실용적인 대안은 타이머로 실행되는 Azure Function이나 Logic App을 통해 exchange rate 데이터 엔터티를 이용해 Data Management Framework로 환율을 밀어 넣는 것입니다. 이렇게 하면 팀이 이미 유지 관리하는 언어로 통합을 유지할 수 있고, 일정이 바뀔 때마다 코드를 재배포할 필요가 없습니다.
파이프라인 구축하기
대상이 무엇이든 작업의 형태는 동일합니다. 한 번 가져와서, ERP별로 변환하고, 로드한 뒤, 검증합니다.
1단계: 스냅샷 한 번 가져오기
하루에 하나의 스냅샷만 가져와서 이를 다운스트림의 모든 시스템에 대한 단일 진실 공급원(source of truth)으로 취급하세요.
curl "https://api.finexly.com/v1/latest?base=USD&symbols=EUR,GBP,JPY,CAD,AUD,CHF" \
-H "Authorization: Bearer YOUR_API_KEY"{
"base": "USD",
"date": "2026-09-03",
"rates": {
"EUR": 0.8631,
"GBP": 0.7402,
"JPY": 151.28,
"CAD": 1.3574,
"AUD": 1.4938,
"CHF": 0.8025
}
}무엇이든 변환하기 전에 이 원본 응답을 그대로 저장하세요. 11월에 어느 컨트롤러가 9월 환율이 왜 그런 값이었는지 물어보면, 저장해 둔 payload가 몇 초 만에 답을 줍니다.
2단계: ERP에 실제로 필요한 통화 쌍 도출하기
API는 하나의 기준 통화 대비 환율을 반환합니다. 하지만 ERP에는 GBP→JPY가 필요할 수 있고, 각 자회사마다 고유한 기능 통화가 있을 수 있습니다. 쌍마다 별도로 호출하는 대신 하나의 스냅샷에서 교차 환율(cross rate)을 도출하세요. 이렇게 하면 도출된 모든 환율의 내부 일관성이 유지되고 요청 수도 적게 유지됩니다.
def cross_rate(rates: dict, base: str, quote: str) -> float:
"""Both legs come from the same snapshot, so the cross is consistent."""
if base == quote:
return 1.0
return rates[quote] / rates[base]
# GBP -> JPY from a USD-based snapshot
gbp_jpy = cross_rate(payload["rates"], "GBP", "JPY") # 151.28 / 0.7402 = 204.38교차 환율의 계산 방식이 낯설다면, 교차 환율 설명 문서에서 제대로 다루고 있습니다.
3단계: 로드한 뒤 검증하기
ERP로부터 받은 HTTP 200 응답 성공을 로드가 제대로 됐다는 증거로 절대 간주하지 마세요. 기록한 뒤에는 몇몇 통화 쌍 샘플을 다시 읽어 스냅샷과 비교하세요. 세 줄짜리 검증 단계만으로도 방향이 뒤바뀐 경우, 조용히 누락된 행, 정밀도 손실을 회계팀이 잘못된 데이터로 전표를 기록하기 전에 잡아낼 수 있습니다.
4단계: 합리적인 실패 처리로 일정 잡기
재무팀이 업무를 시작하기 훨씬 전, 평일 일정으로 작업을 실행하고 다음과 같은 동작을 반영하세요.
- 일시적인 네트워크 장애에 대해 백오프를 두고 재시도하세요 — 10분에 걸친 세 번의 시도로 대부분의 경우를 처리할 수 있습니다.
- 아무것도 로드하지 않는 대신 마지막으로 확인된 정상 환율로 대체하고, 이를 명확히 표시하세요. 오래됐지만 표시가 된 환율을 가진 ERP가 공백이 있는 ERP보다 훨씬 낫습니다.
- 두 번 연속 실패하면 사람에게 알림을 보내세요. 조용한 FX 작업 실패는 월말에 발견되는데, 그때가 가장 최악의 시점입니다.
- 복구 시 백필하세요. 작업이 다시 정상화되면 오늘 날짜뿐 아니라 누락된 모든 날짜를 로드하세요. 캐싱 및 오류 처리 가이드에서 일반적인 패턴을 다룹니다.
월말 결산을 망가뜨리는 함정들
주말과 공휴일. 외환 시장은 문을 닫습니다. 대부분의 ERP는 토요일을 포함해 모든 전표 날짜에 대한 환율을 요구합니다. 금요일 환율을 그대로 이월할지, ERP 자체의 공백 채우기 기능을 사용할지 정책을 명확히 정하고 문서화하세요. 감사인이 반드시 물어볼 것이기 때문입니다.
환율 방향 반전. NetSuite와 관련해 위에서 다뤘지만, 이 위험은 모든 시스템에 공통적입니다. 저장된 숫자가 기준 통화 단위 대비 상대 통화 단위인지, 그 반대인지에 대해 모든 ERP는 나름의 관점을 가지고 있습니다. 방향이 명백한 잘 알려진 통화 쌍으로 검증하세요. USD→JPY가 151이 아니라 0.0066으로 나온다면 방향이 뒤바뀐 것입니다.
시스템 간 타이밍 불일치. 청구 플랫폼이 UTC 00:00에 환율 스냅샷을 찍고 ERP 작업이 현지 시각 06:00에 실행된다면, 청구서와 GL 전표는 서로 다른 숫자를 사용하게 되고 누군가는 그 차이를 대조하느라 한 주를 소비하게 됩니다. 스냅샷은 한 번만 찍고 모든 곳에 배포하세요.
고액권 통화의 환율 팩터. 위에서 다룬 SAP TCURF 문제는 다른 곳에도 유사한 사례가 있습니다. 기준 통화 1단위가 상대 통화 수천 단위에 해당하는 통화는 별도의 테스트 케이스가 필요합니다.
소급 수정. 환율이 잘못 로드되고 이미 전표가 기록된 경우, 대개 테이블을 그냥 덮어쓸 수는 없습니다 — 전표에는 이전 환율이 그대로 남아 있기 때문입니다. 이런 상황이 실제로 필요해지기 전에 재무팀과 함께 수정 워크플로를 미리 계획해 두세요.
직접 만들 것인가, 구매할 것인가 — 솔직한 비교
환율 파이프라인은 실제로는 아주 적은 양의 코드입니다 — 테스트를 포함해도 수백 줄 정도입니다. 환율 API 제공자로부터 구매하는 것은 데이터, 가동 시간(uptime), 과거 데이터 아카이브이지 통합 로직이 아닙니다.
| 수동 입력 | ERP 내장 제공자 | 전용 API + 예약 작업 | |
|---|---|---|---|
| 초기 설정 노력 | 없음 | 낮음 | 1~3일 |
| 지속적인 노력 | 하루 15~30분 | 최소 | 거의 없음 |
| 통화 커버리지 | 직접 찾아본 것만 | 제공자의 목록 | 170개 이상 |
| 시스템 간 일관성 | 없음 | 없음 | 있음 |
| 자체 감사 추적 | 취약 | 제한적 | 완전함 |
| 과거 데이터 백필 | 수동 | 제한적 | 완전함 |
파이프라인이 일단 구축되면 같은 스냅샷이 자연스럽게 인접 시스템에도 데이터를 공급합니다 — 회계 소프트웨어 통합, 다중 통화 청구, BI 대시보드 모두 여러분이 이미 가져오고 있는 바로 그 데이터를 필요로 합니다.
자주 묻는 질문
ERP 환율 로드에 무료 환율 API를 사용해도 될까요?
통화가 몇 개 안 되고 하루에 한 번 로드하는 소규모 법인이라면 가능합니다 — 하루 한 번의 호출은 Finexly의 무료 요금제를 포함한 대부분의 무료 요금제 범위 안에 충분히 들어갑니다. 무료 요금제가 일반적으로 제한하는 것은 과거 데이터의 깊이와 백필 물량인데, 이는 장애 이후나 감사 중에 정확히 필요한 부분입니다. 결정하기 전에 과거 데이터 범위를 확인하세요.
ERP 환율 로드는 얼마나 자주 실행해야 하나요?
대부분의 조직에서는 회계 담당자가 업무를 시작하기 전, 영업일마다 한 번씩입니다. 외환 노출이 큰 기업은 거래 단위 가격 책정을 위해 하루 중 추가 로드를 두면서도 GL 전표용으로는 하나의 일일 환율을 유지하기도 합니다. 그보다 더 자주 하면 정확도 개선 없이 대조 작업만 늘어납니다.
어떤 환율을 써야 하나요 — 스팟, 종가, 아니면 평균?
IFRS와 US GAAP 모두에서 표준 관행은 개별 거래에는 거래일의 환율을, 손익계산서 항목에는 기간 평균 환율을 사용하는 것입니다. 이 결정은 엔지니어링팀이 아니라 재무팀의 몫입니다. 여러분의 역할은 그들이 선택한 환율을 재현 가능한 방식으로 제공하는 것입니다. 사업이 헤지를 하는 경우라면 스팟 환율과 선도 환율의 차이도 여기서 중요합니다.
ERP 내장 제공자를 교체해야 할까요, 아니면 둘 다 운영해야 할까요?
짧은 기간 동안 둘을 병렬로 운영하면서 결과를 비교하세요 — 새 파이프라인을 검증하는 가장 저렴한 방법입니다. 일주일 동안 결과가 일치한다면 내장 제공자를 끄세요. 둘을 무기한 병행 운영하면 어떤 환율이 공식적인 것인지 모호해지며, 이는 둘 중 하나만 쓰는 것보다 더 나쁩니다.
제공자가 지원하지 않는 통화는 어떻게 처리하나요?
유동성 있는 중간 통화 쌍이 존재한다면 교차 환율로 도출하세요. 그렇지 않다면 — 롱테일을 넘어서면 실제로 매우 드문 경우입니다 — 담당자를 지정하고 소스를 명확히 정한 수동 프로세스를 문서화하세요. 조용히 대체 통화로 치환하지 마세요. 그런 것이 2년 뒤 감사에서 드러나는 종류의 문제입니다.
시작하기
ERP에 환율을 수동으로 입력하는 일을 이제 그만두고 싶으신가요? Finexly 무료 API 키를 발급받으세요 — 신용카드가 필요 없습니다. 170개 이상의 통화, 백필과 감사를 위한 과거 데이터, 그리고 하루 오후 만에 NetSuite, SAP, Dynamics에 연결할 수 있는 REST API를 제공합니다. 무료 요금제로 시작해 API 문서를 살펴본 뒤, 호출량이 실제로 필요해질 때만 유료 요금제로 전환하세요.
Explore More
Vlado Grigirov
Senior Currency Markets Analyst & Financial Strategist
Vlado Grigirov is a senior currency markets analyst and financial strategist with over 14 years of experience in foreign exchange markets, cross-border finance, and currency risk management. He has wo...
View full profile →