[FIX] 채팅방 스크롤이 간헐적으로 하단까지 이동하지 않는 문제#1316
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
유경님, 코멘트 남겨주신 내용 정말 잘 읽었습니다!
이 이슈의 본질을 단순한 로딩 UX가 아니라 '초기 스크롤 계산을 위한 레이아웃 안정화' 로 짚어주신 인사이트가 정말 예리하다고 생각합니다. 또한, 짧은 로딩 구간에서 스켈레톤이 번쩍이는 현상이 오히려 시각적으로 거슬릴 수 있다는 점도 깊이 공감합니다. 문제의 핵심과 트레이드오프를 명확히 짚어주셔서 저도 뷰를 넓힐 수 있었어요.
다만, 레이아웃을 확보하기 위해 실제 컴포넌트를 마운트하고 mentorName="", price={0} 같은 더미 데이터를 주입하는 부분은 장기적인 코드 유지보수 관점에서 조금 우려되는 점이 있어 조심스레 의견을 보태봅니다.
당장은 안전하지만, 추후 다른 팀원이 MentoringActionPanel 내부에 DOM을 직접 참조하는 로직(useLayoutEffect)이나 특정 비동기/인터랙션 로직을 추가하게 된다면, 화면에 보이지 않는 섀도우 컴포넌트에서 예기치 못한 에러나 사이드 이펙트가 발생할 잠재적 위험이 될 수 있을 것 같습니다.
💡 제안 사항: CSS min-height + 지연된 스켈레톤(Deferred Skeleton)
유경님이 원하시는 '즉각적인 높이 확보' 와 '짧은 로딩 시의 깜빡임 방지' 를 모두 만족하면서도, 구조적으로 더 단단하게 가져갈 수 있는 방법은 어떨까요?
1. 지연 컴포넌트 (DeferredFallback) 구현
빠른 네트워크 환경에서 스켈레톤이 0.1초 만에 나타났다 사라지는 '번쩍임' 현상을 막기 위해, 일정 시간(예: 200ms) 동안은 렌더링을 지연시키는 유틸리티 컴포넌트입니다.
interface DeferredFallbackProps {
delay?: number;
}
function DeferredFallback({
children,
delay = 200,
}: PropsWithChildren<DeferredFallbackProps>) {
const [isDeferred, setIsDeferred] = useState(false);
useEffect(() => {
const timeoutId = setTimeout(() => setIsDeferred(true), delay);
return () => clearTimeout(timeoutId);
}, [delay]);
if (!isDeferred) {
return null;
}
return <>{children}</>;
}2. 실제 적용 (레이아웃 안정화 + 지연 로딩)
DeferredFallback이 200ms 동안 null을 반환할 때 높이가 0이 되어 초기 스크롤 계산이 다시 어긋나는 것을 방지하기 위해, 해당 영역을 감싸는 래퍼(Wrapper)에 예상 높이를 미리 부여합니다.
<S_Container>
{chatRoomInfoIsPending || !chatRoomInfoData ? (
// 로딩 중에만 렌더링되는 Wrapper에 예상 높이(예: min-height: 11rem)를 확보하여 스크롤 어긋남 방지
<S_LoadingHeaderArea>
<DeferredFallback delay={200}>
<ChatRoomInfoSkeleton />
</DeferredFallback>
</S_LoadingHeaderArea>
) : (
<div>
<ChatRoomHeader name={chatRoomInfoData.opponentName} />
<MentoringActionPanel
mentorName={chatRoomInfoData.mentorName}
price={chatRoomInfoData.price}
profileImageUrl={chatRoomInfoData.profileImageUrl}
mentorOwned={chatRoomInfoData.myRole === 'MENTOR'}
onPaymentRequestClick={handlePaymentRequestClick}
onReviewRequestClick={handleReviewRequestClick}
onEndClick={handleEndClick}
onPaymentClick={handlePaymentClick}
onReviewClick={handleReviewClick}
/>
</div>
)}
...이렇게 하면 빈 껍데기 컴포넌트를 유지하는 부담을 줄이면서도, 유경님이 의도하신 스크롤 계산 버그 해결과 쾌적한 UX를 동시에 달성할 수 있을 것 같습니다.
스켈레톤을 관리해야 하는 비용이 약간 발생하긴 하지만, 컴포넌트의 역할과 책임을 명확히 분리하는 것이 장기적으로 더 유연한 코드가 될 것 같아 의견 남겨봅니다. 이 방식에 대해 어떻게 생각하시나요? 편하게 의견 나누어 주시면 감사하겠습니다! 🙏
|
특정 시간 내에 스켈레톤 렌더링을 지연하는 방식도 고려해보았지만, 현재 구현 수준에서도 기능적으로는 충분하다고 판단하여 적용하지는 않았습니다. 다만,
는 의견을 보고, 구조적으로 더 안전한 방향으로 개선하는 것이 맞겠다고 판단하였습니다. 생각지 못한 부분 짚어주셔서 감사합니다 추가 제안 사항Wrapper에 예상 높이를 두는 방식의 경우 반응형 환경에서 줄바꿈이나 레이아웃 변경이 발생하면, 로딩 중 화면과 실제 데이터 렌더링 이후 화면의 높이가 미묘하게 달라질 가능성도 있다고 생각했습니다. 그래서 종욱님의 의견에 더해, 스켈레톤이 실제 레이아웃과 1:1로 맞춰져 있다는 점을 활용하여, Wrapper에 예상 높이를 두기보다는 |
스켈레톤을 그대로 렌더링하되 일정 시간 이하에는 visibility로 제어하는 방식 너무 좋은 것 같습니다 👍👍 다양한 의견을 나누고 배울 수 있어서 좋았습니다 👍 |
- hidden 상태에서 실제 컴포넌트를 마운트하던 구조 제거 - 로딩 UI와 실제 로직을 분리해 잠재적 사이드이펙트 예방 - 스켈레톤에 delayed visibility를 적용해 로딩 깜빡임 방지
Issue Number
closed #1314
As-Is
To-Be
문제 원인
분석 방법
해결 방법
레이아웃 변동을 제거하기 위해 두 가지 방안을 검토하였습니다.
1️⃣ 스켈레톤 방식
(브랜치 받아서 테스트할때는
ChatRoomInfoSkeleton컴포넌트를 사용하시면 됩니다!)장점
단점
2️⃣ 실컴포넌트 렌더 +
visibility: hidden방식 (선택)ChatRoomHeader및MentoringActionPanel을 렌더visibility: hidden을 적용하여 레이아웃만 유지장점
단점
Check List
(Optional) Additional Description
이번 이슈의 본질은 “로딩 UX”보다는 레이아웃 안정화를 통한 스크롤 계산의 일관성 확보에 있다고 판단했습니다. 이에 따라 실제 컴포넌트를 렌더한 뒤 visibility: hidden으로 레이아웃만 유지하는 방식을 선택했습니다.
또한 해당 영역은 로딩 상태를 적극적으로 드러내야 하는 리스트 영역과는 짧은 로딩 구간에서 스켈레톤 UI를 노출하는 것보다는 레이아웃만 안정적으로 확보하는 방향이 더 적절하다고 보았습니다.
다른 방식이 더 적절하다고 판단되는 부분이 있다면 의견 주시면 감사하겠습니다!