@@ -39,6 +39,9 @@ const NewsDetailPage = () => {
3939 const [ showErrorToast , setShowErrorToast ] = useState ( false ) ;
4040 const [ errorMessage , setErrorMessage ] = useState ( '' ) ;
4141 const socketRef = useRef ( null ) ;
42+ const reconnectAttemptsRef = useRef ( 0 ) ;
43+ const MAX_RECONNECT_ATTEMPTS = 3 ;
44+ const RECONNECT_DELAY = 5000 ; // 5초
4245 const [ highlightSegments , setHighlightSegments ] = useState ( [ ] ) ;
4346
4447 // 인용구 클릭 시 해당 문단으로 스크롤 이동하는 함수
@@ -101,34 +104,91 @@ const NewsDetailPage = () => {
101104 fetchNewsDetail ( ) ;
102105 } , [ params . id ] ) ;
103106
107+ const connectWebSocket = ( ) => {
108+ return new Promise ( ( resolve , reject ) => {
109+ const socket = new SockJS ( SOCKET_CONFIG . ENDPOINT ) ;
110+ const client = Stomp . over ( socket ) ;
111+
112+ client . connect (
113+ { type : SOCKET_CONNECTION_TYPE . PUBLIC } ,
114+ ( ) => resolve ( client ) ,
115+ ( error ) => reject ( error )
116+ ) ;
117+ } ) ;
118+ } ;
119+
120+ const subscribeToChat = ( client ) => {
121+ return new Promise ( ( resolve ) => {
122+ client . subscribe ( `/topic/chat.${ params . id } .count` , ( { body } ) => {
123+ const { count } = JSON . parse ( body ) ;
124+ setUserCount ( count ) ;
125+ } ) ;
126+ resolve ( client ) ;
127+ } ) ;
128+ } ;
129+
130+ const initializeChatCount = ( client ) => {
131+ client . send (
132+ `/app/chat.initCount.${ params . id } ` ,
133+ { } ,
134+ ""
135+ ) ;
136+ } ;
137+
138+ const setupConnectionCloseHandler = ( client ) => {
139+ client . onWebSocketClose = ( event ) => {
140+ console . log ( "WebSocket 연결이 종료되었습니다." , event ) ;
141+
142+ if ( event . code === 1002 ) {
143+ console . log ( "의도하지 않은 연결 종료 (code: 1002), 재연결 시도" ) ;
144+
145+ if ( reconnectAttemptsRef . current < MAX_RECONNECT_ATTEMPTS ) {
146+ reconnectAttemptsRef . current += 1 ;
147+ console . log ( `재연결 시도 ${ reconnectAttemptsRef . current } /${ MAX_RECONNECT_ATTEMPTS } ` ) ;
148+
149+ setTimeout ( async ( ) => {
150+ try {
151+ const newClient = await connectWebSocket ( ) ;
152+ await subscribeToChat ( newClient ) ;
153+ initializeChatCount ( newClient ) ;
154+ setupConnectionCloseHandler ( newClient ) ;
155+ socketRef . current = newClient ;
156+ reconnectAttemptsRef . current = 0 ; // 재연결 성공 시 카운트 초기화
157+ } catch ( error ) {
158+ console . error ( "WebSocket 재연결 실패:" , error ) ;
159+ if ( reconnectAttemptsRef . current >= MAX_RECONNECT_ATTEMPTS ) {
160+ setErrorMessage ( '연결이 불안정합니다. 페이지를 새로고침해주세요.' ) ;
161+ setShowErrorToast ( true ) ;
162+ }
163+ }
164+ } , RECONNECT_DELAY ) ;
165+ } else {
166+ setErrorMessage ( '연결이 불안정합니다. 페이지를 새로고침해주세요.' ) ;
167+ setShowErrorToast ( true ) ;
168+ }
169+ }
170+ } ;
171+ } ;
172+
104173 useEffect ( ( ) => {
105174 if ( ! params . id ) return ;
106175 if ( socketRef . current ) return ;
107- // SockJS + STOMP 클라이언트 생성
108- const socket = new SockJS ( SOCKET_CONFIG . ENDPOINT ) ;
109- const client = Stomp . over ( socket ) ;
110-
111- client . connect (
112- { type : SOCKET_CONNECTION_TYPE . PUBLIC } ,
113- ( ) => {
114- // 인원 수 토픽 구독
115- client . subscribe ( `/topic/chat.${ params . id } .count` , ( { body } ) => {
116- const { count } = JSON . parse ( body ) ;
117- setUserCount ( count ) ;
118- } ) ;
119- // 채팅 인원 수 초기화
120- client . send (
121- `/app/chat.initCount.${ params . id } ` ,
122- { } ,
123- ""
124- ) ;
125- } , console . error
126- ) ;
127176
128- socketRef . current = client ;
177+ const initializeWebSocket = async ( ) => {
178+ try {
179+ const client = await connectWebSocket ( ) ;
180+ await subscribeToChat ( client ) ;
181+ initializeChatCount ( client ) ;
182+ setupConnectionCloseHandler ( client ) ;
183+ socketRef . current = client ;
184+ } catch ( error ) {
185+ console . error ( "WebSocket 초기 연결 실패:" , error ) ;
186+ }
187+ } ;
188+
189+ initializeWebSocket ( ) ;
129190
130191 return ( ) => {
131- // cleanup: 모든 구독 해제하고 연결 종료
132192 if ( socketRef . current ) {
133193 socketRef . current . disconnect ( ) ;
134194 socketRef . current = null ;
@@ -139,7 +199,7 @@ const NewsDetailPage = () => {
139199 // 채팅 에러 핸들러 추가
140200 const handleChatError = ( error ) => {
141201 console . log ( error ) ;
142- setErrorMessage ( '채팅 서비스 연결에 실패했습니다.' ) ;
202+ setErrorMessage ( '채팅 서비스 연결에 실패했습니다. 페이지 새로고침 후에 다시 시도해주세요. ' ) ;
143203 setShowErrorToast ( true ) ;
144204 setIsChatOpen ( false ) ;
145205 setIsChatLoading ( false ) ;
0 commit comments