React와 실시간 환율 API로 통화 변환기 만들기
React로 통화 변환기를 만드는 것은 API 통합, React Hooks, 실제 상태 관리를 연습하고 싶은 개발자에게 훌륭한 프로젝트입니다. 이 단계별 튜토리얼에서는 환율 API에서 실시간 환율을 가져오고, 170개 이상의 통화를 지원하며, 오류를 우아하게 처리하는 완전한 기능의 통화 변환기를 구축합니다 — 모두 모던 React 패턴을 사용하여.
환율 작동 방식이 처음이라면 시작하기 전에 환율 설명서를 확인하세요.
무엇을 만들까요
이 튜토리얼이 끝나면 다음과 같은 React 통화 변환기가 완성됩니다:
- Finexly API에서 실시간 환율 가져오기
- 드롭다운으로 170개 이상의 통화 지원
- 사용자가 입력할 때 실시간으로 변환 (디바운싱 포함)
- 로딩 상태와 API 오류 우아하게 처리
- 환율과 마지막 업데이트 타임스탬프 표시
프로젝트 구조:
currency-converter/
├── src/
│ ├── components/
│ │ └── CurrencyConverter.tsx
│ ├── hooks/
│ │ └── useExchangeRate.ts
│ ├── App.tsx
│ └── main.tsx
├── package.json
└── vite.config.ts사전 요구사항
시작하기 전에 다음을 확인하세요:
- Node.js 18+ 설치
- React Hooks (
useState,useEffect)에 대한 기본 지식 - 무료 Finexly API 키 (약 30초면 얻을 수 있음)
1단계: React 프로젝트 설정
빌드 도구로 Vite를 사용합니다:
npm create vite@latest currency-converter -- --template react-ts
cd currency-converter
npm install
npm run dev개발 서버가 http://localhost:5173에서 시작됩니다.
2단계: Finexly API 이해하기
Finexly API는 간단한 REST 인터페이스를 통해 170개 이상의 통화에 대한 실시간 및 과거 환율을 제공합니다:
GET https://finexly.com/api/v1/latest?base=USD일반적인 응답:
{
"base": "USD",
"date": "2026-04-07",
"rates": {
"EUR": 0.9182,
"GBP": 0.7871,
"JPY": 151.42
},
"timestamp": 1744012800
}요청 헤더에 키를 포함합니다:
Authorization: Bearer 당신의_API_키월 1,000회 요청이 포함된 무료 플랜에 가입할 수 있습니다.
3단계: 커스텀 Hook 만들기
src/hooks/useExchangeRate.ts를 만듭니다:
import { useState, useEffect, useCallback } from "react";
interface ExchangeRateResult {
rates: Record<string, number> | null;
loading: boolean;
error: string | null;
lastUpdated: Date | null;
}
const API_KEY = import.meta.env.VITE_FINEXLY_API_KEY;
const BASE_URL = "https://finexly.com/api/v1";
const rateCache: Record<string, { rates: Record<string, number>; timestamp: number }> = {};
const CACHE_TTL_MS = 5 * 60 * 1000;
export function useExchangeRate(baseCurrency: string): ExchangeRateResult {
const [rates, setRates] = useState<Record<string, number> | null>(null);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
const [lastUpdated, setLastUpdated] = useState<Date | null>(null);
const fetchRates = useCallback(async (base: string) => {
const cached = rateCache[base];
if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
setRates(cached.rates);
setLastUpdated(new Date(cached.timestamp));
return;
}
setLoading(true);
setError(null);
try {
const res = await fetch(`${BASE_URL}/latest?base=${base}`, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
if (!res.ok) throw new Error(`API 오류: ${res.status} ${res.statusText}`);
const data = await res.json();
rateCache[base] = { rates: data.rates, timestamp: Date.now() };
setRates(data.rates);
setLastUpdated(new Date());
} catch (err) {
setError(err instanceof Error ? err.message : "환율을 가져오지 못했습니다");
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
if (baseCurrency) fetchRates(baseCurrency);
}, [baseCurrency, fetchRates]);
return { rates, loading, error, lastUpdated };
}4단계: CurrencyConverter 컴포넌트 만들기
src/components/CurrencyConverter.tsx를 만듭니다:
import { useState, useMemo } from "react";
import { useExchangeRate } from "../hooks/useExchangeRate";
const CURRENCIES = [
"USD", "EUR", "GBP", "JPY", "CAD", "AUD", "CHF", "CNY",
"INR", "MXN", "BRL", "KRW", "SGD", "HKD", "NOK", "SEK",
];
export default function CurrencyConverter() {
const [amount, setAmount] = useState<string>("100");
const [baseCurrency, setBaseCurrency] = useState<string>("USD");
const [targetCurrency, setTargetCurrency] = useState<string>("EUR");
const { rates, loading, error, lastUpdated } = useExchangeRate(baseCurrency);
const convertedAmount = useMemo(() => {
if (!rates || !amount) return null;
const numAmount = parseFloat(amount);
if (isNaN(numAmount) || numAmount < 0) return null;
const rate = rates[targetCurrency];
return rate ? (numAmount * rate).toFixed(2) : null;
}, [rates, amount, targetCurrency]);
const handleSwap = () => {
setBaseCurrency(targetCurrency);
setTargetCurrency(baseCurrency);
};
return (
<div className="converter-card">
<h2>실시간 통화 변환기</h2>
<div className="input-row">
<label htmlFor="amount">금액</label>
<input
id="amount"
type="number"
min="0"
value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="금액 입력"
/>
</div>
<div className="currency-row">
<div className="select-group">
<label htmlFor="base">변환 전</label>
<select id="base" value={baseCurrency} onChange={(e) => setBaseCurrency(e.target.value)}>
{CURRENCIES.map((c) => <option key={c} value={c}>{c}</option>)}
</select>
</div>
<button className="swap-btn" onClick={handleSwap} aria-label="통화 교체">⇄</button>
<div className="select-group">
<label htmlFor="target">변환 후</label>
<select id="target" value={targetCurrency} onChange={(e) => setTargetCurrency(e.target.value)}>
{CURRENCIES.map((c) => <option key={c} value={c}>{c}</option>)}
</select>
</div>
</div>
<div className="result-area">
{loading && <p>최신 환율 가져오는 중...</p>}
{error && <p className="error-text">⚠ {error}</p>}
{!loading && !error && convertedAmount !== null && (
<>
<p className="converted-value">
{parseFloat(amount).toLocaleString()} {baseCurrency} =
<strong>{parseFloat(convertedAmount).toLocaleString()} {targetCurrency}</strong>
</p>
{lastUpdated && <p>환율 업데이트: {lastUpdated.toLocaleTimeString()}</p>}
</>
)}
</div>
</div>
);
}5단계: 환경 변수
프로젝트 루트에 .env 파일을 만듭니다:
VITE_FINEXLY_API_KEY=당신의_api_키_여기API 키를 보호하기 위해 .env를 .gitignore에 추가하세요.
6단계: 앱 연결하기
src/App.tsx를 업데이트합니다:
import CurrencyConverter from "./components/CurrencyConverter";
function App() {
return (
<main>
<CurrencyConverter />
<footer>
<p>환율 제공: <a href="https://finexly.com">Finexly</a></p>
</footer>
</main>
);
}
export default App;더 나아가기
기본 변환기가 동작하면 고가치 개선사항으로는 Finexly 과거 데이터 API를 사용한 30일 환율 차트, 동시 다중 통화 변환, localStorage에 즐겨찾는 통화 쌍 저장, Next.js를 사용한 서버 사이드 렌더링 등이 있습니다.
자주 묻는 질문
React에 가장 좋은 환율 API는 무엇인가요? React 앱에는 CORS를 지원하는 REST API가 필요합니다. Finexly API는 모든 플랜에서 CORS를 지원하고 무료 티어로 170개 이상의 통화를 제공합니다.
환율은 얼마나 자주 업데이트되나요? Finexly API는 실시간 플랜은 60초마다, 스탠다드 플랜은 하루 한 번 업데이트됩니다.
클라이언트 사이드 React 앱에서 통화 API를 사용할 수 있나요? API가 CORS를 지원하면 가능합니다. 프로덕션 앱에서는 자체 백엔드를 통해 요청을 라우팅하는 것이 좋습니다.
React에서 API 키가 노출되지 않도록 하려면?
개발 시에는 Vite의 .env 파일에 VITE_ 접두사를 사용하세요. 프로덕션에서는 Next.js API Route나 Serverless 함수를 통해 요청을 라우팅하세요.
USD가 아닌 두 통화 사이에서 변환하는 방법은? Finexly API는 모든 플랜에서 임의의 기준 통화를 지원하므로 이를 크게 단순화합니다.
React 앱에 실시간 환율을 추가할 준비가 되었나요? 무료 Finexly API 키 받기 — 신용카드 불필요. 월 1,000회 무료 요청으로 시작하고 성장에 따라 업그레이드하세요.
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 →