Nuxt 3.8 업데이트 후 구형 WebView에서 발생한 App Manifest 에러 해결기

커버 이미지

Nuxt 3.8 업데이트 후, 구형 WebView에서 #app-manifest 에러가 터진 이유

Nuxt를 3.8로 올린 뒤부터 일부 iOS 브라우저/앱 내 WebView에서 라우팅이 꼬이기 시작했습니다. 브라우저에서는 멀쩡한데, 웹뷰에서만 페이지 이동이 멈추거나 빈 화면이 뜨고 콘솔에는 아래처럼 #app-manifest import 실패가 찍히는 상황이었어요.

ERROR  Pre-transform error: Failed to resolve import "#app-manifest" from "node_modules/nuxt/dist/app/composables/manifest.js". Does the file exist?
  Plugin: vite:import-analysis
  File: [PROJECT_ROOT]/node_modules/nuxt/dist/app/composables/manifest.js:13:23
  11 |    }
  12 |    if (false) {
  13 |      manifest = import("#app-manifest");
     |                        ^
  14 |    } else {
  15 |      manifest = $fetch(buildAssetsURL('[BUILD_ASSETS_PATH]/meta/[BUILD_ID].json'), { (x2)

결론부터 말하면, Nuxt 3.8에서 기본으로 켜진 experimental.appManifest가 특정 구형 WebView 엔진과 충돌하면서 발생한 문제였고, nuxt.config.ts에서 해당 기능을 끄는 것으로 빠르게 정리했습니다. 이 글에서는 “왜 웹뷰에서만 터졌는지”, “웹뷰에서 어떻게 로그를 봤는지”, “설정을 어떻게 바꿨는지”를 순서대로 정리해볼게요.

TL;DR

  • 증상: 일부 iOS WebView에서 라우팅 실패 + Failed to resolve import "#app-manifest" 에러
  • 원인: Nuxt 3.8의 experimental.appManifest 동작이 구형 WebView와 충돌
  • 해결: experimental: { appManifest: false }로 비활성화
  • 디버깅: WebView 환경에서는 v-console(vConsole)로 콘솔 확인

문제의 배경: Nuxt.js, App Manifest 그리고 웹뷰 환경

문제의 원인을 설명하려면, App Manifest와 WebView가 어떤 특성을 갖는지 먼저 짚고 넘어가는 게 편합니다.

App Manifest (Web App Manifest)

웹 앱 매니페스트(Web App Manifest)는 PWA에서 쓰는 메타데이터(JSON)입니다. 홈 화면 추가, 아이콘/이름, 시작 URL, 표시 모드 같은 정보를 담고 있고, 브라우저가 “웹 앱을 앱처럼” 다루는 데 필요한 기본 재료예요.

Nuxt 3.8 업데이트에는 이 appManifest 기능이 자동으로 활성화되는 변경 사항이 포함되어 있었습니다. 이 기능은 PWA 경험을 개선하기 위한 것이었지만, 저희 프로젝트에서는 특정 웹뷰 환경에서 이 기능이 로드되는 과정에서 스크립트 오류를 일으키며 예상치 못한 부작용을 일으켰습니다.

WebView: 브라우저랑 “비슷하지만 다른” 실행 환경

WebView는 모바일 애플리케이션 내에서 웹 콘텐츠를 표시하기 위해 사용되는 임베드 가능한 브라우저 구성 요소입니다. 이는 전체 웹 브라우저(예: Chrome, Safari)와 달리 주소 표시줄이나 내비게이션 버튼과 같은 브라우저 UI 요소 없이 웹 페이지를 앱의 레이아웃의 일부로 로드하고 표시합니다. WebView는 하이브리드 앱을 구축하거나, 네이티브 앱 내에서 특정 웹 콘텐츠(예: 개인정보처리방침, 약관, 인앱 결제 페이지 등)를 보여줄 때 주로 활용됩니다.

문제는 WebView가 “그냥 작은 브라우저”가 아니라는 점입니다. 앱에 포함된 엔진 버전, JS 런타임, 보안 정책, 캐시 전략 등이 제각각이라서 데스크톱/모바일 브라우저에서는 괜찮던 코드가 웹뷰에서만 터지는 경우가 종종 생깁니다. 특히 구형 WebView는 최신 스펙을 온전히 지원하지 않는 경우가 많고요.

v-console(vConsole): 웹뷰에서 로그 보는 가장 현실적인 방법

모바일 웹 환경, 특히 웹뷰에서는 데스크톱 브라우저처럼 개발자 도구를 쉽게 사용할 수 없습니다. 이럴 때 v-console과 같은 디버깅 라이브러리는 정말 큰 도움이 됩니다. v-console은 모바일 웹 페이지를 위한 가볍고 확장 가능한 프론트엔드 개발자 도구로, 웹페이지 위에 콘솔 로그, 네트워크 요청, 요소 검사 등 개발자 도구와 유사한 기능을 제공하여 웹뷰 환경에서도 개발자가 문제를 진단하고 해결할 수 있도록 돕습니다.

프레임워크에 구애받지 않아 Vue/React/Nuxt 어디든 붙일 수 있고, 실제로 웹뷰에서 “지금 무슨 에러가 나는지”를 확인할 때 이만한 게 없습니다. 이번에도 v-console로 웹뷰 콘솔을 열어보고 나서야 manifest 관련 스크립트에서 문제가 난다는 걸 확실히 잡아낼 수 있었습니다.

정리하면, Nuxt 3.8의 appManifest 동작이 일부 구형 WebView와 충돌했고, 그 여파로 라우팅까지 영향을 받은 케이스였습니다.

구현 포인트: Nuxt 설정 변경을 통한 문제 해결

웹뷰 콘솔에서 에러를 확인한 뒤, 가장 빠르고 확실한 방법은 experimental.appManifest를 꺼서 영향 범위를 제거하는 거였습니다. 아직 experimental로 분류된 기능이기도 했고, 당장 PWA 설치 경험이 핵심 요구사항은 아니었거든요.

1) experimental.appManifest 비활성화

import { defineNuxtConfig } from 'nuxt';
 
export default defineNuxtConfig({
  ...,
  // <strong>핵심 변경</strong>: Nuxt 3.8의 experimental App Manifest 기능 비활성화
  // 특정 웹뷰 환경에서 스크립트 오류를 유발하는 문제를 해결하기 위함입니다.
  experimental: {
    appManifest: false, // 앱 매니페스트 기능 명시적으로 비활성화
  },
});

설정 한 줄로 Nuxt가 자동 생성/로드하던 매니페스트 관련 로직을 타지 않게 됩니다. 결과적으로 웹뷰에서 발생하던 #app-manifest 관련 에러가 사라졌고, 페이지 이동도 정상화됐습니다.

2) v-console로 웹뷰에서 에러 확인하기

앞서 언급했듯이, 웹뷰 환경에서는 일반적인 브라우저 개발자 도구를 사용할 수 없기 때문에 문제 진단이 매우 어렵습니다. 이때 v-console이 유용하게 사용됩니다. 저희는 v-console을 개발 환경에서 조건부로 활성화하여 문제 발생 당시의 스크립트 오류 메시지를 정확히 포착할 수 있었습니다.

import VConsole from "v-console";
 
if (process.client) {
  // 개발 환경(development)에서만 v-console을 활성화하여
  // 프로덕션 빌드에 불필요한 디버깅 도구가 포함되지 않도록 합니다.
  if (process.env.NODE_ENV === "development") {
    const vConsole = new VConsole();
    console.log("[v-console] 개발 모드에서 v-console이 활성화되었습니다.");
  }
  // 또는 프로덕션 환경에서도 특정 조건(예: URL 쿼리 파라미터)에 따라 v-console을 활성화할 수 있습니다.
  // 이는 QA 팀이나 특정 사용자 그룹이 현장 문제를 디버깅할 때 유용할 수 있습니다.
  else if (window.location.href.includes("debug=vconsole")) {
    const vConsole = new VConsole();
    console.log(
      "[v-console] URL 쿼리 파라미터를 통해 v-console이 활성화되었습니다.",
    );
  }
  // 그 외의 경우에는 v-console을 활성화하지 않습니다.
  else {
    console.log("[v-console] v-console은 활성화되지 않았습니다.");
  }
}

핵심은 두 가지입니다.

  • process.client로 클라이언트에서만 실행되게 하고
  • 개발 모드(또는 debug=vconsole 같은 조건)에서만 켜서 프로덕션 번들에 불필요하게 포함되지 않게 합니다.

이렇게 해두면 “웹뷰에서만 나는 에러”를 현장에서 바로 확인할 수 있어서, 문제를 좁히는 데 시간이 크게 줄어듭니다.

결과 및 영향도 평가: App Manifest를 꺼도 정말 괜찮을까?

nuxt.config.ts 파일에서 experimental.appManifest 옵션을 false로 설정한 후, 문제가 발생했던 모든 웹뷰 환경에서 라우팅 오류가 말끔히 해결되었습니다. 사용자들은 이제 일부 iOS 브라우저나 특정 앱 웹뷰에서도 저희 서비스를 문제없이 이용할 수 있게 되었습니다.

다만 기능을 끄는 건 언제나 트레이드오프가 있습니다. 저희는 비활성화 전에 아래 세 가지를 체크했습니다.

1. PWA(Progressive Web App) 기능의 제약

App Manifest는 홈 화면 추가 및 설치형 앱 경험을 제공하는 핵심 파일입니다. 이 기능을 끄면 자동으로 생성되던 PWA 최적화 혜택을 받지 못하게 됩니다.

우리의 판단: 현재 프로젝트는 인앱 웹뷰(In-app WebView)를 통한 콘텐츠 소비가 주된 목적이며, 사용자가 직접 홈 화면에 추가하여 사용하는 PWA 비중이 매우 낮다고 판단했습니다. 따라서 appManifest 비활성화로 인한 실질적인 서비스 타격은 미미할 것이라고 결론 내렸습니다.

2. 라우팅 및 하이드레이션 성능

이 기능은 빌드 메타데이터를 활용해 라우팅을 최적화하는 목적도 있습니다.

검증 결과: 비활성화 시 appManifest가 제공하는 특정 라우팅 최적화 혜택은 포기하게 됩니다. 하지만 기존의 레거시 방식(빌드 페이로드 기반)으로 동작하게 되며, 일반적인 페이지 이동 속도나 데이터 페칭 성능에서 사용자가 체감할 만한 유의미한 차이는 발견되지 않았습니다. 서비스의 핵심 성능 지표에는 부정적인 영향이 없음을 확인했습니다.

3. 향후 업데이트와의 호환성

appManifest 기능은 현재 experimental 단계로 분류되어 있습니다. 실험적인 기능은 예고 없이 변경되거나 예상치 못한 버그를 포함할 수 있으므로, 프로덕션 환경 적용 시에는 더욱 신중해야 합니다.

대응 전략: 당장은 서비스 안정성을 위해 appManifest 비활성화를 유지하되, 향후 Nuxt의 마이너 업데이트에서 웹뷰 엔진과의 충돌 이슈가 해결되었다는 소식이 들리면 다시 활성화를 검토하기로 했습니다. Nuxt 팀의 공식적인 해결책이 나오거나 웹뷰 환경의 호환성이 개선되면 적극적으로 재도입을 고려할 것입니다.

WebView 버전별 호환성 테스트 결과

환경appManifest ONOFF
iOS Safari (최신) / WKWebView (iOS 15+)정상정상
iOS WKWebView (iOS 13~14)라우팅 실패정상
Android WebView (Chrome 90+)정상정상
Android WebView (Chrome 80 미만)간헐적 오류정상
카카오톡 인앱 브라우저라우팅 실패정상
네이버 인앱 브라우저간헐적 오류정상

영향받은 WebView 사용자는 전체 트래픽의 10~15% 수준이었지만, 네이버 인앱 브라우저 비중이 높은 우리 서비스 특성상 체감 영향은 수치 이상이었습니다.

회고 및 다음 단계

이번 일을 겪으면서 다시 확인한 포인트는 이렇습니다.

  1. 프레임워크 업데이트의 양면성: 최신 버전으로의 업데이트는 새로운 기능과 성능 향상을 가져오지만, 때로는 예상치 못한 환경에서 호환성 문제를 일으킬 수 있습니다. 특히 experimental로 분류된 기능들은 도입 시 더욱 신중한 접근과 철저한 테스트가 필요하다는 것을 다시 한번 상기했습니다. 모든 새로운 기능이 모든 환경에서 완벽하게 동작하리라는 보장은 없으며, 특히 레거시 환경을 지원해야 할 때는 더욱 주의가 필요합니다.
  2. 웹뷰 환경 디버깅의 중요성: 일반적인 브라우저와 다른 특성을 가진 웹뷰 환경에서의 디버깅은 전용 도구가 필수적입니다. v-console과 같은 라이브러리를 활용하면 이러한 특수한 환경에서도 문제를 효과적으로 진단하고 해결할 수 있습니다. 웹뷰 환경 테스트와 디버깅은 이제 개발 프로세스의 필수적인 부분으로 자리 잡아야 할 것입니다.
  3. 기능 비활성화 시 영향도 평가의 중요성: 단순히 문제를 해결하기 위해 기능을 끄는 것에서 그치지 않고, 해당 기능이 제공하는 혜택과 잠재적 사이드 이펙트를 평가하는 것이 중요합니다. 현재 프로젝트의 상황과 사용자 시나리오를 고려한 면밀한 영향도 분석은 불필요한 기능 저하를 막고 합리적인 의사결정을 돕습니다.

앞으로는 프레임워크 업데이트를 할 때 “대표 브라우저 + 웹뷰”를 한 세트로 묶어서 회귀 테스트를 돌리고, 웹뷰에서만 재현되는 이슈를 위해 최소한의 디버깅 채널(v-console 같은)을 항상 준비해두려고 합니다.

참고 자료