플러그인이 서버에서도 실행돼 window is not defined로 죽은 이유
문제 발생
분석 도구를 붙이려고 플러그인을 만들었더니 서버 렌더에서 죽었습니다.
// app/plugins/analytics.ts
export default defineNuxtPlugin(() => {
window.analytics.init(KEY); // ReferenceError: window is not defined
});한 파일을 하위 폴더로 옮겼더니 이번에는 아예 실행되지 않았고, 두 플러그인의 초기화 순서도 매번 달랐습니다.
원인 분석
플러그인은 기본적으로 양쪽에서 실행됩니다. Nuxt 문서는 app/plugins/ 디렉터리를 읽어 Vue 앱 생성 시점에 로드하며 안의 모든 플러그인이 자동 등록되어 nuxt.config에 따로 추가할 필요가 없다고 설명합니다. 여기에 실행 환경 구분은 없습니다.
자동 등록의 범위도 정해져 있습니다 — 디렉터리 최상위 파일(또는 하위 디렉터리의 index 파일)만 플러그인으로 자동 등록됩니다. 하위 폴더에 아무렇게나 넣으면 조용히 무시되는 이유입니다.
순서도 문서에 있습니다 — 기본적으로 플러그인은 순차적으로 로드되고, 파일명에 번호를 붙여 순서를 제어할 수 있습니다. 파일명은 문자열로 정렬되므로 01.처럼 자리를 맞춰야 하고(10.이 2.보다 앞섭니다), 특정 플러그인을 기다려야 하면 dependsOn을 씁니다.
해결 방안
- 환경은 파일명 접미사로 정합니다. 문서 설명 그대로
.server또는.client접미사를 쓰면 그쪽에서만 로드됩니다.
app/plugins/analytics.client.ts # 브라우저에서만
app/plugins/logger.server.ts # 서버에서만-
자동 등록되는 위치에 둡니다. 하위 폴더로 정리하고 싶으면
index파일로 만들거나nuxt.config.ts에 직접 등록합니다. -
순서가 필요하면 명시합니다. 번호 접두사(
01.setup.ts,02.analytics.client.ts)나dependsOn으로 의존을 드러냅니다 — 우연히 맞는 순서에 기대지 않습니다. -
독립적인 플러그인은 병렬로 돌립니다.
parallel: true를 주면 앞 플러그인의 완료를 기다리지 않아 부팅이 빨라집니다. 단 의존이 있는 것에는 쓰지 않습니다. -
헬퍼 주입보다 컴포저블을 먼저 고려합니다. 문서가 직접 권합니다 — 전역 네임스페이스를 오염시키지 않도록 헬퍼 제공 대신 컴포저블 사용을 강력히 권장합니다.
provide로$hello를 만드는 대신useHello()를 만드는 쪽입니다. -
window접근은 접미사로 끝내지 말고 이유를 확인합니다. 접미사는 실행 위치를 정할 뿐, "이 기능이 SSR HTML에 있어야 하는가"는 별개 질문입니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.