Power BI에서 실시간 환율을 가져오는 작업은, 실제로 끝나기 훨씬 전부터 다 끝난 것처럼 보이는 부류의 일입니다. 데이터 가져오기 → 웹에 API URL을 붙여넣으면 환율 테이블이 나타나고, 환산된 매출 측정값에 불이 들어오고, 그대로 게시합니다. 이틀 뒤 Power BI 서비스에서 데이터 세트 새로 고침이 동적 데이터 원본 관련 메시지와 함께 실패합니다. 혹은 성공하되, 모든 과거 거래를 오늘 환율로 조용히 환산해 버립니다.
이 가이드는 전 과정을 다룹니다. 깔끔한 환율 테이블을 반환하는 Power Query M 쿼리, 서비스에서도 새로 고침 가능하게 유지하는 RelativePath 패턴, 거래일 기준 환산을 위한 과거 환율 함수, 동적 보고 통화를 위한 DAX 측정값, 그리고 새로 고침 일정이 API 요금제 안에 들어가는지를 결정하는 요청 수 계산까지.
아래 모든 쿼리는 문서화된 Finexly API 응답 구조를 기준으로 작성했습니다. Excel에서 실시간 환율 가져오기 가이드를 읽으셨다면 여기 M 코드가 익숙할 텐데, Power BI에는 Excel에 없는 서비스 측 새로 고침 계층이 하나 더 있고, 대부분의 프로젝트는 바로 그 지점에서 무너집니다.
Power BI로 환율을 가져오는 세 가지 방법
| 접근법 | 서비스에서 새로 고침 가능? | API 키 안전? | 과거 환율 | 적합한 용도 |
|---|---|---|---|---|
| 웹 커넥터, 대화 상자에 URL 붙여넣기 | 대개 불가 — 그 URL은 보통 동적 데이터 원본이 됨 | ❌ 키가 URL에 노출 | 불가 | 5분짜리 개념 검증 |
빈 쿼리 + Web.Contents + RelativePath | ✅ 가능 | ✅ 헤더 방식 | ✅ 가능 | 거의 모든 실제 모델 |
| 데이터 흐름(또는 Fabric 파이프라인)이 환율 테이블 공급 | ✅ 가능하며 보고서 새로 고침과 분리됨 | ✅ 헤더 방식 | ✅ 가능 | 여러 보고서, 대용량 행 |
방법 1: Power Query로 실시간 환율 테이블 만들기
데이터 변환 → 새 원본 → 빈 쿼리 → 고급 편집기를 열고 다음을 붙여넣으세요. 통화쌍마다 한 행씩, UTC 조회 타임스탬프와 함께 반환합니다.
let
ApiKey = "YOUR_API_KEY",
Base = "USD",
Symbols = "EUR,GBP,JPY,CHF,AUD,CAD,SEK,NZD",
Source = Json.Document(
Web.Contents(
"https://api.finexly.com",
[
RelativePath = "v1/latest",
Query = [ base = Base, symbols = Symbols ],
Headers = [ #"Authorization" = "Bearer " & ApiKey ]
]
)
),
Rates = Record.ToTable( Source[rates] ),
Renamed = Table.RenameColumns( Rates, {{"Name", "Quote"}, {"Value", "Rate"}} ),
AddBase = Table.AddColumn( Renamed, "Base", each Base, type text ),
AddStamp = Table.AddColumn( AddBase, "RetrievedUTC", each DateTimeZone.UtcNow(), type datetimezone ),
Typed = Table.TransformColumnTypes(
AddStamp,
{{"Quote", type text}, {"Rate", type number}}
)
in
Typed호출하는 엔드포인트는 명령줄에서 이렇게 생겼습니다. 파싱할 구조를 눈으로 확인하기 위해 한 번 실행해 볼 가치가 있습니다.
curl "https://api.finexly.com/v1/latest?base=USD&symbols=EUR,GBP,JPY" \
-H "Authorization: Bearer YOUR_API_KEY"{
"success": true,
"base": "USD",
"date": "2026-09-01",
"rates": { "EUR": "…", "GBP": "…", "JPY": "…" }
}RelativePath와 Query가 선택 사항이 아닌 이유
이 글에서 가장 중요한 대목이라 별도 제목을 붙였습니다.
URL을 하나의 연결된 문자열로 만들면 — "https://api.finexly.com/v1/latest?base=" & Base — Power Query는 쿼리가 실제로 실행되기 전까지 목적지를 판단할 수 없습니다. Microsoft는 이를 동적 데이터 원본으로 분류하며, 보안과 개인정보 보호를 이유로 동적 데이터 원본은 Power BI 서비스에서 새로 고쳐지지 않습니다. 보고서는 노트북에서는 완벽히 새로 고쳐지고, 예약되는 순간 실패합니다.
경로를 RelativePath에, 매개변수를 Query에 넘기는 것이 문서화된 예외입니다. 그러면 Power BI는 자격 증명과 개인정보 검사를 위해 단일 정적 기본 URL — https://api.finexly.com — 을 확정할 수 있고, 가변 부분은 가변으로 남습니다. 여기서 세 가지 규칙이 나옵니다.
- 기본 URL은 리터럴 문자열이어야 합니다. 매개변수도, 연결도,
&도 없어야 합니다. RelativePath는 고정된 엔드포인트 경로여야 합니다."v1/latest"이지"v1/latest?base=USD"가 아닙니다.Query안에서 절대 문자열을 연결하지 마세요. 이름/값 쌍 레코드를 넘기고 URL 인코딩은 Power Query에 맡기세요. 요청을 깨뜨릴 문자도 알아서 이스케이프해 줍니다.
자격 증명 설정
쿼리를 처음 실행하면 Power BI가 https://api.finexly.com에 어떻게 인증할지 묻습니다. 익명을 선택하세요. 어색해 보이지만 이게 맞습니다. API 키는 M 코드에 넣은 Authorization 헤더로 전달되지, Power BI의 자격 증명 저장소를 거치지 않습니다. 웹 API나 기본을 고르면 Power BI가 자체 헤더를 추가하고 요청은 거부됩니다.
개인정보 수준은 모든 원본에 걸쳐 공용 또는 조직으로 일관되게 설정하세요. 개인정보 수준 불일치는 "Desktop에서는 되는데 서비스에서는 실패"의 두 번째로 흔한 원인입니다. Power BI는 한 원본의 데이터가 다른 원본 요청으로 새어 나갈 위험을 감수하느니 쿼리를 차단합니다.
솔직한 단서 하나: 키는 이제 쿼리 안에 평문으로 저장됩니다. .pbix를 여는 사람은 누구나 읽을 수 있습니다. 자기 컴퓨터 밖으로 공유되는 것이라면 키를 Power Query 매개변수로 승격하고, 값이 채워진 버전은 서비스 계정이 소유한 데이터 흐름에 두세요. 그러면 보고서 작성자는 자격 증명을 한 번도 보지 않고 환율 테이블만 사용합니다.
방법 2: 거래일 환산을 위한 과거 환율
실시간 환율 테이블은 "지금 EUR/USD가 얼마냐"에 답합니다. "1월 매출이 USD로 얼마였냐"에는 답하지 못하며, 그 용도로 쓰는 것이 이 주제 전체에서 가장 비싼 실수입니다. 모델이 새 환율로 재환산하는 바람에 지난 분기 숫자를 재작성하는 일은, 감사인이 정확히 찾는 상황입니다. 보고서가 나중에 방어해야 할 무언가를 뒷받침한다면 환율과 세무 보고 가이드를 함께 읽어 보세요.
날짜를 키로 하는 환율 테이블이 필요합니다. 다음 M 함수는 시계열 엔드포인트를 감싸 날짜별·통화별로 한 행씩 반환합니다.
let
FxHistory = (base as text, symbols as text, startDate as date, endDate as date) as table =>
let
ApiKey = "YOUR_API_KEY",
Source = Json.Document(
Web.Contents(
"https://api.finexly.com",
[
RelativePath = "v1/timeseries",
Query = [
base = base,
symbols = symbols,
start_date = Date.ToText( startDate, [Format = "yyyy-MM-dd", Culture = "en-US"] ),
end_date = Date.ToText( endDate, [Format = "yyyy-MM-dd", Culture = "en-US"] )
],
Headers = [ #"Authorization" = "Bearer " & ApiKey ]
]
)
),
Days = Table.RenameColumns( Record.ToTable( Source[rates] ), {{"Name", "RateDate"}} ),
Expanded = Table.ExpandRecordColumn( Days, "Value", Record.FieldNames( Days{0}[Value] ) ),
Unpivoted = Table.UnpivotOtherColumns( Expanded, {"RateDate"}, "Quote", "Rate" ),
AsDate = Table.TransformColumns(
Unpivoted,
{{"RateDate", each Date.FromText( _, [Format = "yyyy-MM-dd", Culture = "en-US"] ), type date}}
),
AddBase = Table.AddColumn( AsDate, "Base", each base, type text ),
Typed = Table.TransformColumnTypes( AddBase, {{"Quote", type text}, {"Rate", type number}} )
in
Typed
in
FxHistory여기서 실제로 일하는 디테일이 둘 있습니다.
Date.ToText와Date.FromText양쪽의Culture = "en-US". 이것이 없으면 독일어나 프랑스어 로캘로 설정된 컴퓨터는start_date로01.09.2026을 보내고 API가 거부합니다. 더 나쁘게는, 동료의 새로 고침이 당신 것과 다른 모양의 테이블을 만들어 냅니다. 로캘은 두 나라 이상에 걸친 모든 Power Query 프로젝트의 보이지 않는 변수입니다.Table.UnpivotOtherColumns. API는 날짜를 레코드 키로, 값에 통화의 중첩 레코드를 반환합니다.RateDate / Base / Quote / Rate의 긴 형태로 피벗 해제하면 날짜 차원과 깔끔히 조인되고, 통화를 추가할 때마다 형태를 다시 만들 필요도 없습니다.
로드마다 한 번 호출하세요: FxHistory( "USD", "EUR,GBP,JPY", #date(2026,1,1), Date.From( DateTime.LocalNow() ) ).
과거 날짜의 환율은 절대 바뀌지 않으므로, 이 테이블은 증분 새로 고침의 교과서적 사례입니다. RateDate로 분할하고 최근 7일만 새로 고치고 나머지는 보관하세요. 새로 고침 시간이 히스토리와 함께 늘어나지 않고, 요청 수도 마찬가지입니다.
행마다 API를 호출하지 마세요
이런 모델을 죽이는 패턴은 팩트 테이블의 사용자 지정 열로 환율 함수를 호출하는 것입니다. 1만 건의 거래는 새로 고침마다 1만 번의 HTTP 요청, 40분짜리 새로 고침, 그리고 점심 전에 도착하는 할당량 청구서를 뜻합니다.
만들기 전에 계산부터 하세요. Power BI Pro는 데이터 세트당 하루 8회 예약 새로 고침을, Premium Per User와 Fabric 용량은 48회를 허용합니다. 필요한 모든 통화를 담은 단 한 번의 /v1/latest 호출을 Pro 최대치로 새로 고치면 비용은 하루 8회 요청 — 월 약 240회로, 1,000회 무료 한도 안에 여유 있게 들어옵니다. 같은 일정이라도 행 단위 함수는 상한이 없습니다. PPU 최대치인 48회 새로 고침에서도 통합 호출은 월 약 1,440회 요청에 머물러, 행 단위 참사가 아니라 소액 유료 플랜 수준입니다. 정확히 산정하려면 요금제에 임계값이 정리돼 있습니다.
보고서가 둘 이상 환율을 필요로 한다면 쿼리를 데이터 흐름으로 옮기세요. 데이터 흐름이 자체 일정으로 API를 호출하고 결과를 구체화하면, 하위 데이터 세트는 API를 다시 두드리지 않고 저장소에서 읽습니다. 같은 데이터 흐름 위의 보고서 다섯 개는 다섯 세트가 아니라 한 세트의 요청만 만듭니다.
금액 환산: Power Query 병합 vs DAX 측정값
환산을 적용할 정당한 위치는 두 곳이며, 각각 다른 질문에 답합니다.
옵션 A: Power Query에서 병합
보고 통화가 고정이라면 — 전부 USD로 보고하고 끝 — 로드 시점에 조인하세요.
- 팩트 테이블을 Power Query로 로드합니다.
- 환율 테이블과 쿼리 병합하되, 통화 코드와 날짜로 일치시킵니다.
Ctrl을 누른 채 두 테이블에서 같은 순서로 열을 선택하세요. Rate열만 확장하고 고정 10진수로 설정합니다.Amount와Rate를 선택한 뒤 열 추가 → 표준 → 곱하기.- 다른 참조가 없다면 환율 테이블의 로드를 비활성화합니다.
빠르고, 한 번만 구체화되며, 슬라이서에 흔들리지 않습니다. 마지막 항목이 곧 절충점입니다.
옵션 B: 보고 통화를 선택할 수 있는 DAX 측정값
사용자가 보고서 전체를 USD, EUR, GBP 사이에서 전환해야 한다면 환산은 쿼리 시점에 일어나야 합니다. ISO 코드 한 열만 있는 비연결 테이블 Reporting Currency를 추가해 슬라이서에 넣고 이렇게 작성합니다.
Revenue (Reporting Currency) =
VAR ReportingCurrency = SELECTEDVALUE( 'Reporting Currency'[Code], "USD" )
RETURN
SUMX (
'Sales',
VAR TxCurrency = 'Sales'[CurrencyCode]
VAR TxDate = 'Sales'[OrderDate]
VAR Rate =
CALCULATE (
MAX ( 'FX Rates'[Rate] ),
REMOVEFILTERS ( 'FX Rates' ),
'FX Rates'[Base] = TxCurrency,
'FX Rates'[Quote] = ReportingCurrency,
'FX Rates'[RateDate] = TxDate
)
RETURN 'Sales'[Amount] * Rate
)주목할 점 세 가지:
VAR줄들이 구조를 떠받칩니다.CALCULATE앞에서TxCurrency와TxDate를 변수로 잡아 두면 현재SUMX행에 고정됩니다. 필터 인수 안에서 열을 직접 참조하면 컨텍스트 전환 버그를 불러, 그럴듯하지만 틀린 합계를 만듭니다.REMOVEFILTERS( 'FX Rates' )는 환율 테이블로 들어오는 필터가 조회 범위를 좁히지 못하게 막습니다.- 환율이 없으면
BLANK()가 반환되고,Amount * BLANK()도BLANK()입니다. 바로 이 동작을 원해야 합니다. 조용히 미환산 금액으로 되돌아가는 행은, 그 환율만큼 합계를 부풀리는 행입니다.
관계 설정의 함정
통화 코드만으로 팩트 테이블과 환율 테이블 사이에 물리적 관계를 만들지 마세요. 날짜 키가 있는 환율 테이블에서 통화 코드는 고유하지 않으므로 Power BI는 다대다 관계를 제안하고, 양방향 필터링이 붙은 다대다는 행 수를 마음껏 부풀리고 매출을 몇 배로 만듭니다. Power Query의 복합 키 병합을 쓰거나, 환율 테이블을 비연결로 두고 위처럼 DAX에서 조회하세요.
오류 없이 숫자만 틀리게 만드는 다섯 가지 실수
- 연결된 URL. Desktop에서는 새로 고쳐지고, 서비스에서는 "이 데이터 세트에는 동적 데이터 원본이 포함되어 있습니다"로 실패합니다.
RelativePath와Query로 해결됩니다. - 뒤집힌 통화쌍.
base=USD&symbols=EUR는 USD→EUR를 반환합니다. 팩트 테이블이 EUR 금액을 저장한다면 역수가 필요합니다. 어떤 합계든 믿기 전에 알려진 한 쌍을 손으로 확인하세요. 어느 코드가 어느 쪽인지 헷갈리면 ISO 4217 참고 자료를 보세요. - 과거 행에 오늘 환율. 숫자는 새로 고칠 때마다 바뀌고, 누군가 같은 보고서의 두 내보내기를 비교하기 전까지 아무도 눈치채지 못합니다.
- 로캘 형식의 날짜와 소수. 소수점 쉼표는
1,0842를 텍스트로 만들고,Table.TransformColumnTypes는 모델이 공백으로 취급하는 오류를 반환하며, 해당 행들은 합계에서 사라집니다. - 잘못된 단계에서의 반올림. 곱셈 이후, 표시 단계에서 한 번만 반올림하세요. 일곱 자리 금액에 곱하기 전에 환율을 소수 넷째 자리로 반올림하면 회계 시스템과 눈에 띄는 차이가 생깁니다.
자주 묻는 질문
Power BI가 환율을 자동으로 새로 고칠 수 있나요?
가능합니다. 게시된 데이터 세트는 Power BI Pro에서 하루 최대 8회, Premium Per User 또는 Fabric 용량에서 하루 48회 예약 새로 고침을 설정할 수 있습니다. Premium의 XMLA 엔드포인트를 쓰면 외부 도구로 이 한도 밖에서도 새로 고침을 트리거할 수 있습니다. 환율 쿼리 자체는 서비스가 받아들이도록 Web.Contents + RelativePath로 작성하는 것 외에 특별한 처리가 필요 없습니다.
Power BI에서 API 키를 안전하게 전달하려면?
Web.Contents의 Headers 레코드에 Authorization = "Bearer " & ApiKey로 넣고, Power BI가 물으면 익명 인증을 선택하세요. 이렇게 하면 키가 URL, 프록시 로그, 브라우저 기록에 남지 않습니다. 다만 .pbix 안에서 암호화되지는 않으므로, 공유 모델에서는 서비스 계정이 소유한 데이터 흐름에 키를 두고 보고서는 구체화된 테이블만 읽게 하세요.
왜 "이 데이터 세트에는 동적 데이터 원본이 포함되어 있습니다"라고 나오나요?
URL이 코드로 조립되어 Power BI가 쿼리 실행 전에 목적지를 검증할 수 없기 때문에 서비스에서 새로 고침을 거부하는 것입니다. 정적 기본 URL에 RelativePath와 Query 옵션을 더해 호출을 다시 만들고, 재게시한 뒤 기본 URL에 대한 자격 증명을 다시 입력하세요.
거래일 환율로 금액을 환산하려면?
시계열 엔드포인트에서 날짜 키 환율 테이블을 로드한 다음 통화와 날짜 둘 다로 일치시키세요. Power Query의 복합 키 병합이나, 위에서 보인 SUMX 안의 CALCULATE 조회 중 하나면 됩니다. 통화만으로 조인하면 안 됩니다. 정렬에서 우연히 맨 앞에 온 환율 행을 조용히 집어 오게 됩니다.
Power BI와 함께 쓸 수 있는 무료 환율 API가 있나요?
있습니다. Finexly의 무료 통화 API 등급은 신용카드 없이 월 1,000회 요청을 포함하며, Pro 라이선스 데이터 세트를 하루 여덟 번 새로 고쳐도 여유가 넉넉합니다. 새로 고침 한도, 히스토리 깊이, 통화 커버리지로 공급자를 저울질하는 중이라면, 몇 년간 유지보수할 모델에 연결하기 전에 통화 API 비교를 살펴보세요.
Finexly 시작하기
Power BI 보고서에 실시간 환율을 넣을 준비가 되셨나요? 무료 Finexly API 키를 받으세요 — 신용카드는 필요 없습니다. 월 1,000회 무료 요청으로 시작해 성장에 맞춰 업그레이드하세요. 170개 이상 통화의 실시간·과거 환율을, Power Query에서 부르든 Python에서 부르든 결제 서비스에서 부르든 똑같이 동작하는 하나의 REST 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 →