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] socket 분리 로직 수정 #91

Merged
merged 5 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion BE/src/stock/index/stock-index.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@ import { SocketModule } from '../../websocket/socket.module';
imports: [KoreaInvestmentModule, SocketModule],
controllers: [StockIndexController],
providers: [StockIndexService],
exports: [StockIndexService],
})
export class StockIndexModule {}
8 changes: 4 additions & 4 deletions BE/src/stock/order/stock-order.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { RequestInterface } from './interface/request.interface';
@Controller('/api/stocks/trade')
@ApiTags('주식 매수/매도 API')
export class StockOrderController {
constructor(private readonly stockTradeService: StockOrderService) {}
constructor(private readonly stockOrderService: StockOrderService) {}
Copy link
Collaborator

@uuuo3o uuuo3o Nov 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 이거 socket 분리 로직 수정 커밋 맞나요?? 소켓이랑 상관 없어보이는 코드 수정 같아 보이는데 커밋 나눠서 작성해주시면 더 좋을 거 같아요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

에고 그렇네요ㅜ 다음부터 유의해서 커밋 올리겠습니당


@Post('/buy')
@ApiBearerAuth()
Expand All @@ -39,7 +39,7 @@ export class StockOrderController {
@Req() request: RequestInterface,
@Body(ValidationPipe) stockOrderRequest: StockOrderRequestDto,
) {
await this.stockTradeService.buy(request.user.id, stockOrderRequest);
await this.stockOrderService.buy(request.user.id, stockOrderRequest);
}

@Post('/sell')
Expand All @@ -57,7 +57,7 @@ export class StockOrderController {
@Req() request: RequestInterface,
@Body(ValidationPipe) stockOrderRequest: StockOrderRequestDto,
) {
await this.stockTradeService.sell(request.user.id, stockOrderRequest);
await this.stockOrderService.sell(request.user.id, stockOrderRequest);
}

@Delete('/:order_id')
Expand All @@ -75,6 +75,6 @@ export class StockOrderController {
@Req() request: RequestInterface,
@Param('order_id') orderId: number,
) {
await this.stockTradeService.cancel(request.user.id, orderId);
await this.stockOrderService.cancel(request.user.id, orderId);
}
}
45 changes: 30 additions & 15 deletions BE/src/websocket/base-socket.service.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
import { WebSocket } from 'ws';
import { Injectable, OnModuleInit } from '@nestjs/common';
import { SocketGateway } from './socket.gateway';
import {
Injectable,
InternalServerErrorException,
OnModuleInit,
} from '@nestjs/common';
import { SocketTokenService } from './socket-token.service';

@Injectable()
export abstract class BaseSocketService implements OnModuleInit {
protected socket: WebSocket;
protected socketConnectionKey: string;
export class BaseSocketService implements OnModuleInit {
private socket: WebSocket;
private socketConnectionKey: string;
private socketOpenHandlers: (() => void | Promise<void>)[] = [];
private socketDataHandlers: {
[key: string]: (data) => void;
} = {};

constructor(
protected readonly socketTokenService: SocketTokenService,
protected readonly socketGateway: SocketGateway,
) {}
constructor(private readonly socketTokenService: SocketTokenService) {}

async onModuleInit() {
this.socketConnectionKey =
await this.socketTokenService.getSocketConnectionKey();
this.socket = new WebSocket(process.env.KOREA_INVESTMENT_SOCKET_URL);

this.socket.onopen = () => {
this.handleSocketOpen();
Promise.all(
this.socketOpenHandlers.map(async (socketOpenHandler) => {
await socketOpenHandler();
}),
).catch(() => {
throw new InternalServerErrorException();
});
};

this.socket.onmessage = (event) => {
Expand All @@ -30,14 +40,11 @@ export abstract class BaseSocketService implements OnModuleInit {
if (data.length < 2) return;

const dataList = data[3].split('^');
this.handleSocketData(dataList);
this.socketDataHandlers[data[1]](dataList);
};
}

protected abstract handleSocketOpen(): void;
protected abstract handleSocketData(dataList): void;

protected registerCode(trId: string, trKey: string) {
registerCode(trId: string, trKey: string) {
this.socket.send(
JSON.stringify({
header: {
Expand All @@ -55,4 +62,12 @@ export abstract class BaseSocketService implements OnModuleInit {
}),
);
}

registerSocketOpenHandler(handler: () => void | Promise<void>) {
this.socketOpenHandlers.push(handler);
}

registerSocketDataHandler(tradeCode: string, handler: (data) => void) {
this.socketDataHandlers[tradeCode] = handler;
}
}
8 changes: 7 additions & 1 deletion BE/src/websocket/socket.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ import { Module } from '@nestjs/common';
import { StockIndexSocketService } from './stock-index-socket.service';
import { SocketGateway } from './socket.gateway';
import { SocketTokenService } from './socket-token.service';
import { BaseSocketService } from './base-socket.service';

@Module({
imports: [],
controllers: [],
providers: [SocketTokenService, StockIndexSocketService, SocketGateway],
providers: [
SocketTokenService,
StockIndexSocketService,
SocketGateway,
BaseSocketService,
],
exports: [SocketGateway],
})
export class SocketModule {}
42 changes: 26 additions & 16 deletions BE/src/websocket/stock-index-socket.service.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
import { Injectable } from '@nestjs/common';
import { StockIndexValueElementDto } from '../stock/index/dto/stock-index-value-element.dto';
import { BaseSocketService } from './base-socket.service';
import { SocketGateway } from './socket.gateway';

@Injectable()
export class StockIndexSocketService extends BaseSocketService {
export class StockIndexSocketService {
private TR_ID = 'H0UPCNT0';
private STOCK_CODE = {
'0001': 'KOSPI',
'1001': 'KOSDAQ',
'2001': 'KOSPI200',
'3003': 'KSQ150',
};

protected handleSocketOpen() {
this.registerCode('H0UPCNT0', '0001'); // 코스피
this.registerCode('H0UPCNT0', '1001'); // 코스닥
this.registerCode('H0UPCNT0', '2001'); // 코스피200
this.registerCode('H0UPCNT0', '3003'); // KSQ150
}
constructor(
private readonly socketGateway: SocketGateway,
private readonly baseSocketService: BaseSocketService,
) {
baseSocketService.registerSocketOpenHandler(() => {
this.baseSocketService.registerCode(this.TR_ID, '0001'); // 코스피
this.baseSocketService.registerCode(this.TR_ID, '1001'); // 코스닥
this.baseSocketService.registerCode(this.TR_ID, '2001'); // 코스피200
this.baseSocketService.registerCode(this.TR_ID, '3003'); // KSQ150
});

protected handleSocketData(dataList: string[]) {
this.socketGateway.sendStockIndexValueToClient(
this.STOCK_CODE[dataList[0]],
new StockIndexValueElementDto(
dataList[2],
dataList[4],
dataList[9],
dataList[3],
),
baseSocketService.registerSocketDataHandler(
this.TR_ID,
(data: string[]) => {
this.socketGateway.sendStockIndexValueToClient(
this.STOCK_CODE[data[0]],
new StockIndexValueElementDto(
data[2], // 주가 지수
data[4], // 전일 대비 등락
data[9], // 전일 대비 등락률
data[3], // 부호
),
);
},
);
}
}
Loading