// 상태 및 참조 변수 선언
const [notification, setNotification] = useState<InviteWebSocketMessage | null>(null);
const hasSubscribed = useRef(false);
// 1. 소켓 연결 전용 useEffect
useEffect(() => {
if (!isConnected) connectWebSocket();
}, []);
// 2. 구독 등록용 useEffect (한 번만 실행)
useEffect(() => {
if (!isConnected || hasSubscribed.current) return;
hasSubscribed.current = true;
subscribeToNotification(userId, (message: InviteWebSocketMessage) => {
console.log('Notification received:', message);
setNotification(message);
});
}, [isConnected]);
// 3. 메시지 처리용 useEffect (notification 상태 변경 시)
useEffect(() => {
if (!notification) return;
if (notification.messageType === 'INVITE_PLAYER') {
const inviteMessage = notification;
if (inviteMessage.payload.action === 'INVITE') {
console.log('Invite notification received:', inviteMessage.payload);
InviteNotificationToast({
senderNickname: inviteMessage.payload.senderNickname,
targetNickname: inviteMessage.payload.targetNickname,
roomName: inviteMessage.payload.roomName,
onAccept: () => {
console.log('Invitation accepted:', inviteMessage.payload);
// 서버 API 호출, 소켓 이벤트 등 처리
},
onDecline: () => {
console.log('Invitation declined:', inviteMessage.payload);
// 서버 API 호출, 소켓 이벤트 등 처리
},
});
}
}
}, [notification]);
hasSubscribed
라는 useRef 변수를 사용하여, 구독 등록 로직이 한 번만 실행되도록 합니다.
hasSubscribed.current
값을 확인하여 구독이 이미 등록되었는지 판단합니다.hasSubscribed.current
를 true로 변경하여, 이후 중복 구독을 방지합니다.이처럼 useRef를 활용하면 렌더링과 상관없이 값이 유지되며, 중복 실행을 효과적으로 막을 수 있습니다.