Skip to content

Commit

Permalink
[FE][Chore] 프론트엔드 4주차 배포
Browse files Browse the repository at this point in the history
  • Loading branch information
happyhyep committed Nov 21, 2024
2 parents 9c93848 + 7c58107 commit 66099e0
Show file tree
Hide file tree
Showing 18 changed files with 236 additions and 88 deletions.
24 changes: 10 additions & 14 deletions backend/src/controllers/authController.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { loginUser, registerUser } from '../services/authService.js';
import { ErrorResponseDto } from '../dto/errorResponse.dto.js';
import { ResponseDto } from '../dto/response.dto.js';

/**
* @description 로그인 컨트롤러
Expand All @@ -9,16 +11,12 @@ export const loginController = async (req, res) => {
try {
const token = await loginUser(id, password);
if (!token) {
return res.status(401).json({ success: false, message: 'Invalid ID or password' });
return res.status(401).json(new ErrorResponseDto({ message: 'Invalid ID or password' }));
}
return res.status(201).json({
success: true,
message: 'Login successfully',
data: token,
});
return res.status(200).json(new ResponseDto({ resultMsg: 'Login successful', data: token }));
} catch (error) {
console.error('Login error:', error);
return res.status(500).json({ success: false, message: 'Server error occurred' });
return res.status(500).json(new ErrorResponseDto({ message: 'Server error occurred' }));
}
};

Expand All @@ -29,16 +27,14 @@ export const registerUserController = async (req, res) => {
try {
const { id, name, password, email } = req.body;
const newUser = await registerUser(id, name, password, email);
return res.status(201).json({
success: true,
message: 'Login successfully',
data: newUser,
});
return res
.status(200)
.json(new ResponseDto({ resultMsg: 'Registration successful', data: newUser }));
} catch (error) {
if (error.message === 'User ID already exists') {
return res.status(409).json({ error: 'User ID already exists' });
return res.status(409).json(new ErrorResponseDto({ message: 'User ID already exists' }));
}
console.error('User registration error:', error);
res.status(500).json({ error: 'Server error' });
return res.status(500).json(new ErrorResponseDto({ message: 'Server error' }));
}
};
71 changes: 28 additions & 43 deletions backend/src/controllers/channelController.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
getChannelGuestInfoService,
getUserChannels,
} from '../services/channelService.js';
import { ResponseDto } from '../dto/response.dto.js';
import { ErrorResponseDto } from '../dto/errorResponse.dto.js';

/**
* @description 채널 생성 컨트롤러
Expand All @@ -15,17 +17,12 @@ export const createChannelController = async (req, res) => {

const channel = await createChannelService(name, host_id, guests);

return res.status(201).json({
success: true,
message: 'Channel created successfully',
data: channel,
});
return res
.status(200)
.json(new ResponseDto({ resultMsg: 'Channel created successfully', data: channel }));
} catch (err) {
console.error(err);
return res.status(500).json({
success: false,
message: 'Server error',
});
return res.status(500).json(new ErrorResponseDto({ message: 'Server error occurred' }));
}
};

Expand All @@ -40,22 +37,15 @@ export const addGuestController = async (req, res) => {
const updatedChannel = await addGuestService(channelId, guests);

if (!updatedChannel) {
return res.status(404).json({
success: false,
message: 'Channel not found',
});
return res.status(404).json(new ErrorResponseDto({ message: 'Channel not found' }));
}

return res.status(200).json({
success: true,
message: 'Guests added successfully',
});
return res
.status(200)
.json(new ResponseDto({ resultMsg: 'Guests added successfully', data: updatedChannel }));
} catch (err) {
console.error(err);
return res.status(500).json({
success: false,
message: 'Server error',
});
return res.status(500).json(new ErrorResponseDto({ message: 'Server error occurred' }));
}
};

Expand All @@ -68,16 +58,14 @@ export const getChannelInfoController = async (req, res) => {
try {
const channel = await getChannelByIdService(id);
if (!channel) {
return res.status(404).json({ success: false, message: 'Channel not found' });
return res.status(404).json(new ErrorResponseDto({ message: 'Channel not found' }));
}
return res.status(200).json({
success: true,
message: 'Get channel successfully',
data: channel,
});
return res
.status(200)
.json(new ResponseDto({ resultMsg: 'Get channel successfully', data: channel }));
} catch (err) {
console.error(err);
return res.status(500).json({ success: false, message: 'Server error' });
return res.status(500).json(new ErrorResponseDto({ message: 'Server error occurred' }));
}
};

Expand All @@ -89,17 +77,14 @@ export const getChannelGuestInfoController = async (req, res) => {
try {
const result = await getChannelGuestInfoService(channelId, guestId);
if (result) {
res.status(200).json({
success: true,
message: 'Get guest data successfully',
data: result,
});
} else {
res.status(404).json({ success: false, message: 'Channel or guest not found' });
return res
.status(200)
.json(new ResponseDto({ resultMsg: 'Get guest data successfully', data: result }));
}
return res.status(404).json(new ErrorResponseDto({ message: 'Channel or guest not found' }));
} catch (error) {
console.error(error);
res.status(500).json({ success: false, message: 'Server error' });
return res.status(500).json(new ErrorResponseDto({ message: 'Server error occurred' }));
}
};

Expand All @@ -112,15 +97,15 @@ export const getUserChannelsController = async (req, res) => {
try {
const channels = await getUserChannels(userId);
if (!channels.length) {
return res.status(404).json({ success: false, message: 'No channels found for this user.' });
return res
.status(404)
.json(new ErrorResponseDto({ message: 'No channels found for this user.' }));
}
res.status(200).json({
success: true,
message: 'Get channels successfully',
data: channels,
});
res
.status(200)
.json(new ResponseDto({ resultMsg: 'Get channels successfully', data: { channels } }));
} catch (error) {
console.error(error);
return res.status(500).json({ success: false, message: 'Server error' });
return res.status(500).json(new ErrorResponseDto({ message: 'Server error occurred' }));
}
};
8 changes: 8 additions & 0 deletions backend/src/dto/errorResponse.dto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export class ErrorResponseDto {
constructor(error) {
this.resultCode = error.resultCode || 1;
this.resultMsg = error.resultMsg || error.message || 'Unknown Error';
this.data = null;
this.totalCount = 0;
}
}
8 changes: 8 additions & 0 deletions backend/src/dto/response.dto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export class ResponseDto {
constructor(data = {}) {
this.resultCode = data.resultCode || 0;
this.resultMsg = data.resultMsg || '';
this.data = data.data || null;
this.totalCount = data.totalCount || 0;
}
}
6 changes: 3 additions & 3 deletions backend/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ app.use(express.json());
// TODO: 프론트 배포 후 origin url 변경
app.use(
cors({
origin: ['http://localhost:5173', 'http://223.130.151.43'],
origin: ['http://localhost:5173', 'http://223.130.151.43', 'https://ddara.kro.kr'],
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
credentials: true,
}),
Expand All @@ -36,6 +36,6 @@ try {
console.error('Failed to initialize WebSocket server:', error);
}

app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
server.listen(PORT, () => {
console.log(`Server is running`);
});
18 changes: 18 additions & 0 deletions backend/src/middleware/authenticateJWT.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import jwt from 'jsonwebtoken';

export const authenticateJWT = (req, res, next) => {
const token = req.header('Authorization')?.replace('Bearer ', '');

if (!token) {
return res.status(403).json({ message: 'Access Denied: No Token Provided' });
}

jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) {
return res.status(403).json({ message: 'Invalid Token' });
}

req.user = user;
next();
});
};
2 changes: 1 addition & 1 deletion backend/src/routes/authRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ authRouter.post(
* schema:
* $ref: '#/components/schemas/RegisterRequest'
* responses:
* "201":
* "200":
* description: "회원가입 성공"
* "400":
* description: "유효성 검사 실패"
Expand Down
7 changes: 6 additions & 1 deletion backend/src/routes/channelRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
getUserChannelsController,
} from '../controllers/channelController.js';
import { validationMiddleware } from '../middleware/validationMiddleware.js';
import { authenticateJWT } from '../middleware/authenticateJWT.js';

export const channelRouter = express.Router();

Expand All @@ -27,7 +28,7 @@ export const channelRouter = express.Router();
* schema:
* $ref: '#/components/schemas/CreateChannelRequest'
* responses:
* 201:
* 200:
* description: '채널 생성 성공'
* content:
* application/json:
Expand All @@ -40,6 +41,7 @@ channelRouter.post(
body('name').notEmpty().withMessage('Name is required'),
body('host_id').notEmpty().withMessage('Host ID is required'),
],
authenticateJWT,
validationMiddleware,
createChannelController,
);
Expand Down Expand Up @@ -77,6 +79,7 @@ channelRouter.post(
channelRouter.post(
'/:channelId/guests',
[body('guests').isArray().withMessage('Guests must be an array')],
authenticateJWT,
validationMiddleware,
addGuestController,
);
Expand Down Expand Up @@ -108,6 +111,7 @@ channelRouter.post(
channelRouter.get(
'/:id',
[param('id').notEmpty().withMessage('Channel ID is required')],
authenticateJWT,
validationMiddleware,
getChannelInfoController,
);
Expand Down Expand Up @@ -182,6 +186,7 @@ channelRouter.get(
channelRouter.get(
'/user/:userId',
[param('userId').notEmpty().withMessage('User ID is required')],
authenticateJWT,
validationMiddleware,
getUserChannelsController,
);
6 changes: 2 additions & 4 deletions backend/src/services/channelService.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ export const getChannelByIdService = async id => {
try {
return await getChannelWithGuestsByIdFromDB(id);
} catch (error) {
console.error('Error fetching channel:', error);
throw error;
throw new Error('Error fetching channel', error);
}
};

Expand All @@ -89,8 +88,7 @@ export const getChannelGuestInfoService = async (channelId, guestId) => {
try {
return await getGuestByChannelAndGuestIdFromDB(channelId, guestId);
} catch (error) {
console.error('Error fetching channel:', error);
throw error;
throw new Error('Error fetching channel', error);
}
};

Expand Down
54 changes: 51 additions & 3 deletions backend/src/websocketServer.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
import { WebSocketServer } from 'ws';

const activeConnections = {}; // token별로 연결을 관리하기 위한 객체
const clientLocations = {};

export const initializeWebSocketServer = server => {
const wss = new WebSocketServer({ server });
const wss = new WebSocketServer({
server,
verifyClient: (info, done) => {
const { origin } = info;

if (origin === 'http://localhost:5173' || origin === 'https://ddara.kro.kr') {
done(true);
} else {
done(false, 403, 'Forbidden: Origin not allowed');
}
},
});

wss.on('error', err => {
console.error('WebSocket Server Error:', err);
});

wss.on('connection', (ws, req) => {
// URL에서 token 추출
// TODO: 프론트 라우터 및 token 설정 완료 후 테스트
const url = new URL(req.url, `http://${req.headers.host}`);
const url = new URL(req.url, `https://${req.headers.host}`);
const token = url.searchParams.get('token');

if (!token) {
Expand All @@ -26,16 +42,48 @@ export const initializeWebSocketServer = server => {

console.log(`Client connected with token: ${token}`);

// 새 클라이언트에게 기존 클라이언트의 위치 전송
ws.send(
JSON.stringify({
type: 'init',
clients: Object.entries(clientLocations).map(([clientToken, location]) => ({
token: clientToken,
location,
})),
}),
);

// 클라이언트로부터 메시지 받았을 때의 이벤트 처리
ws.on('message', message => {
console.log(`Received from ${token}:`, message);
try {
const data = JSON.parse(message);
if (data.type === 'location' && data.location) {
clientLocations[token] = data.location;

// 모든 클라이언트에게 위치 정보 전송
Object.keys(activeConnections).forEach(otherToken => {
if (activeConnections[otherToken].readyState === ws.OPEN) {
activeConnections[otherToken].send(
JSON.stringify({
type: 'location',
token,
location: data.location,
}),
);
}
});
}
} catch (err) {
console.error('Invalid message format:', err);
}
});

// 클라이언트 연결 종료 시
ws.on('close', (code, reason) => {
console.log(`Client disconnected with token: ${token}, Code: ${code}, Reason: ${reason}`);
// 연결이 종료되면 activeConnections에서 해당 token 제거
delete activeConnections[token];
delete clientLocations[token];
});
});
};
Loading

0 comments on commit 66099e0

Please sign in to comment.