Skip to content

Commit 09feeb0

Browse files
authored
refactor: 긴 메소드의 코드를 여러 private 메소드로 분리 (#387)
- connect()에 있던 socket event listening 로직을 constructor로 옮깁니다. - `#` 대신 private 제한자를 씁니다.
1 parent aa15ac6 commit 09feeb0

File tree

1 file changed

+111
-85
lines changed

1 file changed

+111
-85
lines changed

client/src/utils/rtc/index.ts

Lines changed: 111 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ type onMediaDisconnectedCb = (socketId: string) => void;
77

88
class RTC {
99
static BITRATE = Number(env.WEBRTC_VIDEO_BITRATE);
10+
1011
private socket: Socket;
1112
private iceServerUrls: string[];
1213
private userMediaStream: MediaStream;
@@ -27,6 +28,28 @@ class RTC {
2728
this.streams = new Map();
2829
this.onMediaConnectedCallback = () => {}; // eslint-disable-line @typescript-eslint/no-empty-function
2930
this.onMediaDisconnectedCallback = () => {}; // eslint-disable-line @typescript-eslint/no-empty-function
31+
32+
this.socket.on(
33+
WORKSPACE_EVENT.RECEIVE_HELLO,
34+
this.sendOfferOnHello.bind(this),
35+
);
36+
this.socket.on(
37+
WORKSPACE_EVENT.RECEIVE_OFFER,
38+
this.sendAnswerOnOffer.bind(this),
39+
);
40+
this.socket.on(
41+
WORKSPACE_EVENT.RECEIVE_ANSWER,
42+
this.setRemotePeerOnAnswer.bind(this),
43+
);
44+
this.socket.on(WORKSPACE_EVENT.RECEIVE_ICE, this.addIce.bind(this));
45+
this.socket.on(
46+
WORKSPACE_EVENT.RECEIVE_BYE,
47+
this.cleanUpRemoteAndEmitMediaDisconnectedEvent.bind(this),
48+
);
49+
}
50+
51+
connect() {
52+
this.socket.emit(WORKSPACE_EVENT.SEND_HELLO);
3053
}
3154

3255
onMediaConnected(callback: onMediaConnectedCb) {
@@ -37,41 +60,110 @@ class RTC {
3760
this.onMediaDisconnectedCallback = callback;
3861
}
3962

40-
#createPeerConnection(remoteSocketId: string) {
63+
private async sendOfferOnHello(remoteSocketId: string) {
64+
const pc = this.createPeerConnection(remoteSocketId);
65+
66+
const offer = await pc.createOffer();
67+
await pc.setLocalDescription(offer);
68+
69+
this.socket.emit(WORKSPACE_EVENT.SEND_OFFER, offer, remoteSocketId);
70+
}
71+
72+
private async sendAnswerOnOffer(
73+
offer: RTCSessionDescriptionInit,
74+
remoteSocketId: string,
75+
) {
76+
const pc = this.createPeerConnection(remoteSocketId);
77+
await pc.setRemoteDescription(offer);
78+
79+
const answer = await pc.createAnswer();
80+
await pc.setLocalDescription(answer);
81+
82+
this.setVideoBitrate(pc, RTC.BITRATE);
83+
84+
this.socket.emit(WORKSPACE_EVENT.SEND_ANSWER, answer, remoteSocketId);
85+
}
86+
87+
private async setRemotePeerOnAnswer(
88+
answer: RTCSessionDescriptionInit,
89+
remoteSocketId: string,
90+
) {
91+
const pc = this.connections.get(remoteSocketId);
92+
if (!pc) {
93+
throw new Error('No RTCPeerConnection on answer received.');
94+
}
95+
96+
await pc.setRemoteDescription(answer);
97+
98+
this.setVideoBitrate(pc, RTC.BITRATE);
99+
}
100+
101+
private addIce(ice: RTCIceCandidateInit, remoteSocketId: string) {
102+
const pc = this.connections.get(remoteSocketId);
103+
if (!pc) {
104+
throw new Error('No RTCPeerConnection on ice candindate received.');
105+
}
106+
107+
pc.addIceCandidate(ice);
108+
}
109+
110+
private cleanUpRemoteAndEmitMediaDisconnectedEvent(remoteSocketId: string) {
111+
this.connections.delete(remoteSocketId);
112+
this.streams.delete(remoteSocketId);
113+
114+
this.onMediaDisconnectedCallback(remoteSocketId);
115+
}
116+
117+
private createPeerConnection(remoteSocketId: string) {
41118
// initialize
42119
const pcOptions = {
43120
iceServers: [{ urls: this.iceServerUrls }],
44121
};
45122
const pc = new RTCPeerConnection(pcOptions);
46123

47124
// add event listeners
48-
pc.addEventListener('icecandidate', (iceEvent) => {
49-
this.socket.emit(
50-
WORKSPACE_EVENT.SEND_ICE,
51-
iceEvent.candidate,
52-
remoteSocketId,
53-
);
54-
});
55-
pc.addEventListener('track', async (event) => {
56-
if (this.streams.has(remoteSocketId)) {
57-
return;
58-
}
59-
60-
const [remoteStream] = event.streams;
61-
62-
this.streams.set(remoteSocketId, remoteStream);
63-
this.onMediaConnectedCallback(remoteSocketId, remoteStream);
64-
});
125+
const emitIce: (iceEvent: RTCPeerConnectionIceEvent) => void =
126+
this.emitIce.bind(this, remoteSocketId);
127+
pc.addEventListener('icecandidate', emitIce);
128+
129+
const setRemoteTrack: (trackEvent: RTCTrackEvent) => void =
130+
this.setRemoteTrackAndEmitMediaConnectedEvent.bind(this, remoteSocketId);
131+
pc.addEventListener('track', setRemoteTrack);
65132

66133
// add tracks
67134
this.userMediaStream
68135
.getTracks()
69136
.forEach((track) => pc.addTrack(track, this.userMediaStream));
70137

138+
// register connection
139+
this.connections.set(remoteSocketId, pc);
140+
71141
return pc;
72142
}
73143

74-
async #setVideoBitrate(pc: RTCPeerConnection, bitrate: number) {
144+
private emitIce(remoteSocketId: string, iceEvent: RTCPeerConnectionIceEvent) {
145+
this.socket.emit(
146+
WORKSPACE_EVENT.SEND_ICE,
147+
iceEvent.candidate,
148+
remoteSocketId,
149+
);
150+
}
151+
152+
private setRemoteTrackAndEmitMediaConnectedEvent(
153+
remoteSocketId: string,
154+
trackEvent: RTCTrackEvent,
155+
) {
156+
if (this.streams.has(remoteSocketId)) {
157+
return;
158+
}
159+
160+
const [remoteStream] = trackEvent.streams;
161+
162+
this.streams.set(remoteSocketId, remoteStream);
163+
this.onMediaConnectedCallback(remoteSocketId, remoteStream);
164+
}
165+
166+
private async setVideoBitrate(pc: RTCPeerConnection, bitrate: number) {
75167
// fetch video sender
76168
const videoSender = pc
77169
.getSenders()
@@ -86,72 +178,6 @@ class RTC {
86178
params.encodings[0].maxBitrate = bitrate;
87179
await videoSender.setParameters(params);
88180
}
89-
90-
connect() {
91-
this.socket.on(WORKSPACE_EVENT.RECEIVE_HELLO, async (remoteSocketId) => {
92-
const pc = this.#createPeerConnection(remoteSocketId);
93-
this.connections.set(remoteSocketId, pc);
94-
95-
const offer = await pc.createOffer();
96-
await pc.setLocalDescription(offer);
97-
98-
this.socket.emit(
99-
WORKSPACE_EVENT.SEND_OFFER,
100-
pc.localDescription,
101-
remoteSocketId,
102-
);
103-
});
104-
105-
this.socket.on(
106-
WORKSPACE_EVENT.RECEIVE_OFFER,
107-
async (offer, remoteSocketId) => {
108-
const pc = this.#createPeerConnection(remoteSocketId);
109-
this.connections.set(remoteSocketId, pc);
110-
111-
await pc.setRemoteDescription(offer);
112-
113-
const answer = await pc.createAnswer();
114-
await pc.setLocalDescription(answer);
115-
116-
this.#setVideoBitrate(pc, RTC.BITRATE);
117-
118-
this.socket.emit(WORKSPACE_EVENT.SEND_ANSWER, answer, remoteSocketId);
119-
},
120-
);
121-
122-
this.socket.on(
123-
WORKSPACE_EVENT.RECEIVE_ANSWER,
124-
async (answer, remoteSocketId) => {
125-
const pc = this.connections.get(remoteSocketId);
126-
if (!pc) {
127-
throw new Error('No RTCPeerConnection on answer received.');
128-
}
129-
130-
await pc.setRemoteDescription(answer);
131-
132-
this.#setVideoBitrate(pc, RTC.BITRATE);
133-
},
134-
);
135-
136-
this.socket.on(WORKSPACE_EVENT.RECEIVE_ICE, (ice, remoteSocketId) => {
137-
const pc = this.connections.get(remoteSocketId);
138-
139-
if (!pc) {
140-
throw new Error('No RTCPeerConnection on ice candindate received.');
141-
}
142-
143-
pc.addIceCandidate(ice);
144-
});
145-
146-
this.socket.on(WORKSPACE_EVENT.RECEIVE_BYE, (remoteSocketId) => {
147-
this.connections.delete(remoteSocketId);
148-
this.streams.delete(remoteSocketId);
149-
150-
this.onMediaDisconnectedCallback(remoteSocketId);
151-
});
152-
153-
this.socket.emit(WORKSPACE_EVENT.SEND_HELLO);
154-
}
155181
}
156182

157183
export default RTC;

0 commit comments

Comments
 (0)