From 63d2deeecf92ca40b7af1fcd1202339d601c0664 Mon Sep 17 00:00:00 2001 From: manNomi Date: Tue, 26 May 2026 17:36:53 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=EC=B1=84=ED=8C=85=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=B0=8C?= =?UTF-8?q?=EA=B7=B8=EB=9F=AC=EC=A7=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChatContent/_ui/ChatMessageBox/index.tsx | 28 +++++++++---------- .../src/components/ui/ProfileWithBadge.tsx | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/apps/web/src/app/mentor/chat/[chatId]/_ui/ChatContent/_ui/ChatMessageBox/index.tsx b/apps/web/src/app/mentor/chat/[chatId]/_ui/ChatContent/_ui/ChatMessageBox/index.tsx index 182a9bf8..e749e580 100644 --- a/apps/web/src/app/mentor/chat/[chatId]/_ui/ChatContent/_ui/ChatMessageBox/index.tsx +++ b/apps/web/src/app/mentor/chat/[chatId]/_ui/ChatContent/_ui/ChatMessageBox/index.tsx @@ -180,14 +180,14 @@ const ChatMessageBox = ({ }; return isMine ? ( -
-
-
-
- {formatTime(message.createdAt)} -
+
+
+
+
+ {formatTime(message.createdAt)} +
{shouldShowContent(messageType) && ( -

{message.content}

+

{message.content}

)} {renderAttachments()}
@@ -196,19 +196,19 @@ const ChatMessageBox = ({
) : ( -
-
+
+
-
+
{partnerNickname} -
-
+
+
{shouldShowContent(messageType) && ( -

{message.content}

+

{message.content}

)} {renderAttachments()}
- {formatTime(message.createdAt)} + {formatTime(message.createdAt)}
diff --git a/apps/web/src/components/ui/ProfileWithBadge.tsx b/apps/web/src/components/ui/ProfileWithBadge.tsx index 48528a05..e0d7ffda 100644 --- a/apps/web/src/components/ui/ProfileWithBadge.tsx +++ b/apps/web/src/components/ui/ProfileWithBadge.tsx @@ -26,7 +26,7 @@ const ProfileWithBadge = ({ const iconSize = Math.round(badgeSize * 0.67); return ( -
+
{/* 프로필 이미지 */}
Date: Tue, 26 May 2026 17:41:57 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EC=B1=84=ED=8C=85=20=EC=A0=84?= =?UTF-8?q?=EC=86=A1=20=EC=8B=9C=20=ED=95=98=EB=8B=A8=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChatContent/_hooks/useChatListHandler.ts | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/apps/web/src/app/mentor/chat/[chatId]/_ui/ChatContent/_hooks/useChatListHandler.ts b/apps/web/src/app/mentor/chat/[chatId]/_ui/ChatContent/_hooks/useChatListHandler.ts index 9187e38f..bdd37c17 100644 --- a/apps/web/src/app/mentor/chat/[chatId]/_ui/ChatContent/_hooks/useChatListHandler.ts +++ b/apps/web/src/app/mentor/chat/[chatId]/_ui/ChatContent/_hooks/useChatListHandler.ts @@ -37,10 +37,18 @@ const useChatListHandler = (chatId: number) => { const hasInitialAutoScrolledRef = useRef(false); const prevMessageCountRef = useRef(0); const prevChatIdRef = useRef(chatId); + const shouldForceScrollToBottomRef = useRef(false); const imagePreviewByUrlRef = useRef>(new Map()); const objectUrlsRef = useRef([]); const queryClient = useQueryClient(); + const scrollToBottom = useCallback(() => { + const container = scrollContainerRef.current; + if (!container) return; + + container.scrollTop = container.scrollHeight; + }, []); + // --- 2. 하위 Hooks 호출 --- // API를 통해 채팅 기록을 페이지 단위로 가져옵니다. @@ -173,6 +181,7 @@ const useChatListHandler = (chatId: number) => { prevChatIdRef.current = chatId; hasInitialAutoScrolledRef.current = false; prevMessageCountRef.current = 0; + shouldForceScrollToBottomRef.current = false; }, [chatId]); // 초기 히스토리 로딩 완료 후, 최초 1회만 하단으로 이동합니다. @@ -182,18 +191,15 @@ const useChatListHandler = (chatId: number) => { } const rafId = requestAnimationFrame(() => { - const container = scrollContainerRef.current; - if (!container) return; - - container.scrollTop = container.scrollHeight; + scrollToBottom(); hasInitialAutoScrolledRef.current = true; prevMessageCountRef.current = submittedMessages.length; }); return () => cancelAnimationFrame(rafId); - }, [isLoading, isFetchingNextPage, submittedMessages.length]); + }, [isLoading, isFetchingNextPage, scrollToBottom, submittedMessages.length]); - // 신규 메시지 도착 시, 사용자가 하단 근처에 있을 때만 자동으로 하단을 유지합니다. + // 신규 메시지 도착 시 하단 근처라면 유지하고, 내가 보낸 메시지는 현재 위치와 무관하게 하단으로 이동합니다. useEffect(() => { if (isLoading || isFetchingNextPage) return; @@ -217,21 +223,21 @@ const useChatListHandler = (chatId: number) => { } const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight; + const shouldForceScrollToBottom = shouldForceScrollToBottomRef.current; - if (distanceFromBottom <= BOTTOM_PROXIMITY_THRESHOLD) { + if (shouldForceScrollToBottom || distanceFromBottom <= BOTTOM_PROXIMITY_THRESHOLD) { const rafId = requestAnimationFrame(() => { - const target = scrollContainerRef.current; - if (!target) return; - target.scrollTop = target.scrollHeight; + scrollToBottom(); }); + shouldForceScrollToBottomRef.current = false; prevMessageCountRef.current = currentMessageCount; return () => cancelAnimationFrame(rafId); } prevMessageCountRef.current = currentMessageCount; - }, [isLoading, isFetchingNextPage, submittedMessages.length]); + }, [isLoading, isFetchingNextPage, scrollToBottom, submittedMessages.length]); // --- 4. Handler 함수 --- @@ -246,12 +252,14 @@ const useChatListHandler = (chatId: number) => { destination: `/publish/chat/${chatId}`, body: JSON.stringify({ content, senderId }), }); + shouldForceScrollToBottomRef.current = true; + requestAnimationFrame(scrollToBottom); invalidateChatPreviewQueries(); } else { // 여기에 메시지 전송 실패에 대한 UI 피드백 로직을 추가할 수 있습니다. (e.g., alert, toast) } }, - [chatId, connectionStatus, invalidateChatPreviewQueries], + [chatId, connectionStatus, invalidateChatPreviewQueries, scrollToBottom], ); // chatId와 connectionStatus가 변경될 경우에만 함수를 재생성 const sendImageMessage = useCallback( @@ -312,7 +320,10 @@ const useChatListHandler = (chatId: number) => { }); } }); - if (newMessages.length > 0) setSubmittedMessages((prev) => [...prev, ...newMessages]); + if (newMessages.length > 0) { + shouldForceScrollToBottomRef.current = true; + setSubmittedMessages((prev) => [...prev, ...newMessages]); + } return previewUrls; }, [setSubmittedMessages], @@ -366,7 +377,10 @@ const useChatListHandler = (chatId: number) => { }); } }); - if (newMessages.length > 0) setSubmittedMessages((prev) => [...prev, ...newMessages]); + if (newMessages.length > 0) { + shouldForceScrollToBottomRef.current = true; + setSubmittedMessages((prev) => [...prev, ...newMessages]); + } }, [setSubmittedMessages], );