이전 글에서는 웹 UI 개선 이후 앱(WebView)에서 발생한 UI 충돌 문제와,
그 문제를 인식하게 된 배경을 회고 중심으로 정리했습니다. 궁금하시면 아래의 링크에서 확인해보실 수 있어요!
[모아동] 웹에서는 괜찮았는데 앱에서는 깨졌다 - WebView와 앱 버전의 문제
모아동은 웹 서비스지만, React Native 기반 앱에서도 WebView를 통해 주요 화면을 함께 사용하고 있습니다.특히 동아리 상세페이지부터는 웹뷰를 그대로 공유하는 구조입니다. 저는 웹을 주로 개발
suhyun113.tistory.com
이번 글에서는 그 문제를 해결하기 위해 실제로 적용했던 웹뷰 라우트 분리 설계와 그 구현 방식에 대해 정리해보았습니다.
하나의 라우트, 서로 다른 버전의 사용자
모아동은 웹 서비스이지만, React Native 기반의 앱에서도 WebView를 통해 상세페이지를 공유하고 있습니다.
기존의 구조는 단순했습니다.
웹과 앱 모두 /club/:clubId 로 통일된 라우트를 사용했었습니다.
상세페이지 UI는 하나였고, 앱은 웹을 그대로 WebView로 노출하는 방식이었습니다.
이 방식이 기존에는 문제가 없었지만, 웹 상세페이지 UI를 전체적으로 개선하면서 발생했습니다.

위의 이미지처럼 웹에서는 신규 UI가 정상적으로 노출되었지만,
앱에서는 앱 자체의 탑바와 웹 UI 상단 영역이 겹치면서 스크롤 시 탑바가 두 개처럼 보이는 문제가 발생했습니다.
그 원인은 UI 자체가 아니라 접근하는 사용자들의 앱 버전 차이에 있었습니다.
웹은 항상 최신 상태를 사용자에게 보여주기 때문에 신경쓰지 못 한 부분이었습니다.
앱에서는 업데이트하지 않은 사용자는 이전 버전을 보는 시스템이기 때문에, 업데이트한 사용자와 업데이트하지 않은 사용자가 동시에 다른 UI를 바라보게 되는 것이었습니다. 따라서 업데이트하지 않은 사용자를 위해 이전 버전에서도 정상적인 UI가 필요한데, 이를 고려하지 않고 만들어버려서 앱에서는 업데이트하지 않은 사용자가 위와 같은 잘못된 UI를 보게 된 것입니다.
이를 해결하기 위해 업데이트한 사용자와 업데이트하지 않은 사용자가 동시에 정상적인 UI를 바라볼 수 있도록 서로 다른 앱 버전이 동시에 존재하도록 해야했습니다.
즉, 현재는 이 모든 사용자들이 같은 URL인 /club/:clubId로 접근하고 있었기 때문에 발생하는 문제였습니다.
"같은 라우트에서 모든 버전을 처리하지 말자"
이 문제를 해결하기 위해서 가장 먼저 정리한 원칙은 다음과 같았습니다.
하나의 라우트에서 서로 다른 버전의 사용자를 처리하려 하지 말자.
즉, 라우트 자체를 분리하여 각 사용자들이 의도된 UI만 접근하도록 만드는 방식을 선택하기로 했습니다.
업데이트하지 않은 사용자는 이전 버전의 UI를 바라보도록 하며,
모든 사용자가 업데이트를 마치면 이전 버전의 UI를 제거하는 방식으로 관리하는 것입니다.
따라서 라우트 분리는 아래와 같은 기준으로 설계했습니다.
- 앱을 업데이트하지 않은 사용자 UX 보호
- 웹과 신규 앱 사용자에게는 신규 UI 제공
- 추후 레거시 UI 제거가 가능한 구조
최종 라우트 구조
최종적으로 라우트는 레거시 상세페이지, 웹 전용 신규 상세페이지, 신규 앱 전용 상세페이지 3개로 분리했습니다.
1️⃣ 레거시 상세페이지 (기존 앱 사용자 보호)
{/* 기존 웹 & 안드로이드 (v1.1.0 이하) */}
<Route
path="/club/:clubId"
element={
<Suspense fallback={null}>
<LegacyClubDetailPage />
</Suspense>
}
/>
앱을 업데이트하지 않은 사용자가 접근하도록 하는 라우트입니다.
임시로 추가한 라우트로 구버전 앱 사용자가 모두 업데이트를 마치면 제거할 생각으로 추가했습니다.
이렇게 분리했을 때, 앱 탑바와 충돌하지 않는 기존 UI로 유지되어 UI가 깨지지 않는 것을 최우선 목표로 두었습니다.
완전히 레거시 라우트로 생성했으며, 신규 기능이나 UI 개선은 적용하지 않았습니다.
2️⃣ 웹 전용 신규 상세페이지 (임시 라우트)
{/* 웹 유저에게 신규 상세페이지를 제공하기 위한 임시 URL */}
<Route
path="/clubDetail/:clubId"
element={
<Suspense fallback={null}>
<ClubDetailPage />
</Suspense>
}
/>
웹 사용자에게 신규 UI를 즉시 보여주도록 하는 라우트입니다.
앱에서는 사용하지 않는 라우트로, 웹 배포를 지연시키지 않기 위한 임시 분리입니다.
웹 전용 라우트로, 앱에서는 접근하지 않도록 관리했습니다.
3️⃣ 신규 앱(WebView) 전용 상세페이지
{/* 신규 빌드된 앱에서만 사용하는 WebView 전용 라우트 */}
<Route
path="/webview/club/:clubId"
element={
<Suspense fallback={null}>
<ClubDetailPage />
</Suspense>
}
/>
신규 앱 버전에서만 사용하는 WebView 라우트입니다.
앱 탑바 구조를 고려한 신규 UI로 신규 UI를 적용했을 때 겹치던 탑바 문제를 해결한 버전입니다.
앱 탑바를 제거한 버전이므로, 신규 UI를 적용해도 UI가 깨지지 않도록 했습니다.
앱 업데이트를 완료한 사용자만 접근 가능하도록 하였으며, RN 앱에서 WebView URL을 이 경로로 변경함으로써
신규 UI는 오직 업데이트된 앱에서만 노출되도록 했습니다.
최종 결과

라우트를 분리한 결과, 위의 이미지처럼 왼쪽의 앱 화면에서 UX 깨짐 현상이 사라졌습니다.
업데이트된 사용자의 화면으로 기존 앱 탑바가 사라지고, 개선된 UI가 적용된 모습으로 잘 보이는 것을 확인할 수 있었습니다.
오른쪽의 화면 2개는 모바일 웹 화면인데, 스크롤 전과 후 모두 새로운 UI가 잘 적용된 것을 확인할 수 있습니다.
이번 웹뷰 라우트 분리는 단순히 URL을 나눈 작업이 아니라,
웹과 앱이 서로 다른 배포 단위를 가진다는 사실을 구조적으로 알게되었고 그에 대한 선택이었습니다.
하나의 라우트에서 모든 사용자를 처리하려고 하기보다,
사용자 그룹(웹/업데이트된 앱/업데이트되지 않은 앱)을 라우트 레벨에서 명확히 분리하면서 문제를 해결할 수 있었습니다.
레거시 페이지를 유지해야 하는 비용과 라우트 관리 부담이 분명 존재하겠지만,
앱 업데이트과 완료되면 자연스럽게 정리될 수 있는 일시적인 문제로, 당장의 UX 개선을 위해서는 이렇게 수정하는 방향이 맞다고 생각했습니다.
이번 경험을 통해 개인적으로 가장 크게 느낀 부분은 웹과 앱을 함께 운영한다는 것이 마음대로 배포할 수 없다는 뜻임을 알게된 것 같습니다. 웹처럼 배포한다고 곧바로 모든 사용자에게 적용될 것이라 생각했던 전제가 완전히 깨졌고,,, 앱에는 버전이 있고 사용자별로 각각 다른 상태에 있다는 사실을 체감하게 된 것 같습니다.
라우트를 나눠서 관리한다는 접근 방식도 처음에는 낯설어서 이해하기 어려웠지만, 선배들과 함께 이야기하며 프로그래밍하니 점차 이해가 되었고, 문제를 명확히 분리하고 책임 범위를 나눌 수 있는 방법이어서 새로운 방식을 배울 수 있었습니다.
웹과 앱의 경계에서 생길 수 있는 문제를 실제로 겪어보며, 구조로 문제를 해결하는 방식에 대해 공부해볼 수 있었습니다!
'프로젝트 > 모아동' 카테고리의 다른 글
| [모아동] 웹에서는 괜찮았는데 앱에서는 깨졌다 - WebView와 앱 버전의 문제 (1) | 2026.02.01 |
|---|---|
| [모아동] 탭 전환 UX 개선을 Lighthouse로 측정하려다 막혔던 이유 (0) | 2026.01.31 |
| [모아동] React 탭 전환 시 이미지 로딩이 느린 이유와 UX 개선 방법 (0) | 2026.01.29 |