Skip to content

Commit

Permalink
Merge pull request #213 from yewon830/feat/share-webcam
Browse files Browse the repository at this point in the history
[Feat] 시그널링 서버 및 프론트엔드 배포 파일 작성
  • Loading branch information
jihyun-j authored Jul 13, 2024
2 parents 9e83048 + bf52a3e commit 186ecd0
Show file tree
Hide file tree
Showing 9 changed files with 313 additions and 22 deletions.
1 change: 1 addition & 0 deletions front/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
Expand Down
23 changes: 23 additions & 0 deletions front/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM node:16-alpine as build

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

FROM nginx:stable-alpine

COPY --from=build /app/build /usr/share/nginx/html

RUN rm /etc/nginx/conf.d/default.conf

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

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
10 changes: 10 additions & 0 deletions front/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
server {
listen 80;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
3 changes: 3 additions & 0 deletions front/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"axios": "^1.7.2",
"express": "^4.19.2",
"jwt-decode": "^4.0.0",
"phaser": "^3.80.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router": "^6.23.0",
"react-router-dom": "^6.23.0",
"react-scripts": "5.0.1",
"socket.io": "^4.7.5",
"socket.io-client": "^4.7.5",
"tailwindcss": "^3.4.3",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4",
Expand Down
75 changes: 75 additions & 0 deletions front/server/signalingServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import express from 'express';
import http from 'http';
import { Server as socketIo } from 'socket.io';

interface Room{
users: string[]
}


const app = express(); // express 애플리케이션 인스턴스 생성
const server = http.createServer(app); // hTTP 서버 생성, 이 서버가 Express 애플리케이션 처리

// socket.io 서버 인스턴스
const io = new socketIo(server, {
cors: {
origin: true, // FIXME :보안을 위해 CORS 설정 구체화 해줘야 함
},
});

const totalRooms :{[key: string] : Room} = {}; // {방의 이름 : [user 소켓 id]}의 객체

// 클라이언트가 socket.io 서버에 연결 되어있을 때
io.on('connection', (socket: any) => {
console.log(`Client connected. socket: ${socket.id}`);

// 채팅을 위한 방에 접속
socket.on('join', (data: { room: string }) => {
if(!data?.room) return;
socket.join(data.room);
// 방이 없으면 새로운 방을 만든다.
if(!totalRooms[data.room]){
totalRooms[data.room] = {users: []};
}
//방에 사용자를 추가
totalRooms[data.room].users.push(socket.id);
socket.room = data.room;

console.log(`Join room ${data.room}. Socket ${socket.id}`);
});

// peer가 제안 :: SDP 방식(제안-응답)
socket.on('offer', (data: { sdp: string; room: string }) => {
socket.to(data.room).emit('offer', { sdp: data.sdp, sender: socket.id });
});

// peer가 응답
socket.on('answer', (data: { sdp: string; room: string }) => {
socket.to(data.room).emit('answer', { sdp: data.sdp, sender: socket.id });
});

// peer가 자신이 데이터를 보낼 수 있는 네트워크 경로를 찾기 위해 ICE 프로세스 수행
socket.on('candidate', (data: { candidate: string; room: string }) => {
socket.to(data.room).emit('candidate', { candidate: data.candidate, sender: socket.id });
});

// 연결 종료
socket.on('disconnect', () => {
// 방에서 사용자 제거
if(socket.room && totalRooms[socket.room]){
totalRooms[socket.room].users = totalRooms[socket.room].users.filter(
(id) => id !==socket.id
)
//사용자가 한명도 없으면 방 없앰
if(totalRooms[socket.room].users.length ===0){
delete totalRooms[socket.room];
}
}
console.log('Client disconnected');
});
});

// 포트 실행
server.listen(5001, () => { // 포트 번호
console.log('Listening on port 5001');
});
41 changes: 29 additions & 12 deletions front/src/components/VideoCall/VideoCallBoxList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,29 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'
import VideoCallBoxListItem from './VideoCallBoxListItem'
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
import { Member } from '../../types/layout';
import { Box } from '@mui/material';
import axios from 'axios';
import { useParams } from 'react-router';
import { ServerMember } from '../../types/server';

const VideoCallBoxList = () => {
const [curVideoCallBoxPage, setCurVideoCallBoxPage] = useState(0);
const [slicedMemberList, setSlicedMemberList] = useState<Member[]>([]); // 페이징 처리 된 멤버 리스트
const serverMemberList = [ {
id: 13,
userName: "test",
profilePath: "https://helpx.adobe.com/content/dam/help/en/photoshop/using/quick-actions/remove-background-before-qa1.png"
},];
const [slicedMemberList, setSlicedMemberList] = useState<ServerMember[]>([]); // 페이징 처리 된 멤버 리스트
const [serverMemberList, setServerMemberList] = useState([]);
// const serverId = useParams();

// FIXME : 해당 API axios 인터셉터 개발되면 수정 필요
const accessToken = localStorage.getItem('dicoTown_AccessToken');
const getServerMember = useCallback(()=>{
axios.get(`http://kpring.duckdns.org/server/api/v1/server/66795ea1981fc767b76ca9d0`,{
headers: {'Authorization': `${accessToken}`}
})
.then(response=>{
setServerMemberList(response.data.data.users);
})
.catch(err=>console.log(err))
},[accessToken])


// 마지막 페이지 수
const lastPage = useMemo(()=>{
Expand All @@ -24,17 +36,17 @@ const VideoCallBoxList = () => {
lastPage = Math.floor(memberCnt/4)
}
return lastPage
},[])
},[serverMemberList])

// TODO : 화면 공유 박스 이전 페이지 이동 핸들링 함수
// 화면 공유 박스 이전 페이지 이동 핸들링 함수
const handleBoxPagePrev = useCallback(()=>{
let curPage = curVideoCallBoxPage;
if(curPage!==0){
setCurVideoCallBoxPage(curPage - 1)
}
},[curVideoCallBoxPage])

// // TODO : 화면 공유 박스 다음 페이지 이동 핸들링 함수
// 화면 공유 박스 다음 페이지 이동 핸들링 함수
const handleBoxPageNext = useCallback(()=>{
if(curVideoCallBoxPage!==lastPage){
let curPage = curVideoCallBoxPage;
Expand All @@ -43,11 +55,16 @@ const VideoCallBoxList = () => {
},[curVideoCallBoxPage,lastPage])


// TODO : 화면공유 멤버 리스트 슬라이싱 함수
// 화면공유 멤버 리스트 슬라이싱 함수
const sliceMemberList = useCallback(()=>{
const newMemberList = serverMemberList.slice(curVideoCallBoxPage*4, (curVideoCallBoxPage*4)+4);
setSlicedMemberList(newMemberList)
},[curVideoCallBoxPage])
},[curVideoCallBoxPage, serverMemberList])

// 무한루프 방지를 위해 useEffect 분리
useEffect(()=>{
getServerMember();
},[getServerMember])

useEffect(() => {
sliceMemberList();
Expand Down
8 changes: 4 additions & 4 deletions front/src/components/VideoCall/VideoCallBoxListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useEffect, useRef } from 'react'
import { Member } from '../../types/layout'
import React from 'react'
import { Box } from '@mui/material';
import { ServerMember } from '../../types/server';

interface MemberListItemProps{
member: Member;
member: ServerMember;
}

const VideoCallBoxListItem : React.FC<MemberListItemProps>= ({member}) => {
Expand Down Expand Up @@ -35,7 +35,7 @@ const VideoCallBoxListItem : React.FC<MemberListItemProps>= ({member}) => {
position:'absolute',
bottom: '8px',
right: '16px'
}}>{member.userName}</Box>
}}>{member.name}</Box>
</Box>
</Box>
</Box>
Expand Down
7 changes: 7 additions & 0 deletions front/src/types/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,10 @@ export interface ServerCardProps {
export interface ServerCardListProps {
servers: ServerType[];
}

// 서버 멤버 조회
export interface ServerMember {
id : number;
name : string;
profileImage : string;
}
Loading

0 comments on commit 186ecd0

Please sign in to comment.