Skip to content

Commit 1f0f1e2

Browse files
Merge pull request #109 from boostcampwm-2024/dev
[Release] Preview v0.1.0
2 parents 7ab0259 + 19f9d3d commit 1f0f1e2

33 files changed

+1645
-200
lines changed

.github/workflows/deploy.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Deploy to Ncloud Server
2+
on:
3+
push:
4+
branches:
5+
- main
6+
jobs:
7+
deploy:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- name: Checkout code
11+
uses: actions/checkout@v3.3.0 # workflow 내에서 repo의 최신 코드를 checkout
12+
- name: Deploy to Ncloud via SSH
13+
uses: appleboy/ssh-action@master # GitHub Actions에서 SSH로 서버에 접근
14+
with:
15+
host: ${{ secrets.REMOTE_SSH_HOST }}
16+
username: ${{ secrets.REMOTE_SSH_USERNAME }}
17+
key: ${{ secrets.REMOTE_SSH_KEY }}
18+
passphrase: ${{ secrets.REMOTE_SSH_PASSPHRASE }}
19+
password: ${{ secrets.REMOTE_SSH_PASSWORD }}
20+
port: ${{ secrets.REMOTE_SSH_PORT }}
21+
script: |
22+
echo ${{ secrets.REMOTE_SSH_PASSWORD }} | sudo -S echo deploy start!
23+
./deploy.sh # 배포 스크립트 실행

README.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
# web27-Preview
1+
# ✨ Preview
2+
<img width="100%" src="https://github.com/user-attachments/assets/4894268d-c31d-44d6-9e6c-9c37b86a4a99" />
23

3-
실시간 화상회의 기반 면접 스터디 플랫폼
4+
<br/>
5+
6+
<div align="center">면접 연습을 하고 싶은데.. 🧐</div>
7+
<div align="center">다른 사람과 함께 할 수 없을까? 👥</div>
8+
9+
<h3 align="center">✨ Preview에서 면접 연습 시작하자! ✨</h3>
410

511
### 배포
6-
[배포 링크](https://boostcamp-preview.kro.kr/)
12+
[**Preview 바로가기**](https://boostcamp-preview.kro.kr)
713

814
## 👋 팀원 소개
915

@@ -95,6 +101,7 @@
95101
<br>
96102

97103
## 📁 문서
104+
98105
### 팀 노션 워크스페이스
99106
- [노션 링크](https://alpine-tiglon-9f0.notion.site/PREVIEW-HOME-12d696f85d1f805b9787e26374b3d209?pvs=4)
100107

@@ -114,5 +121,4 @@
114121

115122
### 개발 일지
116123
- [공통 개발 일지](https://alpine-tiglon-9f0.notion.site/12d696f85d1f80c89569dcfe55b62b44?v=12f696f85d1f802db6af000cf32dfa28&pvs=4)
117-
- [문제 해결 일지](https://alpine-tiglon-9f0.notion.site/87b7f1ce19564eda8127eca29d567d0f?v=f2df7d634605464d876ccf43c9197db4&pvs=4)
118-
-
124+
- [문제 해결 일지](https://alpine-tiglon-9f0.notion.site/87b7f1ce19564eda8127eca29d567d0f?v=f2df7d634605464d876ccf43c9197db4&pvs=4)

backend/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
"@nestjs/common": "^10.0.0",
2424
"@nestjs/core": "^10.0.0",
2525
"@nestjs/platform-express": "^10.0.0",
26+
"@nestjs/platform-socket.io": "^10.4.6",
27+
"@nestjs/websockets": "^10.4.6",
2628
"reflect-metadata": "^0.2.0",
27-
"rxjs": "^7.8.1"
29+
"rxjs": "^7.8.1",
30+
"socket.io": "^4.8.1"
2831
},
2932
"devDependencies": {
3033
"@nestjs/cli": "^10.0.0",

backend/src/app.controller.spec.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
import { Test, TestingModule } from '@nestjs/testing';
2-
import { AppController } from './app.controller';
3-
import { AppService } from './app.service';
1+
import { Test, TestingModule } from "@nestjs/testing";
2+
import { AppController } from "./app.controller";
3+
import { AppService } from "./app.service";
44

5-
describe('AppController', () => {
6-
let appController: AppController;
5+
describe("AppController", () => {
6+
let appController: AppController;
77

8-
beforeEach(async () => {
9-
const app: TestingModule = await Test.createTestingModule({
10-
controllers: [AppController],
11-
providers: [AppService],
12-
}).compile();
8+
beforeEach(async () => {
9+
const app: TestingModule = await Test.createTestingModule({
10+
controllers: [AppController],
11+
providers: [AppService],
12+
}).compile();
1313

14-
appController = app.get<AppController>(AppController);
15-
});
14+
appController = app.get<AppController>(AppController);
15+
});
1616

17-
describe('root', () => {
18-
it('should return "Hello World!"', () => {
19-
expect(appController.getHello()).toBe('Hello World!');
17+
describe("root", () => {
18+
it('should return "Hello World!"', () => {
19+
expect(appController.getHello()).toBe("Hello World!");
20+
});
2021
});
21-
});
2222
});

backend/src/app.controller.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { Controller, Get } from '@nestjs/common';
2-
import { AppService } from './app.service';
1+
import { Controller, Get } from "@nestjs/common";
2+
import { AppService } from "./app.service";
33

44
@Controller()
55
export class AppController {
6-
constructor(private readonly appService: AppService) {}
6+
constructor(private readonly appService: AppService) {}
77

8-
@Get()
9-
getHello(): string {
10-
return this.appService.getHello();
11-
}
8+
@Get()
9+
getHello(): string {
10+
return this.appService.getHello();
11+
}
1212
}

backend/src/app.module.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { Module } from '@nestjs/common';
2-
import { AppController } from './app.controller';
3-
import { AppService } from './app.service';
1+
import { Module } from "@nestjs/common";
2+
import { AppController } from "./app.controller";
3+
import { AppService } from "./app.service";
4+
import { SocketModule } from "./socket/socket.module";
45

56
@Module({
6-
imports: [],
7-
controllers: [AppController],
8-
providers: [AppService],
7+
imports: [SocketModule],
8+
controllers: [AppController],
9+
providers: [AppService],
910
})
1011
export class AppModule {}

backend/src/app.service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Injectable } from '@nestjs/common';
1+
import { Injectable } from "@nestjs/common";
22

33
@Injectable()
44
export class AppService {
5-
getHello(): string {
6-
return 'Hello World!';
7-
}
5+
getHello(): string {
6+
return "Hello World!";
7+
}
88
}

backend/src/main.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { NestFactory } from '@nestjs/core';
2-
import { AppModule } from './app.module';
1+
import { NestFactory } from "@nestjs/core";
2+
import { AppModule } from "./app.module";
33

44
async function bootstrap() {
5-
const app = await NestFactory.create(AppModule);
6-
await app.listen(process.env.PORT ?? 3000);
5+
const app = await NestFactory.create(AppModule);
6+
await app.listen(process.env.PORT ?? 3000);
77
}
88
bootstrap();
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import {
2+
WebSocketGateway,
3+
WebSocketServer,
4+
OnGatewayConnection,
5+
OnGatewayDisconnect,
6+
SubscribeMessage,
7+
MessageBody,
8+
} from "@nestjs/websockets";
9+
import { Server } from "socket.io";
10+
11+
interface User {
12+
id: string;
13+
nickname: string;
14+
}
15+
16+
@WebSocketGateway({
17+
cors: {
18+
origin: "*", // CORS 설정
19+
},
20+
})
21+
export class SocketGateway implements OnGatewayConnection, OnGatewayDisconnect {
22+
@WebSocketServer()
23+
server: Server;
24+
25+
private users: { [key: string]: User[] } = {};
26+
private socketToRoom: { [key: string]: string } = {};
27+
private maximum = 5;
28+
29+
handleConnection(socket: any) {
30+
console.log(`Client connected: ${socket.id}`);
31+
}
32+
33+
handleDisconnect(socket: any) {
34+
console.log(`Client disconnected: ${socket.id}`);
35+
const roomID = this.socketToRoom[socket.id];
36+
if (roomID) {
37+
const room = this.users[roomID];
38+
if (room) {
39+
this.users[roomID] = room.filter(
40+
(user) => user.id !== socket.id
41+
);
42+
if (this.users[roomID].length === 0) {
43+
delete this.users[roomID];
44+
} else {
45+
this.server.to(roomID).emit("user_exit", { id: socket.id });
46+
}
47+
}
48+
}
49+
}
50+
51+
@SubscribeMessage("join_room")
52+
handleJoinRoom(socket: any, data: { room: string; nickname: string }) {
53+
if (this.users[data.room]) {
54+
if (this.users[data.room].length === this.maximum) {
55+
socket.emit("room_full");
56+
return;
57+
}
58+
this.users[data.room].push({
59+
id: socket.id,
60+
nickname: data.nickname,
61+
});
62+
} else {
63+
this.users[data.room] = [
64+
{ id: socket.id, nickname: data.nickname },
65+
];
66+
}
67+
68+
this.socketToRoom[socket.id] = data.room;
69+
socket.join(data.room);
70+
console.log(`[${data.room}]: ${socket.id} enter`);
71+
72+
const usersInThisRoom = this.users[data.room].filter(
73+
(user) => user.id !== socket.id
74+
);
75+
socket.emit("all_users", usersInThisRoom);
76+
}
77+
78+
@SubscribeMessage("offer")
79+
handleOffer(
80+
@MessageBody()
81+
data: {
82+
offerReceiveID: string;
83+
sdp: any;
84+
offerSendID: string;
85+
offerSendNickname: string;
86+
}
87+
) {
88+
this.server.to(data.offerReceiveID).emit("getOffer", {
89+
sdp: data.sdp,
90+
offerSendID: data.offerSendID,
91+
offerSendNickname: data.offerSendNickname,
92+
});
93+
}
94+
95+
@SubscribeMessage("answer")
96+
handleAnswer(
97+
@MessageBody()
98+
data: {
99+
answerReceiveID: string;
100+
sdp: any;
101+
answerSendID: string;
102+
}
103+
) {
104+
this.server.to(data.answerReceiveID).emit("getAnswer", {
105+
sdp: data.sdp,
106+
answerSendID: data.answerSendID,
107+
});
108+
}
109+
110+
@SubscribeMessage("candidate")
111+
handleCandidate(
112+
@MessageBody()
113+
data: {
114+
candidateReceiveID: string;
115+
candidate: any;
116+
candidateSendID: string;
117+
}
118+
) {
119+
this.server.to(data.candidateReceiveID).emit("getCandidate", {
120+
candidate: data.candidate,
121+
candidateSendID: data.candidateSendID,
122+
});
123+
}
124+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Module } from "@nestjs/common";
2+
import { SocketGateway } from "./socket.gateway";
3+
4+
@Module({
5+
providers: [SocketGateway],
6+
})
7+
export class SocketModule {}

0 commit comments

Comments
 (0)