업비트 알림봇 만들기 3편 - API 연동

업비트 API 문서 처음 봤을 때 좀 어려워 보였는데, 막상 써보니까 엄청 간단하더라고요. 시세 조회는 API 키도 필요 없어서 바로 테스트해볼 수 있고요.
지난 편에서 Cloudflare Workers 프로젝트를 만들고 배포까지 해봤죠? 이번 편에서는 드디어 업비트 API를 연동해볼 거예요. 실시간으로 코인 가격 가져오는 거죠.
업비트 API 기본
업비트 API는 크게 두 종류예요:
- QUOTATION API: 시세 조회 (API 키 불필요)
- EXCHANGE API: 주문, 잔고 조회 (API 키 필요)
우리는 시세만 볼 거니까 API 키 없이 바로 사용할 수 있어요.
마켓 코드 조회하기
먼저 어떤 코인들이 있는지 볼게요. src/index.js를 수정하세요:
export default {
async fetch(request, env, ctx) {
// 업비트 마켓 목록 조회
const response = await fetch('https://api.upbit.com/v1/market/all');
const markets = await response.json();
// KRW 마켓만 필터링
const krwMarkets = markets.filter(m => m.market.startsWith('KRW-'));
return new Response(JSON.stringify(krwMarkets, null, 2), {
headers: { 'Content-Type': 'application/json' },
});
},
};
로컬에서 실행해보세요:
npm run dev
[
{
"market": "KRW-BTC",
"korean_name": "비트코인",
"english_name": "Bitcoin"
},
{
"market": "KRW-ETH",
"korean_name": "이더리움",
"english_name": "Ethereum"
},
...
]
원화(KRW)로 거래 가능한 코인 목록이 나와요.

현재가 조회하기
이제 진짜 가격을 가져와볼게요. 코드를 이렇게 바꿔보세요:
export default {
async fetch(request, env, ctx) {
// 비트코인, 이더리움 현재가 조회
const markets = 'KRW-BTC,KRW-ETH,KRW-XRP';
const response = await fetch(
`https://api.upbit.com/v1/ticker?markets=${markets}`
);
const tickers = await response.json();
// 필요한 정보만 추출
const result = tickers.map(ticker => ({
market: ticker.market,
현재가: ticker.trade_price.toLocaleString() + '원',
변동: ticker.change === 'RISE' ? '상승' : ticker.change === 'FALL' ? '하락' : '보합',
변동률: (ticker.change_rate * 100).toFixed(2) + '%',
거래량: Math.floor(ticker.acc_trade_volume_24h).toLocaleString(),
}));
return new Response(JSON.stringify(result, null, 2), {
headers: { 'Content-Type': 'application/json' },
});
},
};
[
{
"market": "KRW-BTC",
"현재가": "139,850,000원",
"변동": "상승",
"변동률": "2.35%",
"거래량": "1,234"
},
{
"market": "KRW-ETH",
"현재가": "4,850,000원",
"변동": "하락",
"변동률": "-1.20%",
"거래량": "5,678"
}
]
업비트 API 주요 필드 정리
ticker API가 주는 데이터 중 자주 쓰는 것들이에요:
| 필드 | 설명 |
|---|---|
market | 마켓 코드 (KRW-BTC) |
trade_price | 현재가 |
change | RISE/FALL/EVEN |
change_rate | 변동률 (0.0235 = 2.35%) |
change_price | 변동 금액 |
acc_trade_volume_24h | 24시간 거래량 |
acc_trade_price_24h | 24시간 거래대금 |
high_price | 당일 고가 |
low_price | 당일 저가 |
prev_closing_price | 전일 종가 |
URL 파라미터로 코인 선택하기
하드코딩 말고 URL로 코인을 선택할 수 있게 해볼게요:
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
const markets = url.searchParams.get('markets') || 'KRW-BTC';
const response = await fetch(
`https://api.upbit.com/v1/ticker?markets=${markets}`
);
const tickers = await response.json();
const result = tickers.map(ticker => ({
market: ticker.market,
price: ticker.trade_price,
change: ticker.change,
change_rate: (ticker.change_rate * 100).toFixed(2) + '%',
volume_24h: ticker.acc_trade_volume_24h,
}));
return new Response(JSON.stringify(result, null, 2), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
});
},
};
이제 이렇게 요청할 수 있어요:
http://localhost:8787?markets=KRW-BTC,KRW-ETH,KRW-DOGE
가격 변동 감지 로직 추가
알림봇의 핵심이죠. 특정 조건을 만족하면 알림을 보내야 해요. 일단 조건 체크 로직부터 만들어볼게요:
// 알림 조건 체크 함수
function checkAlertConditions(ticker) {
const alerts = [];
const changeRate = ticker.change_rate * 100;
// 5% 이상 급등
if (ticker.change === 'RISE' && changeRate >= 5) {
alerts.push({
type: 'PUMP',
message: `🚀 ${ticker.market} 급등! +${changeRate.toFixed(2)}%`,
});
}
// 5% 이상 급락
if (ticker.change === 'FALL' && changeRate >= 5) {
alerts.push({
type: 'DUMP',
message: `📉 ${ticker.market} 급락! -${changeRate.toFixed(2)}%`,
});
}
// 특정 가격 도달 (예: 비트코인 1억5천)
if (ticker.market === 'KRW-BTC' && ticker.trade_price >= 150000000) {
alerts.push({
type: 'PRICE',
message: `💰 비트코인 1억 5천만원 돌파!`,
});
}
return alerts;
}
export default {
async fetch(request, env, ctx) {
const markets = 'KRW-BTC,KRW-ETH,KRW-XRP,KRW-DOGE';
const response = await fetch(
`https://api.upbit.com/v1/ticker?markets=${markets}`
);
const tickers = await response.json();
// 모든 코인에 대해 알림 조건 체크
const allAlerts = [];
for (const ticker of tickers) {
const alerts = checkAlertConditions(ticker);
allAlerts.push(...alerts);
}
return new Response(JSON.stringify({
checked_at: new Date().toISOString(),
alerts: allAlerts,
prices: tickers.map(t => ({
market: t.market,
price: t.trade_price,
change_rate: (t.change_rate * 100).toFixed(2) + '%',
})),
}, null, 2), {
headers: { 'Content-Type': 'application/json' },
});
},
};
{
"checked_at": "2025-12-02T12:00:00.000Z",
"alerts": [
{
"type": "PUMP",
"message": "🚀 KRW-DOGE 급등! +7.35%"
}
],
"prices": [
{ "market": "KRW-BTC", "price": 139850000, "change_rate": "2.35%" },
{ "market": "KRW-ETH", "price": 4850000, "change_rate": "-1.20%" }
]
}
에러 처리 추가
API 호출이 실패할 수도 있으니 에러 처리도 해줘야 해요:
export default {
async fetch(request, env, ctx) {
try {
const markets = 'KRW-BTC,KRW-ETH';
const response = await fetch(
`https://api.upbit.com/v1/ticker?markets=${markets}`
);
if (!response.ok) {
throw new Error(`업비트 API 에러: ${response.status}`);
}
const tickers = await response.json();
// ... 나머지 로직
} catch (error) {
return new Response(JSON.stringify({
error: true,
message: error.message,
}), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
}
},
};
정리
이번 편에서 한 것:
- 업비트 마켓 목록 조회
- 현재가(ticker) 조회
- URL 파라미터로 코인 선택
- 가격 변동 감지 로직
- 에러 처리
다음 편에서는 이 데이터를 텔레그램으로 전송하고 스케줄러로 자동 실행되게 만든다. 진짜 알림봇이 완성된다.
운영자 실전 노트
실제 프로젝트 진행하며 겪은 문제
- 업비트 API 인증 오류 → Access Key, Secret Key 쌍 확인 및 서명 생성 정확도 검증
- 서명 생성 오류 → Query String 인코딩 방식과 JWT 생성 순서 주의
이 경험을 통해 알게 된 점
- 시세 조회 API는 인증 없이 사용 가능해 개발 초기 단계가 쉽다
- API 호출 제한(초당 10회)은 5분 간격 스케줄러면 충분하다