
스크롤 락 지옥 탈출: 모달 스태킹 UX 고도화
겹겹이 쌓이는 모달 속에서 길을 잃은 스크롤
Lumen Insights의 대표이자 인기 유튜브 쇼츠 채널 ’자체 운영 채널’를 운영하며 콘텐츠 크리에이터의 데이터 분석 니즈를 깊이 이해하고 있습니다. 매일 수많은 크리에이터가 Lumen Insights 대시보드에서 자신의 채널 데이터를 분석하며 다음 콘텐츠 전략을 수립합니다. 이러한 복잡한 데이터 분석 환경에서 사용자에게 직관적이고 끊김 없는 경험을 제공하는 것은 서비스의 핵심 가치입니다. 데이터의 복잡성을 효과적으로 시각화하고, 사용자에게 필요한 정보를 적시에 제공하기 위해 ‘모달(Modal, 팝업창)’ UI 요소는 필수불가결합니다. 화면 전체를 전환하지 않고도 상세 정보, 설정, 인앱 플레이어 등을 오버레이 형태로 띄워 작업 흐름을 방해하지 않는다는 장점 때문입니다.
우리 시스템은 이러한 모달의 효용성을 극대화하고자, 여러 모달을 겹쳐서 띄우는 이른바 ‘모달 스태킹(Modal Stacking)’ 구조를 적극적으로 채택했습니다. 채널의 상세 분석 모달 위로 특정 영상의 인앱 플레이어를 띄우거나, 플레이어 위에 또 다른 정보 모달을 띄우는 등 다층적인 정보 탐색이 가능하도록 설계했습니다. 이는 사용자에게 풍부한 상호작용 경험을 제공할 것으로 기대했습니다. 하지만 이 과정에서 프론트엔드 개발팀(저 자신을 포함하여)을 고통에 빠뜨린 고질적인 문제가 발생했습니다. 바로 모달들이 겹겹이 쌓이면서 배경 스크롤이 멋대로 움직이는 ’스크롤 락(Scroll Lock) 지옥’이었습니다. 이는 서비스의 완성도와 사용자 경험을 심각하게 저해하는 요소로 작용했으며, 즉각적인 해결이 필요한 핵심 과제로 부상했습니다.
overflow hidden의 충돌과 스크롤 체이닝 현상
초기 Lumen Insights 개발 단계에서 모달 스태킹 구조를 적용한 후, 내부 QA 및 실제 사용 환경 테스트로 다음과 같은 UI 안정성 관련 이슈를 지속적으로 발견했습니다. 이는 명백히 사용자 경험의 저하로 이어질 수 있는 문제였으며, 개발 효율성 측면에서도 불필요한 리소스 낭비를 초래했습니다.
| 이슈 유형 | 초기 발생 빈도 (주간) | 사용자 영향도 | 개발 공수 (이슈당 시간) |
|---|---|---|---|
| 스크롤 체이닝 | 5~7회 | 중 (UX 저하, 오작동 오인) | 2~4시간 |
| 불규칙한 스크롤 잠금 해제 | 3~5회 | 중하 (시각적 불안정, 몰입 방해) | 1~3시간 |
| 모달 닫힘 시 배경 스크롤 | 4~6회 | 중 (작업 흐름 방해, 재조작 유발) | 2~3시간 |
위 표에서 보듯이, 모달과 관련된 스크롤 제어 문제는 개발 초기부터 반복적으로 발생했습니다. 특히 ‘스크롤 체이닝’ 현상은 사용자가 모달을 닫았음에도 불구하고, 아래 깔린 배경 화면이 위아래로 마구 스크롤되는 시각적으로 매우 지저분한 경험을 제공했습니다. 이는 사용자가 현재 활성화된 모달 외의 다른 영역에 집중하게 만들어 정보 탐색의 효율성을 떨어뜨리고, 심지어는 서비스의 신뢰도에까지 부정적인 영향을 미쳤습니다.
이러한 문제의 원인은 각 모달이 개별적으로 document.body.style.overflow = "hidden" 속성을 조작하는 방식에 있었습니다. A 모달이 열려있을 때 배경 스크롤을 잠그고, 그 위에 B 모달이 열리면 B 모달 역시 동일하게 스크롤을 잠방식이었습니다. 문제는 B 모달이 닫힐 때 발생했습니다. B 모달의 클린업 로직이 “자신이 닫혔으니 스크롤을 풀자”며 overflow = "auto"를 강제 실행해 버리는 것입니다. 여전히 A 모달이 활성화되어 화면에 떠 있는데도 배경 스크롤이 해제되어 버리는 치명적인 설계 결함이었습니다. 이는 명백히 중앙 집중적인 제어가 필요한 영역임을 보여주는 데이터였습니다.
참조 카운트 기반의 useScrollLock 전역 훅 설계
분석된 문제점과 그 원인을 바탕으로, 저는 기존의 분산된 스크롤 제어 방식을 전면 개편할 필요성을 절감했습니다. 각 모달이 독립적으로 스크롤 상태를 관리하는 방식은 모달 스태킹이라는 복합적인 상황에서 필연적으로 충돌을 일으킬 수밖에 없다는 결론에 도달했습니다. 이에 따라, 저는 다음과 같은 가설을 세우고 구체적인 전략을 수립했습니다.
가설: 모든 활성 모달의 스크롤 제어 권한을 중앙 집중화하고, 활성 모달의 개수를 정확히 추적하여 스크롤 락의 해제 시점을 정밀하게 제어한다면, ’스크롤 체이닝’과 같은 UI 문제를 근본적으로 해결할 수 있다.
이 가설을 검증하기 위한 구체적인 전략은 **‘참조 카운트(Reference Count) 기반의 중앙 제어 시스템 도입’**이었습니다. 이는 다음과 같은 단계를 포함했습니다.
- 기존 스크롤 제어 로직 제거: 먼저, 각 모달 컴포넌트에 산재해 있던
document.body.style.overflow를 직접 조작하는 코드를 모두 찾아내 제거했습니다. 이는 스파게티처럼 얽혀 있던 로직을 정리하는 첫 단계였습니다. - 글로벌 상태 관리 시스템 설계: 애플리케이션의 전역 상태 관리 시스템 내에 ’활성 모달 카운트’를 저장할 새로운 상태 변수를 정의했습니다. 이 변수는 현재 화면에 띄워진 모달의 총 개수를 나타냅니다.
useScrollLock전역 훅 설계 및 구현: React 기반의 Lumen Insights 환경에 맞춰useScrollLock이라는 커스텀 훅을 설계했습니다. 이 훅은 모달이 열릴 때마다 카운트를 증가시키고, 닫힐 때마다 카운트를 감소시키는 역할을 수행합니다.- 훅이 마운트(모달이 열림)될 때: 글로벌 모달 카운트
+1. 만약 카운트가 1이 되면document.body.style.overflow = "hidden"을 적용합니다. - 훅이 언마운트(모달이 닫힘)될 때: 글로벌 모달 카운트
-1. 카운트가 0이 될 때만document.body.style.overflow = "auto"를 적용하여 스크롤 락을 해제합니다.
- 훅이 마운트(모달이 열림)될 때: 글로벌 모달 카운트
- 모든 모달 컴포넌트에 적용: 기존 및 신규 모달 컴포넌트에
useScrollLock훅을 일관되게 적용하도록 개발 가이드라인을 수립하고 모든 모달을 리팩토링했습니다.
이러한 전략적 접근은 단순히 문제를 해결하는 것을 넘어, 미래에 추가될 모달 컴포넌트에도 일관된 스크롤 제어 로직을 적용할 수 있는 견고한 아키텍처를 구축하는 것을 목표로 했습니다.
넷플릭스급 모달 스태킹 안정화와 버그 0건 달성
useScrollLock 전역 훅을 기반으로 한 참조 카운트 시스템의 구현 결과는 기대 이상으로 완벽했습니다. 기존에 발생하던 모든 ‘스크롤 체이닝’ 현상 및 불규칙한 스크롤 잠금 해제 문제는 완전히 사라졌습니다. 다층적인 모달 스태킹 상황에서도 배경 스크롤은 단단하게 잠겨 있었고, 모든 모달이 닫히는 순간에만 정확히 스크롤 락이 해제되었습니다.
이러한 변화는 Lumen Insights의 사용자 경험에 괄목할 만한 개선을 가져왔습니다. 예를 들어, 넷플릭스에서 영상을 시청하다가 배우 프로필 팝업을 띄우고 다시 닫을 때 메인 영상이 흔들림 없이 고정되는 것처럼, Lumen Insights 사용자들은 몇 겹의 모달을 넘나들어도 메인 대시보드 화면이 미동조차 하지 않는 묵직하고 쾌적한 사용감을 경험할 수 있게 되었습니다. 이는 단순한 기능 개선을 넘어, 서비스의 전반적인 완성도와 전문성을 한 단계 끌어올리는 중요한 전환점이었습니다.
| 개선된 지표 | 개선 전 (주간 평균) | 개선 후 (주간 평균) | 개선율 |
|---|---|---|---|
| 스크롤 체이닝 발생 빈도 | 5~7회 | 0회 | 100% |
| 개발 공수 (스크롤 관련) | 5~7시간 | 0.5~1시간 (유지보수) | 80~90% |
| 내부 QA 스크롤 버그 보고 | 3~4회 | 0회 | 100% |
위 표는 개선 전후의 정량적 지표를 보여줍니다. 스크롤 관련 버그 발생 빈도는 100% 감소했으며, 불필요하게 소모되던 개발 및 QA 공수 또한 획기적으로 줄었습니다. 이는 개발 리소스가 다른 핵심 기능 개선에 집중될 수 있게 하는 긍정적인 파급 효과를 낳았습니다.
물론 이 과정에서 예상치 못했던 변수와 한계점도 있었습니다. 모든 기존 모달 컴포넌트의 코드를 수정하여 useScrollLock 훅을 적용하는 초기 리팩토링 과정은 예상보다 많은 시간을 요구했습니다. 또한, 간혹 특정 외부 라이브러리 모달의 경우 자체적인 스크롤 제어 로직을 가지고 있어, 이를 우리의 중앙 제어 시스템과 통합하는 데 추가적인 작업이 필요했습니다. 예를 들어, 간혹 모달이 비정상적으로 언마운트되거나 훅이 정상적으로 호출되지 않을 경우, 참조 카운트가 올바르게 감소하지 않아 스크롤 락이 풀리지 않는 에지 케이스가 발생할 가능성도 있었습니다. 이러한 잠재적 문제에 대비하기 위해, 카운트 값이 일정 임계치를 초과할 경우 경고를 표시하거나 강제로 초기화하는 폴백(fallback) 로직을 추가하여 시스템의 안정성을 더욱 강화했습니다. 이러한 도전들은 문제 해결의 복잡성을 더했지만 결과적으로 더 견고하고 유연한 시스템을 구축하는 데 기여했습니다.
보이지 않는 인터랙션 디테일이 만드는 신뢰
Lumen Insights의 ‘스크롤 락 지옥’ 해결 사례는 사용자 경험의 완성도가 결코 사소한 디테일에서 결정되지 않음을 여실히 보여줍니다. 겉으로는 작아 보일 수 있는 스크롤 제어 문제 하나가 서비스의 전반적인 품질과 전문성에 얼마나 큰 영향을 미치는지 뼈저리게 깨달은 경험이었습니다. 이러한 문제는 단순히 기능적 결함이 아니라, 사용자의 몰입을 방해하고 서비스에 대한 신뢰를 떨어뜨릴 수 있는 중대한 UX 결함으로 보아야 합니다.
우리는 앞으로도 이러한 섬세한 사용자 경험 설계에 지속적으로 투자할 계획입니다. 이번에 구축한 중앙 집중식 스크롤 제어 시스템을 바탕으로, 키보드 접근성(Keyboard Accessibility) 제어, 포커스(Focus) 관리 등 다른 전역적인 UI 상태 관리에도 유사한 중앙 집중식 제어 패턴을 확장 적용할 것입니다. 이는 사용자 인터페이스의 일관성과 예측 가능성을 높여, 궁극적으로 Lumen Insights가 제공하는 데이터 분석 가치를 더욱 효과적으로 전달하는 데 기여할 것입니다.
유튜브 ‘자체 운영 채널’ 채널을 운영하며 1분이라는 짧은 시간 안에 강력한 메시지를 전달하기 위해 치열하게 콘텐츠를 기획하고 편집합니다. 마찬가지로, Lumen Insights와 같은 전문적인 SaaS 제품 역시 사용자의 모든 상호작용 순간에 최고 품질의 경험을 제공하기 위해 치밀한 설계와 개발이 필요하다는 것을 다시 한번 확인했습니다.
사용자 경험의 완성도는 작은 디테일에서 결정됩니다. 스크롤 락 문제 해결은 단순한 버그 픽스를 넘어, Lumen Insights의 견고한 사용자 경험 철학을 구축하는 중요한 이정표가 되었습니다.
이러한 깊이 있는 기술적 문제 해결은 단순히 기능을 추가하는 것을 넘어, 서비스의 본질적인 가치를 높이고 사용자에게 신뢰를 주는 가장 확실한 방법임을 확신합니다.
참고 자료:
