-
Notifications
You must be signed in to change notification settings - Fork 3
๐ฆ ๋ค์ค ์ ์ ๋์์ฑ ์ ์ด โ ์ฑ๊ธํค, ๋ฎคํ ์ค
sunghwki edited this page Dec 4, 2024
·
3 revisions
๋ถ์ผ | ์์ฑ์ | ์์ฑ์ผ |
---|---|---|
BE | ๊น์ฑํ | 24๋ 12์ 02์ผ |
- ์ฃผ์ถค์ฃผ์ถค ์๋น์ค๋ ํ๊ตญํฌ์์ฆ๊ถ์ ์น์์ผ์ ์ด์ฉํด ์ ์ ์๊ฒ ์ฃผ๊ฐ ์ ๋ณด์ ๊ฐ์ ์ค์๊ฐ ์ ๋ณด๋ฅผ ์๋นํ๋ค.
- ํ๋์ ๊ณ์ข๋ ์น์์ผ์ ํ๋๋ฅผ ๊ฐ์ง ์ ์๊ณ , ์น์์ผ์ ๋ฐํ์ผ๋ก ์ด 41๊ฐ์ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ ์๋ค.
- ํ์ฌ ํ๋ณด๋ ๊ณ์ข๋ 4๊ฐ๋ก ์ด 164๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ์ฃผ์๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ ์๋ค.
graph
A[class LiveData] -. inject .-> B[class Stock]
- ํ์ฌ
stock.gateway.ts
์์๋livedata
๋ฅผ ์์กดํ๋ ํ์์ผ๋ก ๋์ด ์๊ณ ,LiveData
์ subscribe, unsubscribe์ ์ฌ์ฉํด ์น์์ผ ๊ตฌ๋ ๊ณผ ๊ตฌ๋ ํด์ ๋ฅผ ๊ด๋ฆฌํ๊ณ ์๋ค.
//stock.gateway
@SubscribeMessage('connectStock')
async handleConnectStock(
@MessageBody() stockId: string,
@ConnectedSocket() client: Socket,
) {
client.join(stockId);
const connectedSockets = await this.server.in(stockId).fetchSockets();
if (connectedSockets.length > 0 && !this.liveData.isSubscribe(stockId)) {
this.liveData.subscribe(stockId);
}
client.emit('connectionSuccess', {
message: `Successfully connected to stock room: ${stockId}`,
stockId,
});
}
async handleDisconnectStock(
@MessageBody() stockId: string,
@ConnectedSocket() client: Socket,
) {
client.leave(stockId);
const connectedSockets = await this.server.in(stockId).fetchSockets();
if (connectedSockets.length === 0) {
this.liveData.unsubscribe(stockId);
}
client.emit('disconnectionSuccess', {
message: `Successfully disconnected to stock room: ${stockId}`,
stockId,
});
}
- ํด๋น ๋ฌธ์ ๋ ๋ง์ ์ฌ์ฉ์๊ฐ ๋ฐฉ์ ์ฐธ์ฌํ๊ณ , ๋๊ฐ๋ ๊ณผ์ ์์ ๋ฐ์ํ ์ ์๋ค.
- ๋ง์ฝ, ๋ง์ ์ฌ์ฉ์๊ฐ ๋ฐฉ์ ๋์์ ์ฐธ์ฌํ๋ฉด
livedata.subscribe
๊ฐ ๋์์ ๋ฐ์ํด์ ์ํ์ง ์๋ ์ฌ๋ฌ๊ฐ์ subscribe๊ฐ ๋ฐ์ํ ์ ์๋ค. - ์ ์ ๊ฐ ๋๊ฐ๋ฉด์ ์๊ฐ์ ์ผ๋ก ์ ์ ์๊ฐ 0๋ช ์ด ๋๋ฉด์ subscribe๊ฐ ์์ด์ง ์ ์๊ณ , ์ด๋ด ๊ฒฝ์ฐ ์ ์ ๊ฐ ์กด์ฌํ๋ ๋ฐ ์ฃผ์์ ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ ์๋ ๋ฌธ์ ๊ฐ ์๋ค.
- ๋ง์ฝ, ๋ง์ ์ฌ์ฉ์๊ฐ ๋ฐฉ์ ๋์์ ์ฐธ์ฌํ๋ฉด
- nestjs์ ์ผ๋ก ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ ๊ฒ์ํ์ผ๋(interceptor ๋ฑ) ๋น์ฆ๋์ค ๋ก์ง์๋ ์ด์ธ๋ฆฌ์ง ์๋ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
- ์ฃผ์ ํ์ด์ง์ ๋ค์ด์์ ๋ ์์ฒญ์ ๊ฑฐ๋ถํ๋ ๊ฒ์ด ์๋ ๋ชฉ์ ๋ฐ์ดํฐ๋ผ๋ ๋ณด์ฌ์ผ ํ๊ณ , ๋ฐ๋ผ์ mutex๋ฅผ ์ด์ฉํ ๋์์ฑ ์ ์ด๊ฐ ๋ ํฉ๋นํ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
-
nodejs
์์ ์ง์ํ๋async-mutex
์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ๊ฐ์ ๋ฎคํ ์ค๋ฅผ ๊ณต์ ํ ์ํ์์ ๋์์ฑ ์ ์ด๋ฅผ ํ๋ ๋ฐฉํฅ์ ๊ณ ๋ คํ๋ค. - ๋ฌธ์ ๋ ๋ฎคํ ์ค๋ฅผ ์ ์ฉํ์ ๋, ์๊ณ ๊ตฌ์ญ์ ๋ค๋ฅธ ๋ถ๋ถ์์ ์ ๊ทผํ์ง ์๋๋ค๋ ๋ณด์ฅ์ด ํ์ํ๋ค.
- ์ ์ญ ๋ฎคํ
์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ฎคํ
์ค ๊ด๋ฆฌ ์ธก๋ฉด์์๋ ์ข์ง๋ง, ๊ทธ ์ธ ๋ถ๋ถ์์๋ ๋ชจ๋ ์ ์ข๋ค.
- ์๋ชป๋ ์ฌ์ฉ์ผ๋ก ์ธํ dead lock, ๋ฎคํ ์ค ๋จ๋ฐ๋ก ์ธํ ์ฑ๋ฅ ์ ํ๊ฐ ์ฐ๋ ค๋๋ค.
- ๋ฎคํ
์ค๋ฅผ ๊ด๋ฆฌํ๋ ํด๋์ค, ์๊ณ ๊ตฌ์ญ ๋ด์ ํด๋์ค ๋ ๋ถ๋ถ์ด ์ฑ๊ธํค์ผ๋ก ๊ตฌ์ฑ๋์ด ์์ด์ผ ํ๋ค
- ์ด๋ฐ ๋ฐฉ๋ฒ์ ๋์ ํ๋ ๊ฒ์ด ํ์ฌ ๋จ์ผ ์๋ฒ ๊ตฌ์กฐ์์๋ ์ด์ธ๋ฆฐ๋ค๊ณ ์๊ฐํ๋ค.
-
nestjs์์๋
Injectable
๋ฐ์ฝ๋ ์ดํฐ๊ฐ ์์ผ๋ฉด์, ๊ฐ์ ๋ชจ๋ํ์ ์์ผ๋ฉด ์ฑ๊ธํค ๊ฐ์ฒด๋ฅผ ๋ณด์ฅํ๋ค.- ๋ง์ฝ, ๋ค๋ฅธ ๋ชจ๋์์ ์ฌ์ฉํด์ผํ๋ค๋ฉด, module์์
export
๋ฅผ ์ด์ฉํด ์๋น์ค๋ฅผ ๋ค๋ฅธ ๋ชจ๋์์ ์ฌ์ฉํ ์ ์๊ฒ ๋ง๋ค์ด์ผ ํ๋ค.
- ๋ง์ฝ, ๋ค๋ฅธ ๋ชจ๋์์ ์ฌ์ฉํด์ผํ๋ค๋ฉด, module์์
-
์ฑ๊ธํค์ด ๋ณด์ฅ๋๊ฒ
Injectable
๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ถ๊ฐํ๊ณ ,liveData
์๋น์ค๋ฅผ ์ฃผ์ ๋ฐ๋ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ๋ค.@Injectable() export class StockGateway { @WebSocketServer() server: Server; private readonly mutex = new Mutex(); constructor(private readonly liveData: LiveData) {} //์ดํ ์๋ต
StockGateway
์์ ์ต์ ๋จ์๋ก mutex๋ฅผ ๊ฑธ์๋ค.
- ํ์ฌ ์์ผ์ ์ ์๋์ด ์๋ ์ ์ ๋ฅผ ๊ฒ์ฌํ๊ณ , ๊ตฌ๋ ๋์๋ ์ง๋ฅผ ๊ฒ์ฌํ๊ฒ ์ฒ๋ฆฌํด์ฃผ์๋ค.
@SubscribeMessage('connectStock')
async handleConnectStock(
@MessageBody() stockId: string,
@ConnectedSocket() client: Socket,
) {
client.join(stockId);
// ์ถ๊ฐ๋ ๋ถ๋ถ
await this.mutex.runExclusive(async () => {
const connectedSockets = await this.server.in(stockId).fetchSockets();
if (connectedSockets.length > 0 && !this.liveData.isSubscribe(stockId)) {
this.liveData.subscribe(stockId);
}
});
client.emit('connectionSuccess', {
message: `Successfully connected to stock room: ${stockId}`,
stockId,
});
}
async handleDisconnectStock(
@MessageBody() stockId: string,
@ConnectedSocket() client: Socket,
) {
client.leave(stockId);
await this.mutex.runExclusive(async () => {
const connectedSockets = await this.server.in(stockId).fetchSockets();
if (connectedSockets.length === 0) {
this.liveData.unsubscribe(stockId);
}
});
client.emit('disconnectionSuccess', {
message: `Successfully disconnected to stock room: ${stockId}`,
stockId,
});
}
- ๋ค๋ง, ์ด๋ฐ ๋ฐฉ์์ ๊ตฌํ์ ๋์์ ์ ์ ๊ฐ ๋ค์ด์ค๊ณ , ๋๊ฐ๋ ๋ถ๋ถ์์ ๋ฎคํ ์ค๋ฅผ ๊ณต์ ํ๋ฏ๋ก์จ ์ฑ๋ฅ์ ํ๊ฐ ๋ฐ์ํ ์ ์๋ค.
- ๋ํ, ๋ค์ค ์๋ฒ ํ๊ฒฝํ์์๋ ์๊ณ ๊ตฌ์ญ์ ๋ค๋ฅธ ์๋ฒ์์ ์ ๊ทผ ๊ฐ๋ฅํ๋ฏ๋ก ์ด๋ฐ ํด๊ฒฐ๋ฐฉ๋ฒ์ผ๋ก๋ ์ฝ๊ฒ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
Node.js์์ ๊ณต์ ๋ฆฌ์์ค์ ๋ํ ๋๊ธฐํ๋ฅผ ์ํ async-mutex ์ฌ์ฉ
- ๐ฉ FE ๊ธฐ์ ์ ํ์ด์
- โจ ์ฐจํธ์ ๋ฐ์ํ ๊ตฌํ๊ณผ useRef ํ์ ๋ฌธ์
- ๐ฃ ๋ถ๋ชจ ์์์ ์ํ์ ๋ฐ๋ผ ์์ ์์๋ ์คํ์ผ ๋ณํ ๋ถ์ฌํ๊ธฐ
- ๐ zod ๋์ ํ๊ธฐ
- ๐ useInfiniteQuery๋ฅผ ์ฌ์ฉํ ๊ทธ๋ํ ๋ฌดํ์คํฌ๋กค ๊ตฌํ
- ๐ซ ์ฌ์ฉ์์ ์์ ๋ณํ ์๋ ๊ทธ๋ํ ์คํฌ๋กค ๊ตฌํํ๊ธฐ
- ๐งช ์๋ง์ ๊ทธ๋ํ ๋ฐ์ดํฐ ์์ฒญ์ ์ด๋ป๊ฒ ์ค์ผ๊น
- ๐ ๋คํฌ๋ชจ๋์์ ์๋ก๊ณ ์นจ ์ ๋ผ์ดํธ๋ชจ๋๊ฐ ์ ๊น ๋ณด์ด๋ ๋ฌธ์
- ๐ ์น์์ผ์ ์ฑํ ๋ฐ์ดํฐ์ REST API์ ์ฑํ ๋ฐ์ดํฐ๋ฅผ ํจ๊ป ๊ด๋ฆฌํ๊ธฐ
- ๐ก BE ๊ธฐ์ ์ ํ ์ด์
- โ๏ธ Node WebSocket ํ๊ณ ๋ค๊ธฐ
- โ๏ธ TypeORM Datasource mock ๋ง๋ค๊ธฐ
- โ๏ธ oauth ID range ๋ฌธ์
- ๐ custom pipe์์ Nan์ด ๋ฐ์์ง๋ ๋ฌธ์
- ๐ช nest Websocket์ ์ธ์ ์ด ์๋๋ค๊ณ ?
- ๐ด nginx websocket ์ฐ๊ฒฐ ์ ๋ฌธ์ ๋ฐ์
- ๐ WebPush ๊ตฌํ
- ๐ง ์ฐ์ ์์ ํ๋ก ์์ฒญ ์ ์ดํ๊ธฐ
- ๐ websocket์ด ๋ฆ๊ฒ ํ ๋น๋์ด ๋ฐ์๋๋ ๋ฌธ์
- ๐ฅณ typeorm์ ์ด์ฉํ FCM ์๋ฆผ ์๋น์ค
- ๐ฆ ๋ค์ค ์ ์ ๋์์ฑ ์ ์ด โ ์ฑ๊ธํค, ๋ฎคํ ์ค
- ๐ ๊ทธ๋ํ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ์ ๊ณตํ๊ธฐ์ํ ์ ๋ต
- ๐ ๏ธ ์ธํ๋ผ ๊ธฐ์ ์คํ ์ ํ ์ด์
- ๐ Ncloud ์ค์ ๊ณผ์
- ๐ ORM ๊ธฐ์ ์คํ ๋น๊ต
- ๐ค RabbitMQ๋ก ๋ถ์ฐ ์๋ฒ์๊ฒ ๋ฉ์์ง๋ฅผ ๋ถ๋ฐฐํ๊ธฐ
- ๐ข private DB ์๋ฒ์ ์ ์ํ์ง ๋ชปํ๋ ํ์
- ๐ 1์ฃผ์ฐจ ๋ฐํ
- ๐ 2์ฃผ์ฐจ ๋ฐํ
- ๐ 3์ฃผ์ฐจ ๋ฐํ
- ๐ 4์ฃผ์ฐจ ๋ฐํ
- ๐ 5์ฃผ์ฐจ ๋ฐํ
- ๐ ์ต์ข ๋ฐํ