블로그로 돌아가기

Power BI 통화 변환: API로 실시간 환율 연동하기 (2026 가이드)

V
Vlado Grigirov
August 27, 2026
Currency API Exchange Rates Power BI Power Query DAX Tutorial Finexly

Power BI 통화 변환을 다루는 글은 대개 두 진영 중 하나에 속합니다. DAX 진영은 우아한 측정값을 보여주면서, 모델에 ExchangeRate 테이블이 이미 있다는 사실을 슬쩍 전제합니다. API 진영은 Power BI Desktop에서는 훌륭하게 동작하다가 게시하는 순간 실패하는 Power Query 코드를 보여줍니다. 예약된 새로 고침이 그것을 거부하기 때문입니다.

이 가이드는 두 절반을 순서대로 다룹니다. REST API에서 실시간 환율을 Power BI로 가져오되 Power BI 서비스 게시까지 살아남는 방법, 숫자를 방어할 수 있도록 환율을 모델링하는 방법, 그리고 보고서가 실제로 필요로 하는 바에 따라 가져오기 시점에 변환할지 쿼리 시점에 변환할지 고르는 방법입니다.

아래의 모든 Power Query와 DAX 예제는 Finexly API 문서에 명시된 응답 구조를 기준으로 작성했습니다.

먼저 어떤 변환 문제인지부터 정하세요

"Power BI의 통화 변환"은 같은 이름을 쓰는 세 가지 다른 엔지니어링 문제이며, 여기서 잘못 고르는 것이 이 글 전체에서 가장 비싼 실수입니다.

  1. 여러 원본 통화, 하나의 보고 통화. 매출 테이블에 EUR, GBP, JPY 행이 있고 CFO는 USD 숫자 하나를 원합니다. 가져오기 시점에 변환하세요. 환율은 거래의 속성이지 보고서의 속성이 아닙니다.
  2. 하나의 원본 통화, 여러 보고 통화. 모두 USD로 저장되어 있고 사용자가 슬라이서로 표시 통화를 고릅니다. DAX로 쿼리 시점에 변환하세요. 모든 통화를 미리 계산하는 것은 비현실적입니다.
  3. 여러 원본 통화, 여러 보고 통화. 가져오기 시점에 하나의 기준 통화로 정규화한 뒤, 그 위에 2번을 얹으세요. 한 단계로 해결하려 하지 마세요.

경험 많은 모델러들이 반복해서 말하고, 여기서도 다시 말할 가치가 있는 원칙은 이렇습니다. 가능한 한 이른 단계에서 변환하라. 쿼리 시점으로 미룬 변환은 모든 시각적 개체, 모든 필터 변경, 모든 슬라이서 클릭마다 비용을 청구합니다.

실시간 환율을 Power Query로 제대로 가져오기

환율 테이블부터 시작합니다. 가장 효율적인 호출은 다중 페어 조회입니다. 통화마다 요청을 보내는 대신, 필요한 통화 전부를 한 번의 요청으로 가져옵니다.

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.finexly.com/v1/convert?q=USD_EUR,USD_GBP,USD_JPY"
{
  "USD_EUR": { "rate": 0.9215 },
  "USD_GBP": { "rate": 0.7892 }
}

동일한 내용을 Power Query M으로 작성하면 다음과 같습니다. 빈 쿼리(홈 → 새 원본 → 빈 쿼리 → 고급 편집기)를 만들고 붙여 넣으세요.

let
    ApiKey = "YOUR_API_KEY",
    Pairs  = "USD_EUR,USD_GBP,USD_JPY,USD_CAD,USD_AUD,USD_CHF",
    Source = Json.Document(
        Web.Contents(
            "https://api.finexly.com",
            [
                RelativePath = "v1/convert",
                Query        = [ q = Pairs ],
                Headers      = [ #"Authorization" = "Bearer " & ApiKey ]
            ]
        )
    ),
    ToTable  = Record.ToTable(Source),
    Expanded = Table.ExpandRecordColumn(ToTable, "Value", {"rate"}, {"Rate"}),
    Split    = Table.SplitColumn(
                   Expanded, "Name",
                   Splitter.SplitTextByDelimiter("_", QuoteStyle.None),
                   {"BaseCurrency", "Currency"}
               ),
    Typed    = Table.TransformColumnTypes(
                   Split,
                   {{"BaseCurrency", type text}, {"Currency", type text}, {"Rate", type number}}
               ),
    Stamped  = Table.AddColumn(Typed, "RetrievedAt", each DateTimeZone.UtcNow(), type datetimezone)
in
    Stamped

이름은 FxRates로 지정합니다. BaseCurrency, Currency, Rate, RetrievedAt 네 열짜리 테이블이 만들어지고, 관계와 측정값에 바로 쓸 수 있습니다.

예약된 새로 고침을 망가뜨리는 Web.Contents 실수

위 쿼리가 하지 않는 일에 주목하세요. 매개변수를 URL 문자열에 이어 붙이지 않습니다. 통화 변환 보고서가 데스크톱에서는 돌아가고 클라우드에서는 죽는 가장 흔한 이유가 바로 이것입니다.

대신 이렇게 쓰면:

// Do NOT do this
Source = Json.Document(
    Web.Contents("https://api.finexly.com/v1/convert?q=" & Pairs)
)

…Power BI Desktop은 아무 불평 없이 새로 고침하고, Power BI 서비스는 "이 데이터 세트에는 동적 데이터 원본이 포함되어 있습니다. 새로 고침이 지원되지 않습니다." 라며 거부합니다. 서비스는 자격 증명을 연결하기 위해 분석 시점에 정적 기본 URL을 확정할 수 있어야 합니다. 가변 부분을 RelativePathQuery로 넘기면 정확히 그 조건이 충족됩니다. 기본 URL은 https://api.finexly.com으로 고정되고, 동적인 것은 모두 옵션 안에 놓입니다.

매개변수, 날짜, 다른 테이블의 값으로 URL을 만드는 모든 쿼리에 같은 규칙이 적용됩니다. 이 글에서 하나만 가져간다면 RelativePath를 가져가세요.

API 키를 하드코딩하지 않고 다루기

ApiKey = "YOUR_API_KEY"를 코드에 직접 적는 것은 5분짜리 테스트에는 괜찮지만 공유되는 무엇에도 부적절합니다. 의미 체계 모델의 M 코드는 빌드 권한이 있는 모든 사람에게 보입니다.

현실적인 두 가지 선택지:

  • Power Query 매개변수(홈 → 매개 변수 관리)를 만들고 ApiKey = KeyParam으로 참조합니다. 여전히 모델과 함께 저장되지만 한곳에 모이고, 교체가 쉬우며, 배포 파이프라인으로 환경별 재정의가 가능합니다.
  • 웹 API 자격 증명 유형. Power BI 서비스에서 의미 체계 모델 설정 → 데이터 원본 자격 증명 → 자격 증명 편집으로 가서 웹 API를 선택하고 키를 입력합니다. 그러면 서비스가 Authorization 헤더를 직접 주입하므로 M에서 Headers 옵션을 완전히 제거할 수 있습니다. 비밀 값이 모델 정의 밖에 남게 됩니다.

무엇을 고르든 보고 용도로만 제한된 키를 쓰고, 팀에서 누군가 떠나면 교체하세요. 키가 헤더가 아니라 URL 쿼리 문자열에 들어가면 프록시와 서버 액세스 로그에 남을 수 있습니다. Finexly 문서도 이 점을 지적하고 있으며, 이는 모든 공급자에 해당합니다.

환율 목록이 아니라 통화 차원을 만드세요

환율 테이블만 있으면 숫자만 얻습니다. 올바른 레이블도, 올바른 소수 자릿수도, 제대로 정렬되는 슬라이서도 얻지 못합니다. 통화 목록을 별도 차원으로 가져오세요.

let
    ApiKey = "YOUR_API_KEY",
    Source = Json.Document(
        Web.Contents(
            "https://api.finexly.com",
            [
                RelativePath = "v1/currencies",
                Headers      = [ #"Authorization" = "Bearer " & ApiKey ]
            ]
        )
    ),
    ToTable = Table.FromList(Source, Splitter.SplitByNothing(), {"Currency"}),
    Typed   = Table.TransformColumnTypes(ToTable, {{"Currency", type text}})
in
    Typed

그런 다음 Power BI가 대신 추론해 줄 수 없는 두 열을 추가합니다.

  • MinorUnits — 해당 통화가 실제로 쓰는 소수 자릿수. JPY는 0, KWD는 3, 대부분은 2입니다. 엔화 합계를 소수 두 자리로 표시하는 것은 재무 보고서에서 눈에 띄는 오류이고, 잘못된 단계에서의 반올림이 이를 키웁니다. 통화 반올림 가이드가 오차가 어디서 들어오는지 다룹니다.
  • FormatString — 예: "\€#,0.00", "\¥#,0". 뒤에서 동적 서식 문자열에 필요합니다.

두 값 모두 Power BI가 기본으로 아는 것이 아니라 ISO 4217 표준을 따릅니다. ISO 4217 참조에 전체 표가 있습니다. 이 테이블을 차원으로 표시하고 FxRates[Currency]와 일대다로 연결한 뒤, 슬라이서의 원본으로는 환율 테이블이 아니라 이 테이블을 쓰세요.

경로 A: 가져오기 시점 변환 (빠르고, 밋밋하고, 정확함)

시나리오 1 —— 여러 통화가 들어오고 하나가 나가는 경우 —— 에서는 작업을 Power Query에서 끝내고 모델에는 깔끔한 숫자 하나만 저장하게 하세요.

  1. 거래 쿼리를 Power Query로 로드합니다.
  2. 홈 → 쿼리 병합으로 Transactions[Currency]FxRates[Currency]를 조인합니다(왼쪽 외부).
  3. 병합된 열을 확장하고 Rate만 남깁니다.
  4. 열 추가 → 사용자 지정 열:
= if [Currency] = "USD" then [Amount]
  else if [Rate] = null then null
  else [Amount] / [Rate]

null 분기에 주목하세요. 특정 통화가 빠진 환율 테이블에 왼쪽 외부 조인을 하면 null이 생기고, Power Query 산술에서 null은 오류가 아니라 조용히 null을 반환합니다. 그것이 시각적 개체의 공백이 되고, 조용히 너무 작은 합계가 됩니다. 빈 곳을 명시적으로 만들어 필터링하고 눈에 보이게 하세요.

나눗셈에도 주목하세요. USD_EUR = 0.9215는 1 USD가 0.9215 EUR라는 뜻이므로 EUR 금액을 USD로 바꿀 때는 나눕니다. USD 금액을 EUR로 바꿀 때는 곱합니다. 이 방향을 뒤집는 것이 다중 통화 보고서에서 두 번째로 흔한 버그이며, 환율이 1.0 근처면 거의 보이지 않습니다. EUR/USD 수치의 3% 오차는 누군가 대사(對査)를 하기 전까지는 반올림 차이처럼 보입니다.

경로 B: DAX로 쿼리 시점 변환

시나리오 2 —— 저장 통화는 하나, 표시 통화는 사용자가 선택 —— 에서는 변환이 측정값 안에서 일어나야 합니다.

단순한 구현은 행마다 LOOKUPVALUE를 하며, 수십만 행을 넘기면 느려집니다. 먼저 집계하고, 변환은 한 번만 하세요.

Sales (Reporting Currency) =
VAR SelectedCurrency = SELECTEDVALUE ( Currency[Currency], "USD" )
VAR Rate =
    CALCULATE (
        SELECTEDVALUE ( FxRates[Rate] ),
        FxRates[Currency] = SelectedCurrency
    )
VAR Result =
    IF (
        SelectedCurrency = "USD",
        [Sales Amount],
        [Sales Amount] * Rate
    )
RETURN
    IF ( ISBLANK ( Rate ) && SelectedCurrency <> "USD", BLANK (), Result )

보이는 것보다 중요한 두 가지 세부 사항:

  • 기본값이 있는 SELECTEDVALUE. "USD" 대체값이 없으면 통화가 선택되지 않은 순간 측정값이 공백을 반환합니다. 그리고 보고서가 열리는 상태가 바로 그것입니다.
  • 명시적인 공백 가드. 환율이 없는 통화라면 [Sales Amount] * BLANK()가 0을 반환하게 두지 말고 의도적으로 공백을 반환하세요. 매출 카드의 0은 거짓말이고, 공백은 눈에 보이는 결측입니다.

환율이 시간에 따라 달라질 때

위 측정값은 데이터 세트 전체에 현재 환율 하나를 적용합니다. "작년 매출이 오늘 기준으로 얼마인가"에는 맞고 나머지 거의 모든 경우에는 틀립니다. 환율 테이블이 통화×일자로 한 행씩이라면 변환 전에 날짜로 그룹화하세요.

Sales (Historical Rates) =
SUMX (
    VALUES ( 'Date'[Date] ),
    VAR DayRate =
        CALCULATE (
            SELECTEDVALUE ( FxRates[Rate] ),
            FxRates[Currency] = SELECTEDVALUE ( Currency[Currency], "USD" )
        )
    RETURN
        [Sales Amount] * DayRate
)

팩트 테이블이 아니라 VALUES('Date'[Date])를 반복하면 반복자가 작게 유지됩니다. 거래 건수가 아니라 일수이기 때문입니다.

동적 서식 문자열

변환된 숫자에 $ 접두사를 고정해 두는 것은 기호가 아예 없는 것보다 나쁩니다. Power BI에서 측정값의 서식동적으로 설정하고 식을 지정하세요.

SELECTEDVALUE ( Currency[FormatString], "#,0.00" )

이제 ¥를 보여주는 카드는 소수점 없이 ¥를 표시하며, 두 번째 측정값은 필요 없습니다. 예전에는 Analysis Services의 계산 그룹이 필요했지만, 측정값의 동적 서식 문자열이 이를 Power BI 자체로 가져왔습니다.

실제로 어떤 환율을 써야 할까요?

이것이 대시보드와 재무팀이 승인하는 보고서를 가르는 질문이며, 어떤 API도 대신 답해 주지 않습니다.

  • 거래일 현물환율 — 개별 거래를 기록할 때. 정확도가 가장 높고 환율 테이블도 가장 큽니다.
  • 월 또는 기간 평균 — IAS 21과 ASC 830 모두에서 손익계산서 항목의 표준입니다. 월중 변동을 평탄화하며 대부분의 연결 결산이 실제로 사용합니다.
  • 기말 마감 환율 — 재무상태표 항목(현금, 매출채권, 매입채무)용.
  • 예산 환율 또는 계획 환율 — 연중 고정해 두어 차이 분석이 영업 성과와 환율 변동을 분리하도록 합니다.

제대로 된 모델은 이 중 두세 가지를 동시에 필요로 하는 경우가 많습니다. 별도 테이블이 아니라 같은 환율 테이블의 별도 열(SpotRate, AverageRate, ClosingRate)로 두세요. 보고서가 신고 자료로 이어진다면 환율과 세무 보고 가이드가 소명 가능한 출처와 타임스탬프를 다루고, 과거 환율 가이드가 실시간이 아닌 일자 지정 환율 조회를 다룹니다.

합계를 조용히 망가뜨리는 주말 공백

외환 시장은 문을 닫습니다. 실시간 API로 만든 일별 환율 테이블에는 토요일도, 일요일도, 12월 25일도 없습니다. 토요일자 거래를 그 테이블에 조인하면 null이 나오고, null은 공백이 되며, 공백은 딱 주말 매출만큼 작아진 합계가 됩니다.

측정값이 아니라 환율 테이블에서 고치세요. 연속된 날짜 목록을 만들고 아래로 채웁니다.

let
    Dates = List.Dates(#date(2026,1,1), Duration.Days(Date.From(DateTime.LocalNow()) - #date(2026,1,1)) + 1, #duration(1,0,0,0)),
    DateTable = Table.FromList(Dates, Splitter.SplitByNothing(), {"Date"}),
    Typed = Table.TransformColumnTypes(DateTable, {{"Date", type date}}),
    Joined = Table.NestedJoin(Typed, {"Date"}, RateHistory, {"Date"}, "r", JoinKind.LeftOuter),
    Expanded = Table.ExpandTableColumn(Joined, "r", {"Currency", "Rate"}),
    Filled = Table.FillDown(Expanded, {"Currency", "Rate"})
in
    Filled

Table.FillDown은 금요일 환율을 주말 내내 이어 갑니다. 이는 관행적인 처리이며, 더 중요하게는 우연이 아니라 명시된 처리입니다. 채우기 전에 통화와 날짜로 정렬하세요. 그러지 않으면 다른 통화의 환율을 공백 구간으로 끌고 가게 됩니다.

요금제에 과거 데이터 엔드포인트가 없다면 이력을 앞으로 쌓아 갈 수도 있습니다. 새로 고침마다 오늘 환율을 저장 테이블에 추가하세요 —— 데이터 흐름이나 Fabric 레이크하우스 테이블이 적합합니다 —— 한 분기가 지나면 진짜 시계열이 생깁니다. 소급은 안 되지만 비용은 하루 API 호출 한 번입니다.

새로 고침 일정과 할당량 계산

Power BI Pro는 의미 체계 모델당 하루 8회 예약 새로 고침을 허용하고, Premium과 Fabric 용량은 48회를 허용합니다. 이것이 API 할당량이 감당해야 할 숫자이며, 계산은 생각보다 너그럽습니다.

위 환율 테이블은 새로 고침 한 번당 두 번의 호출입니다. /v1/currencies 한 번, /v1/convert 한 번. 따라서:

새로 고침 주기월 새로 고침 횟수월 API 호출Finexly 요금제
하루 8회 (Pro 최대)약 240약 480무료 (1,000/월)
하루 48회 (Fabric, 30분마다)약 1,440약 2,880Starter
하루 48회 + 시간별 데이터 흐름 이력약 2,160약 4,320Growth
무료 요금제는 월 1,000회 요청에 분당 10회 상한이며, 최대 주기로 새로 고침하는 Pro 작업 영역을 넉넉히 감당합니다. 현재 한도와 과거 데이터 제공 여부는 요금 페이지에 있습니다.

주의해야 할 것은 분당 10회 상한입니다. Table.AddColumn 안에서 통화마다 /v1/rate를 호출하는 쿼리를 만들면, 20개 통화는 몇 초 만에 20회 호출이 되고 새로 고침 도중에 429가 연달아 발생합니다. 다중 페어 /v1/convert 호출이 존재하는 이유가 바로 이것입니다. 묶어서 호출하고 캐시하세요. 캐싱 및 오류 처리 가이드의 백오프 재시도 패턴은 예약 새로 고침에도 그대로 적용됩니다.

게이트웨이, Excel, Fabric

각각 반나절을 아껴 주는 환경 관련 메모입니다.

  • 게이트웨이는 필요 없습니다. 클라우드 REST API는 온프레미스 원본이 아니므로 온-프레미스 데이터 게이트웨이가 필요하지 않습니다. 새로 고침이 실패하는데 누군가 게이트웨이 설치를 권한다면, 그것은 거의 항상 동적 데이터 원본 오류가 모습을 바꾼 것입니다.
  • Excel도 같은 엔진을 씁니다. Excel의 Power Query는 위 M을 그대로 받습니다. 독자가 대시보드가 아니라 통합 문서에서 일한다면 Excel 실시간 환율 가이드WEBSERVICE, LAMBDA, 버전 표를 다룹니다. Google 스프레드시트 버전도 있습니다.
  • 보고서가 둘 이상 환율 테이블을 필요로 한다면 Fabric Dataflow Gen2가 더 나은 자리입니다. 환율을 한 번만 적재하고 모든 의미 체계 모델이 같은 테이블을 읽게 하면, API 사용량이 보고서 수에 비례해 늘지 않습니다.
  • 게시 전에 알려진 값과 대조하세요. 통화 변환기에서 한 페어를 가져와 같은 시점의 같은 페어에 대해 모델이 보여 주는 값과 비교하세요. 다르다면 방향이나 반올림 문제이며, 이사회 자리가 아니라 지금 찾는 편이 낫습니다.

자주 묻는 질문

API 없이 Power BI로 통화 변환을 할 수 있나요? 환율을 직접 공급한다면 가능합니다. 수동으로 관리하는 표, 재무 시스템 내보내기, 데이터베이스 뷰 등입니다. Power BI에는 기본 제공 환율 원본이 없습니다. API가 의미를 갖는 것은 "누가 기억하지 않아도" 갱신되는 환율이 필요할 때입니다.

변환 보고서가 Power BI Desktop에서는 새로 고쳐지는데 서비스에서는 실패하는 이유는? 거의 항상 동적 데이터 원본 오류입니다. Web.Contents 호출이 문자열 연결로 URL을 만들고 있습니다. 가변 부분을 RelativePathQuery 옵션으로 옮겨 기본 URL을 정적으로 만든 뒤 다시 게시하고 자격 증명을 다시 입력하세요.

변환은 Power Query와 DAX 중 어디서 해야 하나요? 보고 통화가 하나면 Power Query가 더 빠르고 단순합니다. 사용자가 실행 중에 통화를 고른다면 DAX입니다. 둘 다 필요하면 Power Query에서 기준 통화로 정규화한 뒤 그 위에 DAX 측정값을 얹으세요.

Power BI 새로 고침 한 번에 API 요청이 얼마나 드나요? 모든 페어를 /v1/convert 한 번으로 묶으면 새로 고침당 두 번입니다. Power BI Pro의 하루 8회 최대치 기준으로 월 약 480회이며 무료 요금제 범위 안입니다. 비싸지는 경우는 통화마다 또는 행마다 API를 호출할 때뿐입니다.

일별 환율 테이블에서 주말과 공휴일은 어떻게 처리하나요? 연속된 날짜 테이블을 만들고 환율을 왼쪽 조인한 뒤, 통화와 날짜로 정렬하고 아래로 채우세요. 금요일 환율이 주말로 이어집니다. 중요한 것은 그 처리가 의도적이고 문서화되어 있다는 점이며, 행이 조용히 사라지지 않는다는 점입니다.

재무 보고에는 어떤 환율을 써야 하나요? 손익계산서 항목에는 기간 평균 환율, 재무상태표 항목에는 기말 환율을 씁니다. IAS 21과 ASC 830 모두 동일합니다. 하나의 환율 테이블에 별도 열로 저장하면 모델을 바꾸지 않고도 보고서에서 전환할 수 있습니다.


대시보드 뒤에 실시간 환율을 놓을 준비가 되셨나요? 무료 Finexly API 키 받기 —— 신용카드는 필요 없습니다. 월 1,000회 요청으로 시작하세요. Power BI Pro 작업 영역을 최대 주기로 새로 고치기에 충분한 양이며, 과거 데이터나 더 잦은 갱신이 필요해지면 업그레이드하면 됩니다. 아직 공급자를 비교하는 중이라면 비교 페이지에서 선택지를 나란히 볼 수 있습니다.

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 →

이 기사 공유하기