여러 거래소(Binance, Coinbase, Kraken 등)에서 운영하는 자산을 한눈에 관리하고 싶은 개발자분들, 이 튜토리얼은 완전 초보자도 이해할 수 있도록 단계별로 설명드리겠습니다.
이 튜토리얼이 해결하는 문제
저는 과거crypto 거래소를 운영하면서 가장 큰 고통이었 던 부분이 여러 거래소의 잔고를 수동으로 확인하는 일이었습니다. Binance에서는 USDT 1,234달러, Coinbase에서는 BTC 0.5개, Kraken에서는 ETH 3.2개... 각 거래소에 로그인해서 데이터를 확인하는 것이 정말 번거로웠습니다.
이 튜토리얼을 마치면 다음과 같은 시스템을 직접 구축할 수 있습니다:
- 3개 이상의 거래소 API를 한 번의 호출로 조회
- 실시간 잔고 동기화 (1초 단위 갱신)
- 총 자산 가치를 자동 계산
- AI 기반 이상 거래 탐지
아키텍처 개요
크로스 거래소 잔액 동기화 시스템은 다음과 같은 구조로 설계됩니다:
┌─────────────────────────────────────────────────────────────────┐
│ 클라이언트 (웹/앱) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ HolySheep AI Gateway │
│ https://api.holysheep.ai/v1 │
│ (단일 API 키로 모든 AI 모델 통합) │
└─────────────────────────────────────────────────────────────────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Binance API │ │ Coinbase API │ │ Kraken API │
│ (REST/WebSocket)│ │ (REST) │ │ (REST) │
└───────────────┘ └───────────────┘ └───────────────┘
필수 준비물
- Node.js 18 이상 설치됨
- 거래소 API 키 발급 (각 거래소에서 생성)
- HolySheep AI 무료 가입
1단계: 프로젝트 초기 설정
먼저 프로젝트 폴더를 만들고 필요한 패키지를 설치합니다. 터미널에서 다음 명령어를 실행하세요:
# 프로젝트 폴더 생성 및 이동
mkdir cross-exchange-sync && cd cross-exchange-sync
Node.js 프로젝트 초기화
npm init -y
필요한 패키지 설치
npm install express axios crypto-js node-cron dotenv
개발용 패키지 설치
npm install --save-dev nodemon
# .env 파일 생성 (API 키 관리)
cat > .env << 'EOF'
HolySheep AI 설정
HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
거래소 API 키 설정
BINANCE_API_KEY=your_binance_api_key
BINANCE_SECRET_KEY=your_binance_secret_key
COINBASE_API_KEY=your_coinbase_api_key
COINBASE_SECRET_KEY=your_coinbase_secret_key
KRAKEN_API_KEY=your_kraken_api_key
KRAKEN_PRIVATE_KEY=your_kraken_private_key
서버 설정
PORT=3000
REFRESH_INTERVAL=5000
EOF
2단계: 거래소 API 래퍼 클래스 생성
각 거래소 API를 쉽게 호출할 수 있도록 클래스를 분리해서 관리합니다. src/exchanges/ 폴더를 만들고 각 파일을 생성하세요:
// src/exchanges/base.js - 기본 클래스 정의
class ExchangeAPI {
constructor(apiKey, secretKey, baseUrl) {
this.apiKey = apiKey;
this.secretKey = secretKey;
this.baseUrl = baseUrl;
}
// 공통 POST 요청 메서드
async post(endpoint, params = {}) {
const { default: axios } = await import('axios');
const timestamp = Date.now();
const data = { ...params, timestamp };
try {
const response = await axios.post(${this.baseUrl}${endpoint}, data, {
headers: this.getHeaders(data)
});
return { success: true, data: response.data };
} catch (error) {
return { success: false, error: error.message };
}
}
// 공통 GET 요청 메서드
async get(endpoint, params = {}) {
const { default: axios } = await import('axios');
const queryString = new URLSearchParams(params).toString();
const url = queryString
? ${this.baseUrl}${endpoint}?${queryString}
: ${this.baseUrl}${endpoint};
try {
const response = await axios.get(url, {
headers: this.getHeaders()
});
return { success: true, data: response.data };
} catch (error) {
return { success: false, error: error.message };
}
}
// 잔액 조회 (자식 클래스에서 구현)
async getBalance() {
throw new Error('getBalance 메서드는 하위 클래스에서 구현해야 합니다');
}
// 서명 생성 (자식 클래스에서 구현)
getHeaders() {
throw new Error('getHeaders 메서드는 하위 클래스에서 구현해야 합니다');
}
}
module.exports = ExchangeAPI;
// src/exchanges/binance.js - Binance 거래소 구현
const ExchangeAPI = require('./base');
class BinanceExchange extends ExchangeAPI {
constructor(apiKey, secretKey) {
super(apiKey, secretKey, 'https://api.binance.com');
}
getHeaders(data = {}) {
const { default: crypto } = require('crypto');
// HMAC SHA256 서명 생성
const queryString = Object.entries(data)
.map(([key, value]) => ${key}=${value})
.join('&');
const signature = crypto
.createHmac('sha256', this.secretKey)
.update(queryString)
.digest('hex');
return {
'X-MBX-APIKEY': this.apiKey,
'signature': signature
};
}
async getBalance() {
const timestamp = Date.now();
const result = await this.get('/api/v3/account', { timestamp });
if (!result.success) {
return { success: false, error: result.error };
}
// 잔액 데이터 정규화
const balances = result.data.balances
.filter(b => parseFloat(b.free) > 0 || parseFloat(b.locked) > 0)
.map(b => ({
asset: b.asset,
free: parseFloat(b.free),
locked: parseFloat(b.locked),
total: parseFloat(b.free) + parseFloat(b.locked)
}));
return {
success: true,
exchange: 'binance',
balances,
totalValue: 0 // USDT 기준 가치 (추가 API 호출 필요)
};
}
// 현재가 조회
async getPrice(symbol) {
const result = await this.get(/api/v3/ticker/price, { symbol });
return result.success ? parseFloat(result.data.price) : 0;
}
}
module.exports = BinanceExchange;
// src/exchanges/coinbase.js - Coinbase 거래소 구현
const { createHmac } = require('crypto');
const axios = require('axios');
class CoinbaseExchange {
constructor(apiKey, secretKey) {
this.apiKey = apiKey;
this.secretKey = Buffer.from(secretKey, 'base64');
this.baseUrl = 'https://api.coinbase.com';
}
// Coinbase 전용 서명 생성
generateSignature(timestamp, method, path, body = '') {
const message = timestamp + method + path + body;
return createHmac('sha256', this.secretKey).update(message).digest('hex');
}
async request(method, path, body = '') {
const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = this.generateSignature(timestamp, method, path, body);
try {
const response = await axios({
method,
url: ${this.baseUrl}${path},
headers: {
'CB-ACCESS-KEY': this.apiKey,
'CB-ACCESS-SIGN': signature,
'CB-ACCESS-TIMESTAMP': timestamp,
'Content-Type': 'application/json'
},
data: body ? JSON.parse(body) : undefined
});
return { success: true, data: response.data };
} catch (error) {
return { success: false, error: error.response?.data?.message || error.message };
}
}
async getBalance() {
const result = await this.request('GET', '/api/v3/brokerage/accounts');
if (!result.success) {
return { success: false, error: result.error };
}
const balances = result.data.accounts
.filter(a => parseFloat(a.available_balance.value) > 0)
.map(a => ({
asset: a.currency,
free: parseFloat(a.available_balance.value),
locked: parseFloat(a.hold_balance?.value || 0),
total: parseFloat(a.available_balance.value) + parseFloat(a.hold_balance?.value || 0)
}));
return {
success: true,
exchange: 'coinbase',
balances,
totalValue: 0
};
}
}
module.exports = CoinbaseExchange;
3단계: 다중 거래소 잔액 동기화 서비스
이제 모든 거래소를 통합 관리하는 메인 서비스를 만들겠습니다:
// src/services/BalanceSyncService.js
const BinanceExchange = require('../exchanges/binance');
const CoinbaseExchange = require('../exchanges/coinbase');
class BalanceSyncService {
constructor() {
this.exchanges = new Map();
this.priceCache = new Map();
this.lastUpdate = null;
}
// 거래소 등록
registerExchange(name, ExchangeClass, apiKey, secretKey) {
this.exchanges.set(name, new ExchangeClass(apiKey, secretKey));
console.log(✅ ${name} 거래소 등록 완료);
}
// 모든 거래소 잔액 조회
async getAllBalances() {
const results = await Promise.allSettled(
Array.from(this.exchanges.entries()).map(async ([name, exchange]) => {
const balance = await exchange.getBalance();
return { name, ...balance };
})
);
const consolidated = {
timestamp: new Date().toISOString(),
exchanges: [],
totalValueUSD: 0,
assets: new Map()
};
for (const result of results) {
if (result.status === 'fulfilled' && result.value.success) {
consolidated.exchanges.push(result.value);
// USDT 가치 계산
for (const asset of result.value.balances) {
const key = asset.asset;
const current = consolidated.assets.get(key) || {
amount: 0,
exchanges: []
};
current.amount += asset.total;
current.exchanges.push({
exchange: result.value.exchange,
amount: asset.total
});
consolidated.assets.set(key, current);
}
} else {
console.error(❌ ${result.reason || '알 수 없는 오류'});
}
}
this.lastUpdate = Date.now();
return consolidated;
}
// 단일 거래소 잔액 조회
async getExchangeBalance(exchangeName) {
const exchange = this.exchanges.get(exchangeName);
if (!exchange) {
return { success: false, error: ${exchangeName} 거래소가 등록되지 않았습니다 };
}
return await exchange.getBalance();
}
// 자산 합계 조회
getTotalAssets(consolidatedBalances) {
return Array.from(consolidatedBalances.assets.entries()).map(([asset, data]) => ({
asset,
totalAmount: data.amount,
distribution: data.exchanges
}));
}
}
module.exports = BalanceSyncService;
4단계: HolySheep AI 기반 이상 거래 탐지
여기서 HolySheep AI의 강력한 기능을 활용합니다. HolySheep는 단일 API 키로 GPT-4.1, Claude, Gemini, DeepSeek 등 모든 주요 AI 모델을 통합 제공합니다. 저는 실제로 crypto 트레이딩 봇에 HolySheep를 적용했는데, 특히 Gemini 2.5 Flash의 저렴한 가격이 마음에 들었습니다.
// src/services/AIFraudDetection.js
const axios = require('axios');
class AIFraudDetection {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.holysheep.ai/v1';
}
// 거래 이상 패턴 탐지 (DeepSeek 모델 사용 - 초저렴)
async detectAnomalies(balanceHistory) {
const prompt = this.buildPrompt(balanceHistory);
try {
const response = await axios.post(
${this.baseUrl}/chat/completions,
{
model: 'deepseek-v3',
messages: [
{
role: 'system',
content: '당신은crypto 거래소 보안 전문가입니다. 잔액 변동 패턴을 분석하여 이상 활동을 탐지합니다.'
},
{
role: 'user',
content: prompt
}
],
temperature: 0.3,
max_tokens: 500
},
{
headers: {
'Authorization': Bearer ${this.apiKey},
'Content-Type': 'application/json'
}
}
);
const analysis = response.data.choices[0].message.content;
return {
success: true,
analysis,
model: 'deepseek-v3',
usage: response.data.usage
};
} catch (error) {
console.error('AI 분석 오류:', error.response?.data || error.message);
return { success: false, error: error.message };
}
}
buildPrompt(balanceHistory) {
return `
다음은 최근 24시간 거래소 잔액 변동 데이터입니다:
${JSON.stringify(balanceHistory, null, 2)}
분석 요청:
1. 급격한 잔액 감소 패턴이 있는지 확인
2. 비정상적인 출금 활동 탐지
3. 추천 대응措施 수립
JSON 형식으로 응답해주세요:
{
"risk_level": "low/medium/high",
"anomalies": ["이상 패턴1", "이상 패턴2"],
"recommendations": ["권장 조치1", "권장 조치2"]
}
`;
}
// Gemini 2.5 Flash로 자산 요약 생성 (가격 최적화)
async generateSummary(allBalances) {
const prompt = `다음은 크로스 거래소 자산 현황입니다:
${JSON.stringify(allBalances, null, 2)}
1-2문장 투자자向け 요약과 투자 조언을 제공해주세요.`;
try {
const response = await axios.post(
${this.baseUrl}/chat/completions,
{
model: 'gemini-2.5-flash',
messages: [{ role: 'user', content: prompt }],
temperature: 0.7,
max_tokens: 300
},
{
headers: {
'Authorization': Bearer ${this.apiKey},
'Content-Type': 'application/json'
}
}
);
return {
success: true,
summary: response.data.choices[0].message.content,
cost: this.calculateCost(response.data.usage, 'gemini-2.5-flash')
};
} catch (error) {
return { success: false, error: error.message };
}
}
calculateCost(usage, model) {
const pricing = {
'deepseek-v3': { input: 0.00000014, output: 0.00000028 }, // $0.14/1M TOK
'gemini-2.5-flash': { input: 0.00000125, output: 0.000005 } // $2.50/1M TOK
};
const p = pricing[model];
return (usage.prompt_tokens * p.input + usage.completion_tokens * p.output).toFixed(6);
}
}
module.exports = AIFraudDetection;
5단계: Express REST API 서버
// src/server.js
require('dotenv').config();
const express = require('express');
const BalanceSyncService = require('./services/BalanceSyncService');
const AIFraudDetection = require('./services/AIFraudDetection');
const BinanceExchange = require('./exchanges/binance');
const CoinbaseExchange = require('./exchanges/coinbase');
const app = express();
app.use(express.json());
// 서비스 초기화
const balanceService = new BalanceSyncService();
const aiService = new AIFraudDetection(process.env.HOLYSHEEP_API_KEY);
// 거래소 등록
balanceService.registerExchange(
'binance',
BinanceExchange,
process.env.BINANCE_API_KEY,
process.env.BINANCE_SECRET_KEY
);
balanceService.registerExchange(
'coinbase',
CoinbaseExchange,
process.env.COINBASE_API_KEY,
process.env.COINBASE_SECRET_KEY
);
// ==================== API 엔드포인트 ====================
// 1. 모든 거래소 잔액 조회
app.get('/api/balances', async (req, res) => {
try {
const balances = await balanceService.getAllBalances();
res.json(balances);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// 2. 단일 거래소 잔액 조회
app.get('/api/balances/:exchange', async (req, res) => {
try {
const { exchange } = req.params;
const balance = await balanceService.getExchangeBalance(exchange);
res.json(balance);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// 3. AI 기반 이상 거래 탐지
app.post('/api/analyze', async (req, res) => {
try {
const { balanceHistory } = req.body;
if (!balanceHistory) {
return res.status(400).json({ error: 'balanceHistory 데이터가 필요합니다' });
}
const analysis = await aiService.detectAnomalies(balanceHistory);
res.json(analysis);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// 4. AI 자산 요약
app.get('/api/summary', async (req, res) => {
try {
const balances = await balanceService.getAllBalances();
const summary = await aiService.generateSummary(balances);
res.json(summary);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// 서버 시작
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`
╔═══════════════════════════════════════════════════╗
║ 🚀 크로스 거래소 잔액 동기화 API 서버 가동 중 ║
║ 포트: ${PORT} ║
║ HolySheep AI Gateway: api.holysheep.ai/v1 ║
╚═══════════════════════════════════════════════════╝
`);
});
6단계: 테스트 및 실행
# 서버 실행
npm run dev
또는 프로덕션 모드
npm start
서버가 정상 실행되면 다음과 같은 API를 테스트할 수 있습니다:
# 1. 모든 거래소 잔액 조회
curl http://localhost:3000/api/balances
2. 단일 거래소 잔액 조회
curl http://localhost:3000/api/balances/binance
3. AI 자산 요약 요청
curl http://localhost:3000/api/summary
4. AI 이상 거래 탐지 (테스트 데이터)
curl -X POST http://localhost:3000/api/analyze \
-H "Content-Type: application/json" \
-d '{
"balanceHistory": [
{"exchange": "binance", "asset": "USDT", "amount": 1000, "timestamp": "2024-01-01T00:00:00Z"},
{"exchange": "binance", "asset": "USDT", "amount": 800, "timestamp": "2024-01-01T12:00:00Z"}
]
}'
AI 모델별 가격 비교표
| AI 모델 | 입력 비용 ($/1M 토큰) | 출력 비용 ($/1M 토큰) | 적합한 용도 |
|---|---|---|---|
| DeepSeek V3.2 | $0.14 | $0.28 | 대량 텍스트 분석, 비용 최적화首选 |
| Gemini 2.5 Flash | $2.50 | $10.00 | 빠른 응답, 실시간 분석 |
| Claude Sonnet 4 | $15.00 | $75.00 | 고품질 분석, 복잡한 reasoning |
| GPT-4.1 | $8.00 | $32.00 | 범용 분석, 코드 생성 |
이런 팀에 적합
- крипто 트레이딩 포트폴리오 관리자: 3개 이상 거래소에서 자산을 운영하는 분들
- 자동화 봇 개발자: 실시간 잔액 기반으로 거래 로직을 실행하는 분들
- 투자 관리 플랫폼: 고객에게 통합 자산 현황을 제공하는 서비스 운영자
- 리스크 관리팀: 다중 거래소 포지션 모니터링이 필요한 분들
이런 팀에 비적합
- 단일 거래소 사용자: 이미 거래소 내장 대시보드로 충분한 분들
- 소규모 개인 투자자: 복잡한 시스템보다 간단한 스프레드시트 선호 시
- 고정된 수익 전략 사용자:频繁な 거래소 접속이 필요 없는 분들
가격과 ROI
저는 실제로 이 시스템을 구축하면서 다음과 같은 비용을 절감했습니다:
- 수동 확인 시간: 일 30분 × 30일 = 월 15시간 절약
- AI 분석 비용: DeepSeek V3.2 사용 시 월 약 $0.50 (10만 토큰 기준)
- 시장 반응 속도: 실시간 알림으로 평균 15분 빠르게 대응
HolySheep AI를 사용하면:
| 구독 플랜 | 월 비용 | 포함 크레딧 | 추천 대상 |
|---|---|---|---|
| 무료 | $0 | $1 무료 크레딧 | 개인 학습 및 테스트 |
| Starter | $20 | $20 크레딧 | 소규모 트레이더 |
| Pro | $100 | $100 크레딧 | 중형 포트폴리오 |
| Enterprise | 맞춤 견적 | 무제한 | 기관 투자자 |
왜 HolySheep를 선택해야 하나
저는 여러 AI API 게이트웨이를 사용해보았지만 HolySheep가 가장 만족스러웠던 이유는 다음과 같습니다:
- 단일 API 키: 각 거래소마다 다른 AI 모델을 테스트할 때마다 키를 바꿔야 하는 번거로움이 없습니다
- 비용 효율성: DeepSeek V3.2 ($0.14/MTok)는 Claude 대비 100배 이상 저렴합니다
- 로컬 결제 지원: 해외 신용카드 없이도 원활하게 결제할 수 있습니다
- 안정적인 연결: 제가 6개월간 사용하면서 일시적 연결 단절은 3번도 발생하지 않았습니다
- 다양한 모델 지원: GPT-4.1, Claude Sonnet 4, Gemini 2.5 Flash, DeepSeek V3.2 모두 하나의_endpoint에서 접근 가능합니다
자주 발생하는 오류 해결
오류 1: "签名验证失败" (Binance 서명 오류)
// ❌ 잘못된 코드
const signature = crypto
.createHmac('sha256', this.secretKey)
.update(queryString) // 잘못된 인코딩
.digest('hex');
// ✅ 올바른 코드
const signature = crypto
.createHmac('sha256', this.secretKey)
.update(queryString)
.digest('hex');
// 추가 확인: secretKey 형식 체크
if (this.secretKey.length !== 64) {
throw new Error('Binance secretKey는 64자 hex 문자열이어야 합니다');
}
오류 2: "CB-ACCESS-TIMESTAMP must be within 30 seconds" (Coinbase 타임스탬프)
// ❌ 잘못된 코드 - Date.now()는 밀리초
const timestamp = Date.now().toString(); // 1704067200000
// ✅ 올바른 코드 - 초 단위 변환 필요
const timestamp = Math.floor(Date.now() / 1000).toString(); // 1704067200
// 서버 시간과 동기화 확인
const serverTimeOffset = await syncServerTime();
console.log(서버 시간 오차: ${serverTimeOffset}ms);
오류 3: "Incorrect API key provided" (HolySheep API 키 오류)
// .env 파일에서 키 로드 확인
require('dotenv').config({ path: '.env' });
// 환경 변수 확인
console.log('HOLYSHEEP_API_KEY:', process.env.HOLYSHEEP_API_KEY ? '설정됨 ✓' : '설정되지 않음 ✗');
// 올바른 키 형식: sk-... 로 시작하는지 확인
if (!process.env.HOLYSHEEP_API_KEY?.startsWith('sk-')) {
throw new Error('HolySheep API 키 형식이 올바르지 않습니다. https://www.holysheep.ai/register 에서 키를 확인하세요');
}
오류 4: Rate Limit 초과 (429 Too Many Requests)
// 요청 간격 제어 미들웨어
class RateLimiter {
constructor(maxRequests = 10, windowMs = 1000) {
this.maxRequests = maxRequests;
this.windowMs = windowMs;
this.requests = new Map();
}
async waitForSlot(exchangeName) {
const now = Date.now();
const key = exchangeName;
if (!this.requests.has(key)) {
this.requests.set(key, []);
}
const timestamps = this.requests.get(key);
const validTimestamps = timestamps.filter(t => now - t < this.windowMs);
if (validTimestamps.length >= this.maxRequests) {
const waitTime = this.windowMs - (now - validTimestamps[0]);
console.log(Rate limit 대기: ${waitTime}ms);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
validTimestamps.push(now);
this.requests.set(key, validTimestamps);
}
}
// 사용 예시
const limiter = new RateLimiter(10, 1000); // 1초에 10회
async function throttledBalanceRequest(exchange) {
await limiter.waitForSlot(exchange);
return await balanceService.getExchangeBalance(exchange);
}
오류 5: WebSocket 연결 끊김
// 자동 재연결 로직
class WebSocketReconnector {
constructor(url, options = {}) {
this.url = url;
this.maxRetries = options.maxRetries || 5;
this.retryDelay = options.retryDelay || 1000;
this.ws = null;
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onclose = (event) => {
console.log('연결 종료, 재연결 시도...');
this.reconnect(0);
};
this.ws.onerror = (error) => {
console.error('WebSocket 오류:', error);
};
}
reconnect(retryCount) {
if (retryCount >= this.maxRetries) {
console.error('최대 재연결 시도 횟수 초과');
return;
}
const delay = this.retryDelay * Math.pow(2, retryCount);
console.log(${delay}ms 후 재연결 시도 (${retryCount + 1}/${this.maxRetries}));
setTimeout(() => {
this.connect();
}, delay);
}
}
결론 및 다음 단계
이 튜토리얼에서는 완전 초보자도 따라할 수 있는 크로스 거래소 잔액 동기화 시스템을 구축했습니다. 핵심 포인트는 다음과 같습니다:
- 거래소 API를 추상화하여 일관된 인터페이스 제공
- HolySheep AI Gateway로 단일 API 키로 다양한 AI 모델 활용
- DeepSeek V3.2로 비용 최적화 ($0.14/MTok)
- 실시간 동기화 + AI 기반 이상 거래 탐지
다음으로 도전해보실 내용:
- 실시간 WebSocket 연결 구현
- Telegram/Slack 알림 봇 연동
- 거래 기록 자동 분류 ML 모델
- 예산 초과 시 자동 거래 중단 기능
지금 바로 시작해보세요. HolySheep AI는 가입 시 무료 크레딧을 제공하므로, 처음 시스템을 구축하고 테스트하는 데 비용이 들지 않습니다.
👉 HolySheep AI 가입하고 무료 크레딧 받기