Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] feature #14, #46 - SSE적용, DB repository 생성 #47

Merged
merged 24 commits into from
Nov 11, 2024
Merged
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5bf9bca
feat: upbit api websocket 연결 및 sse 설정
SeongHyeon0409 Nov 9, 2024
7d9274c
Merge branch 'dev-be' of https://github.com/boostcampwm-2024/web03-Co…
SeongHyeon0409 Nov 11, 2024
ba0e1a6
feat: 코인 정보 upbit api로 받아오기
SeongHyeon0409 Nov 11, 2024
f1b0899
feat: sse service 분리
SeongHyeon0409 Nov 11, 2024
78d154c
feat: coinTickerDTO
SeongHyeon0409 Nov 11, 2024
6f58c58
chore: 배포용 commit
SeongHyeon0409 Nov 11, 2024
8593280
feat : erd에 따른 module생성
SeongHyeon0409 Nov 11, 2024
6e15eaa
feat: SSE 구조 리팩토링
SeongHyeon0409 Nov 11, 2024
030b784
chore: 배포 설정 수정
SeongHyeon0409 Nov 11, 2024
3e6df26
feat: erd table entity 구현
SeongHyeon0409 Nov 11, 2024
ada8814
chore: 불필요한 파일삭제, 배포yml 수정
SeongHyeon0409 Nov 11, 2024
1cbd9ea
feat: https 테스트
SeungGwan123 Nov 8, 2024
8b5a6b1
feat: healthmodule추가
SeungGwan123 Nov 8, 2024
361d205
feat: cicd branch 수정
SeungGwan123 Nov 11, 2024
ca044c2
feat: 코인 정보 upbit api로 받아오기
SeongHyeon0409 Nov 11, 2024
83b7fa8
feat: sse service 분리
SeongHyeon0409 Nov 11, 2024
daa6e2e
feat: coinTickerDTO
SeongHyeon0409 Nov 11, 2024
3a91264
chore: 배포용 commit
SeongHyeon0409 Nov 11, 2024
8b704b1
feat : erd에 따른 module생성
SeongHyeon0409 Nov 11, 2024
4e95102
feat: SSE 구조 리팩토링
SeongHyeon0409 Nov 11, 2024
dc255ce
chore: 배포 설정 수정
SeongHyeon0409 Nov 11, 2024
bce4c07
feat: erd table entity 구현
SeongHyeon0409 Nov 11, 2024
d9fd208
chore: 불필요한 파일삭제, 배포yml 수정
SeongHyeon0409 Nov 11, 2024
aad5887
Merge branch 'feature-be-#46' of https://github.com/boostcampwm-2024/…
SeongHyeon0409 Nov 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: 코인 정보 upbit api로 받아오기
Co-authored-by: 이승관 <[email protected]>
SeongHyeon0409 and SeungGwan123 committed Nov 11, 2024
commit ca044c2d9aa5c3472fb0808f6677bc4129aa3575
3 changes: 3 additions & 0 deletions dockerfile-client
Original file line number Diff line number Diff line change
@@ -7,5 +7,8 @@ RUN yarn build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html

COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
27 changes: 27 additions & 0 deletions nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#nginx.conf
server {
listen 80;
server_name localhost;

# 정적 파일 서빙 설정
location / {
root /usr/share/nginx/html;
try_files $uri /index.html; # SPA(싱글 페이지 애플리케이션) 라우팅
}

# SSE 요청을 처리하는 프록시 설정 예시
location /sse {
proxy_pass http://backend_server:3000; # SSE 요청을 백엔드 서버로 프록시
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# SSE 스트리밍을 위해 버퍼링 비활성화
proxy_buffering off;

# SSE 연결을 오랫동안 유지할 수 있도록 타임아웃 설정
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -15,6 +15,9 @@
"typescript": "5.4.3"
},
"dependencies": {
"@floating-ui/dom": "^1.6.12"
"@floating-ui/dom": "^1.6.12",
"@nestjs/platform-socket.io": "^10.4.7",
"@nestjs/websockets": "^10.4.7",
"ws": "^8.18.0"
}
}
4 changes: 4 additions & 0 deletions packages/server/package.json
Original file line number Diff line number Diff line change
@@ -20,10 +20,13 @@
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/axios": "^3.1.2",
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/platform-socket.io": "^10.4.7",
"@nestjs/typeorm": "9.0.0",
"@nestjs/websockets": "^10.4.7",
"axios": "^1.7.7",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
@@ -48,6 +51,7 @@
"@types/jest": "^29.5.2",
"@types/js-yaml": "^4",
"@types/node": "^20.3.1",
"@types/socket.io": "^3.0.2",
"@types/supertest": "^6.0.0",
"@types/ws": "^8.5.13",
"@typescript-eslint/eslint-plugin": "^8.0.0",
15 changes: 15 additions & 0 deletions packages/server/src/upbit/coin-list.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';

@Injectable()
export class CoinListService {
constructor(private readonly httpService: HttpService) {}

async getCoinList() {
const response = await firstValueFrom(
this.httpService.get('https://api.upbit.com/v1/market/all?is_details=true')
);
return response.data;
}
}
17 changes: 17 additions & 0 deletions packages/server/src/upbit/types/market.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export type Market = 'KRW' | 'BTC' | 'USDT';

type MarketEvent = {
CONCENTRATION_OF_SMALL_ACCOUNTS: boolean;
DEPOSIT_AMOUNT_SOARING: boolean;
GLOBAL_PRICE_DIFFERENCES: boolean;
PRICE_FLUCTUATIONS: boolean;
TRADING_VOLUME_SOARING: boolean;
};

export type MarketData = {
market: string;
korean_name: string;
english_name: string;
market_warning?: string;
market_event: { warning: boolean; caution: MarketEvent };
};
40 changes: 40 additions & 0 deletions packages/server/src/upbit/types/ticker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
type CoinTicker = {
type: string;
code: string;
opening_price: number;
high_price: number;
low_price: number;
trade_price: number;
prev_closing_price: number;
acc_trade_price: number;
change: 'RISE' | 'FALL' | 'EVEN';
change_price: number;
signed_change_price: number;
change_rate: number;
signed_change_rate: number;
ask_bid: 'ASK' | 'BID';
trade_volume: number;
acc_trade_volume: number;
trade_date: string;
trade_time: string;
trade_timestamp: number;
acc_ask_volume: number;
acc_bid_volume: number;
highest_52_week_price: number;
highest_52_week_date: string;
lowest_52_week_price: number;
lowest_52_week_date: string;
market_state: 'ACTIVE' | 'SUSPENDED' | 'DELISTED';
is_trading_suspended: boolean;
delisting_date: string | null;
market_warning: 'NONE' | 'CAUTION';
timestamp: number;
acc_trade_price_24h: number;
acc_trade_volume_24h: number;
stream_type: 'REALTIME' | 'SNAPSHOT';
};

export type SocketDataType = {
[key: string]: CoinTicker; // 또는
// [market: string]: CoinTicker;
}
11 changes: 8 additions & 3 deletions packages/server/src/upbit/upbit.controller.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { Controller, Sse } from '@nestjs/common';
import { UpbitService } from './upbit.service';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Observable, Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';

@Controller('upbit')
export class UpbitController {

private destroy$ = new Subject<void>();

constructor(private readonly upbitService: UpbitService) {}

@Sse('price-updates')
priceUpdates(): Observable<MessageEvent> {
return this.upbitService.getPriceUpdatesStream().pipe(
return this.upbitService.getPriceUpdatesStream()
.pipe(
takeUntil(this.destroy$),
map((data) => {
// MessageEvent 타입에 맞게 필요한 속성 추가
return new MessageEvent('price-update', {
5 changes: 4 additions & 1 deletion packages/server/src/upbit/upbit.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Module } from '@nestjs/common';
import { UpbitService } from './upbit.service';
import { UpbitController } from './upbit.controller';
import { CoinListService } from './coin-list.service'
import { HttpModule } from '@nestjs/axios';

@Module({
providers: [UpbitService],
imports: [HttpModule],
providers: [UpbitService, CoinListService],
controllers: [UpbitController]
})
export class UpbitModule {}
12 changes: 8 additions & 4 deletions packages/server/src/upbit/upbit.service.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
import { Injectable, OnModuleInit } from '@nestjs/common';
import { Subject } from 'rxjs';
import * as WebSocket from 'ws';
import { CoinListService } from './coin-list.service';

@Injectable()
export class UpbitService implements OnModuleInit {
private ws: WebSocket;
private priceUpdates$: Subject<any> = new Subject(); // SSE로 전달할 스트림 생성
private priceUpdates$: Subject<any> = new Subject(); // SSE로 전달할 스트림 생성

constructor(private readonly coinListService: CoinListService) {};

onModuleInit() {
this.connectWebSocket();
}

private connectWebSocket() {
private async connectWebSocket() {
const coin_list = await this.coinListService.getCoinList()
this.ws = new WebSocket('wss://api.upbit.com/websocket/v1');

this.ws.on('open', () => {
console.log('WebSocket 연결 성공');
// 구독할 마켓 설정
const subscribeMessage = JSON.stringify([
{ ticket: 'test' },
{ type: 'ticker', codes: ['KRW-BTC', 'KRW-ETH'] }, // 원하는 코인 추가
{ type: 'ticker', codes: coin_list.map(coin=>coin.market) }, // 원하는 코인 추가
]);
this.ws.send(subscribeMessage);
});

this.ws.on('message', (data) => {
//TODO: upbitTicker 타입으로 변경
//TODO: upbitTickerDto 타입으로 변경
const message = JSON.parse(data.toString());
this.priceUpdates$.next(message); // SSE로 전달하기 위해 데이터 방출
});
273 changes: 259 additions & 14 deletions yarn.lock

Large diffs are not rendered by default.