Skip to content

Commit 238c941

Browse files
committed
refactor: separate socket server
1 parent 06caf72 commit 238c941

18 files changed

+170
-74
lines changed

.github/workflows/deploy.yml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,12 @@ jobs:
7070
7171
# 서버 디렉토리로 이동하여 환경 변수 설정
7272
cd apps/server
73-
echo "DATABASE_URL=${{ secrets.DEV_DATABASE_URL }}" > .env
74-
echo "JWT_ACCESS_SECRET=${{ secrets.JWT_ACCESS_SECRET }}" >> .env
75-
echo "AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}" >> .env
76-
echo "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}" >> .env
73+
echo "${{SERVER_ENV}}" > .env
7774
7875
# pm2로 기존 프로세스 종료 및 새 프로세스 시작
79-
pm2 stop ask-it || true
80-
pm2 delete ask-it || true
76+
pm2 stop all || true
77+
pm2 delete all || true
8178
pnpx prisma generate
8279
pnpx prisma migrate deploy
8380
pnpm build
84-
pm2 start pnpm --name "ask-it" -- run start:prod
81+
pm2 start ecosystem.config.js

apps/server/ecosystem.config.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module.exports = {
2+
apps: [
3+
{
4+
name: 'http-server',
5+
script: 'pnpm',
6+
args: 'run start:prod',
7+
interpreter: 'none',
8+
cwd: './',
9+
env: {
10+
NODE_ENV: 'production',
11+
PORT: 3000,
12+
},
13+
},
14+
{
15+
name: 'ws-server',
16+
script: 'pnpm',
17+
args: 'run start:prod',
18+
interpreter: 'none',
19+
cwd: './',
20+
env: {
21+
NODE_ENV: 'production',
22+
PORT: 4000,
23+
},
24+
},
25+
],
26+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { BroadcastEventDto } from '@socket/dto/broadcast-event.dto';
2+
3+
const SOCKET_SERVER_HOST = process.env.SOCKET_SERVER_HOST;
4+
const SOCKET_SERVER_PORT = process.env.SOCKET_SERVER_PORT;
5+
6+
export const requestSocket = async ({ event, content, sessionId, token }: BroadcastEventDto) => {
7+
try {
8+
await fetch(`${SOCKET_SERVER_HOST}:${SOCKET_SERVER_PORT}/api/socket/broadcast`, {
9+
method: 'POST',
10+
headers: { 'Content-Type': 'application/json' },
11+
body: JSON.stringify({
12+
event,
13+
content,
14+
sessionId,
15+
token,
16+
}),
17+
});
18+
} catch (error) {
19+
throw error;
20+
}
21+
};

apps/server/src/main.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as cookieParser from 'cookie-parser';
66

77
import { AppModule } from './app.module';
88

9-
async function bootstrap() {
9+
async function bootstrap(port: number) {
1010
const app = await NestFactory.create(AppModule);
1111

1212
app.use(cookieParser());
@@ -25,6 +25,13 @@ async function bootstrap() {
2525

2626
app.useWebSocketAdapter(new IoAdapter(app));
2727

28-
await app.listen(process.env.PORT ?? 3000);
28+
await app.listen(port);
29+
}
30+
31+
const args = process.argv.slice(2);
32+
33+
if (args.includes('http')) {
34+
bootstrap(Number(process.env.API_SERVER_PORT ?? '3000'));
35+
} else if (args.includes('ws')) {
36+
bootstrap(Number(process.env.SOCKET_SERVER_PORT ?? '4000'));
2937
}
30-
bootstrap();

apps/server/src/questions/questions.controller.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { ToggleQuestionLikeSwagger } from './swagger/toggle-question.swagger';
2525
import { BaseDto } from '@common/base.dto';
2626
import { SessionTokenValidationGuard } from '@common/guards/session-token-validation.guard';
2727
import { TransformInterceptor } from '@common/interceptors/transform.interceptor';
28+
import { requestSocket } from '@common/request-socket';
2829
import {
2930
UpdateQuestionBodyDto,
3031
UpdateQuestionClosedDto,
@@ -38,16 +39,13 @@ import {
3839
UpdateQuestionClosedSwagger,
3940
UpdateQuestionPinnedSwagger,
4041
} from '@questions/swagger/update-question.swagger';
41-
import { SocketGateway } from '@socket/socket.gateway';
42+
import { SOCKET_EVENTS } from '@socket/socket.constant';
4243

4344
@ApiTags('Questions')
4445
@UseInterceptors(TransformInterceptor)
4546
@Controller('questions')
4647
export class QuestionsController {
47-
constructor(
48-
private readonly questionsService: QuestionsService,
49-
private readonly socketGateway: SocketGateway,
50-
) {}
48+
constructor(private readonly questionsService: QuestionsService) {}
5149

5250
@Get()
5351
@GetQuestionSwagger()
@@ -66,7 +64,8 @@ export class QuestionsController {
6664
const { sessionId, token } = createQuestionDto;
6765
const resultForOwner = { question: createdQuestion };
6866
const resultForOther = { question: { ...createdQuestion, isOwner: false } };
69-
this.socketGateway.broadcastNewQuestion(sessionId, token, resultForOther);
67+
const event = SOCKET_EVENTS.QUESTION_CREATED;
68+
await requestSocket({ sessionId, token, event, content: resultForOther });
7069
return resultForOwner;
7170
}
7271

@@ -86,7 +85,8 @@ export class QuestionsController {
8685
);
8786
const { sessionId, token } = updateQuestionBodyDto;
8887
const result = { question: updatedQuestion };
89-
this.socketGateway.broadcastQuestionUpdate(sessionId, token, result);
88+
const event = SOCKET_EVENTS.QUESTION_UPDATED;
89+
await requestSocket({ sessionId, token, event, content: result });
9090
return result;
9191
}
9292

@@ -97,7 +97,8 @@ export class QuestionsController {
9797
const { sessionId, token } = data;
9898
await this.questionsService.deleteQuestion(questionId, req.question, data);
9999
const resultForOther = { questionId };
100-
this.socketGateway.broadcastQuestionDelete(sessionId, token, resultForOther);
100+
const event = SOCKET_EVENTS.QUESTION_DELETED;
101+
await requestSocket({ sessionId, token, event, content: resultForOther });
101102
return {};
102103
}
103104

@@ -112,7 +113,8 @@ export class QuestionsController {
112113
const updatedQuestion = await this.questionsService.updateQuestionPinned(questionId, updateQuestionPinnedDto);
113114
const { sessionId, token } = updateQuestionPinnedDto;
114115
const result = { question: updatedQuestion };
115-
this.socketGateway.broadcastQuestionUpdate(sessionId, token, result);
116+
const event = SOCKET_EVENTS.QUESTION_UPDATED;
117+
await requestSocket({ sessionId, token, event, content: result });
116118
return result;
117119
}
118120

@@ -127,7 +129,8 @@ export class QuestionsController {
127129
const updatedQuestion = await this.questionsService.updateQuestionClosed(questionId, updateQuestionClosedDto);
128130
const { sessionId, token } = updateQuestionClosedDto;
129131
const result = { question: updatedQuestion };
130-
this.socketGateway.broadcastQuestionUpdate(sessionId, token, result);
132+
const event = SOCKET_EVENTS.QUESTION_UPDATED;
133+
await requestSocket({ sessionId, token, event, content: result });
131134
return result;
132135
}
133136

@@ -143,7 +146,8 @@ export class QuestionsController {
143146
const { sessionId, token } = toggleQuestionLikeDto;
144147
const resultForOwner = { liked, likesCount };
145148
const resultForOther = { questionId, liked: false, likesCount };
146-
this.socketGateway.broadcastQuestionLike(sessionId, token, resultForOther);
149+
const event = SOCKET_EVENTS.QUESTION_LIKED;
150+
await requestSocket({ sessionId, token, event, content: resultForOther });
147151
return resultForOwner;
148152
}
149153
}

apps/server/src/questions/questions.module.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ import { PrismaModule } from '@prisma-alias/prisma.module';
99
import { QuestionExistenceGuard } from '@questions/guards/question-existence.guard';
1010
import { QuestionOwnershipGuard } from '@questions/guards/question-ownership.guard';
1111
import { RepliesRepository } from '@replies/replies.repository';
12-
import { SocketModule } from '@socket/socket.module';
1312

1413
@Module({
15-
imports: [PrismaModule, SessionTokenModule, SocketModule],
14+
imports: [PrismaModule, SessionTokenModule],
1615
controllers: [QuestionsController],
1716
providers: [QuestionsService, QuestionsRepository, QuestionExistenceGuard, QuestionOwnershipGuard, RepliesRepository],
1817
exports: [QuestionExistenceGuard, QuestionsRepository],

apps/server/src/replies/replies.controller.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,16 @@ import { UpdateReplySwagger } from './swagger/update-reply.swagger';
2626

2727
import { SessionTokenValidationGuard } from '@common/guards/session-token-validation.guard';
2828
import { TransformInterceptor } from '@common/interceptors/transform.interceptor';
29+
import { requestSocket } from '@common/request-socket';
2930
import { QuestionExistenceGuard } from '@questions/guards/question-existence.guard';
30-
import { SocketGateway } from '@socket/socket.gateway';
31+
import { SOCKET_EVENTS } from '@socket/socket.constant';
3132
import { BaseDto } from '@src/common/base.dto';
3233

3334
@ApiTags('Replies')
3435
@UseInterceptors(TransformInterceptor)
3536
@Controller('replies')
3637
export class RepliesController {
37-
constructor(
38-
private readonly repliesService: RepliesService,
39-
private readonly socketGateway: SocketGateway,
40-
) {}
38+
constructor(private readonly repliesService: RepliesService) {}
4139

4240
@Post()
4341
@CreateReplySwagger()
@@ -51,7 +49,7 @@ export class RepliesController {
5149
const resultForOwner = { reply: { ...reply, isHost } };
5250
const resultForOther = { reply: { ...reply, isHost, isOwner: false } };
5351
const { sessionId, token } = createReplyDto;
54-
this.socketGateway.broadcastNewReply(sessionId, token, resultForOther);
52+
await requestSocket({ sessionId, token, event: SOCKET_EVENTS.REPLY_CREATED, content: resultForOther });
5553
return resultForOwner;
5654
}
5755

@@ -63,7 +61,7 @@ export class RepliesController {
6361
const updatedReply = await this.repliesService.updateBody(replyId, updateReplyBodyDto);
6462
const { sessionId, token } = updateReplyBodyDto;
6563
const result = { reply: updatedReply };
66-
this.socketGateway.broadcastReplyUpdate(sessionId, token, result);
64+
await requestSocket({ sessionId, token, event: SOCKET_EVENTS.REPLY_UPDATED, content: result });
6765
return result;
6866
}
6967

@@ -74,7 +72,7 @@ export class RepliesController {
7472
const { sessionId, token } = data;
7573
const { questionId } = await this.repliesService.deleteReply(replyId, token, request['reply']);
7674
const resultForOther = { replyId, questionId };
77-
this.socketGateway.broadcastReplyDelete(sessionId, token, resultForOther);
75+
await requestSocket({ sessionId, token, event: SOCKET_EVENTS.REPLY_DELETED, content: resultForOther });
7876
return {};
7977
}
8078

@@ -87,7 +85,8 @@ export class RepliesController {
8785
const { sessionId, token } = toggleReplyLikeDto;
8886
const resultForOwner = { liked, likesCount };
8987
const resultForOther = { replyId, liked: false, likesCount, questionId };
90-
this.socketGateway.broadcastReplyLike(sessionId, token, resultForOther);
88+
const event = SOCKET_EVENTS.REPLY_LIKED;
89+
await requestSocket({ sessionId, token, event, content: resultForOther });
9190
return resultForOwner;
9291
}
9392
}

apps/server/src/replies/replies.module.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ import { SessionTokenModule } from '@common/guards/session-token.module';
88
import { PrismaModule } from '@prisma-alias/prisma.module';
99
import { QuestionsModule } from '@questions/questions.module';
1010
import { SessionsRepository } from '@sessions/sessions.repository';
11-
import { SocketModule } from '@socket/socket.module';
1211

1312
@Module({
14-
imports: [PrismaModule, SessionTokenModule, QuestionsModule, SocketModule],
13+
imports: [PrismaModule, SessionTokenModule, QuestionsModule],
1514
controllers: [RepliesController],
1615
providers: [RepliesService, RepliesRepository, SessionsRepository],
1716
})

apps/server/src/sessions-auth/sessions-auth.controller.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,15 @@ import { BaseDto } from '@common/base.dto';
2323
import { SessionTokenValidationGuard } from '@common/guards/session-token-validation.guard';
2424
import { JwtPayloadInterceptor } from '@common/interceptors/jwt-payload.interceptor';
2525
import { TransformInterceptor } from '@common/interceptors/transform.interceptor';
26-
import { SocketGateway } from '@socket/socket.gateway';
26+
import { requestSocket } from '@common/request-socket';
27+
import { SOCKET_EVENTS } from '@socket/socket.constant';
2728

2829
@ApiTags('sessions-auth')
2930
@UseInterceptors(TransformInterceptor)
3031
@UseInterceptors(JwtPayloadInterceptor)
3132
@Controller('sessions-auth')
3233
export class SessionsAuthController {
33-
constructor(
34-
private readonly sessionsAuthService: SessionsAuthService,
35-
private readonly socketGateway: SocketGateway,
36-
) {}
34+
constructor(private readonly sessionsAuthService: SessionsAuthService) {}
3735

3836
@Get()
3937
@AuthSessionsSwagger()
@@ -56,7 +54,8 @@ export class SessionsAuthController {
5654
async authorizeHost(@Param('userId', ParseIntPipe) userId: number, @Body() data: UpdateHostDto) {
5755
const { sessionId, token } = data;
5856
const result = { user: await this.sessionsAuthService.authorizeHost(userId, data) };
59-
this.socketGateway.broadcastHostChange(sessionId, token, result);
57+
const event = SOCKET_EVENTS.HOST_CHANGED;
58+
await requestSocket({ sessionId, token, event, content: result });
6059
return result;
6160
}
6261
}

apps/server/src/sessions-auth/sessions-auth.module.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ import { SessionTokenValidationGuard } from '@common/guards/session-token-valida
99
import { SessionTokenModule } from '@common/guards/session-token.module';
1010
import { PrismaModule } from '@prisma-alias/prisma.module';
1111
import { SessionsRepository } from '@sessions/sessions.repository';
12-
import { SocketModule } from '@socket/socket.module';
1312

1413
@Module({
15-
imports: [JwtModule.register({}), PrismaModule, SessionTokenModule, SocketModule],
14+
imports: [JwtModule.register({}), PrismaModule, SessionTokenModule],
1615
controllers: [SessionsAuthController],
1716
providers: [SessionsAuthService, SessionsAuthRepository, SessionTokenValidationGuard, SessionsRepository],
1817
})

0 commit comments

Comments
 (0)