brunch

You can make anything
by writing

C.S.Lewis

by The Compass 더컴퍼스 Jul 24. 2023

[Nuxt3]"Window is not Defined"

우리 금쪽같은 윈도우가요?

안녕하세요 Heegun입니다.

윈도우 객체 사용 시에 마주칠 수 있는 당황스러운 화면이 있습니다.





우리 금쪽같은 윈도우

Nuxt에서 Window 객체를 사용하다가 마주칠 수 있는 에러입니다.

아주 단순한 코드임에도 발생하여서 뒷 목에 식은땀을 흐르게 할 수 있습니다.

Window 객체에서 not defined 에러를 보는 것이 흔치는 않기 때문이죠..


Window

우선 이 Window 객체가 무엇인지 부터 알아보겠습니다.

Window 객체는 브라우저 탭에 존재하는 자바스크립트 전역 최 상위 객체입니다.

당연하게도 JS의 모든 객체, 전역 함수, 전역 변수들은 Window 객체에 소속됩니다.

따라서 어디서든 접근이 가능하며, 주로 브라우저의 창(Window)을 제어하기 위해 접근하는 목적으로 사용됩니다.


여기서 모순이 발생됩니다.

분명 어디서든 접근이 가능하다고 했는데 not defined 애러가 발생하는 것은 앞뒤가 맞지 않게 느껴질 수 있습니다. not defined가 발생하는 이유는


1. 선언되지 않은 변수에 대한 접근

2. 잘못된 범위

위 두가지 이기 때문입니다. (주로.)


물론 크게 도움이 되는 설명은 아닐 수 있습니다.

어디서든 접근할 수 있다고 했으니 두 번째 경우는 아니고, 그렇다고 첫 번째 조건에 걸릴 리는 더욱 더 만무합니다. 

그렇다면 무엇이 문제일까요?

답은 바로 Nuxt의 렌더링 방식에 있습니다.



Nuxt : USR

https://brunch.co.kr/@team-thecompass/10

Nuxt는 Universal Rendering을 통해 SSR(Server Side Rendering)을 지원합니다.

자세한 내용은 위 글을 참조하면 좋을 것 같습니다.

아무튼 이 SSR 과정에서 서버가 서버 측에서 해당 객체(Window, Document 객체)를 찾을 수 없기 때문에 not defined가 발생하는 것입니다.


SSR은 서버에서 사용자에게 보여줄 페이지를 렌더링 한 이후에 띄우는 방식입니다. 그렇기 때문에 랜더링 시점에서 브라우저에 있는 객체인 Window 객체나 Document 객체를 사용할 수 없는 것입니다.


그렇다면 슬프게도 Nuxt에서는 해당 객체를 영영 사용할 수 없는 것일까요?

당연히 아닙니다.


해결방안?

이라고 말할 것도 아니지만, 천천히 서술해보겠습니다.

우선 Window 객체와의 만남을 방해하는 요소를 짚어봅시다. 아무래도 SSR을 가장 먼저 떠올릴 것입니다. 하지만 우리는 이 SSR이라는 친구를 버릴 수는 없는 노릇이죠.


위의 참조된 링크의 글을 읽으면 알 수 있겠지만, SSR은 Nuxt의 큰 장점 중 하나입니다.

이를 버리고 CSR만을 사용한다면 우리는 Nuxt를 사용할 이유가 없습니다.



A) 변수를 부르는 시점을 달리하기

렌더링 방식에 불만을 가질 수 없다면 변수를 부르는 시점을 다르게 해보는 것입니다.

이를 위해서는 Vue의 생명 주기에 대한 지식이 필요합니다.

인스턴스 생명 주기에 대한 그림입니다.

아픈 머리를 붙잡고, 아는 단어들을 몇 개 짚어가며 훑어보면 이해가 빠를 것입니다.

렌더링 직후의 시점이 mounted로 표시되어 있습니다. 그 전의 시점인 created 등의 시점은 DOM 이 렌더링 되지 않은 시점입니다.

Virtual DOM에는 접근이 가능하지만 BOM, DOM 객체 등에는 접근할 수 없습니다.

그러므로 우리는 그 이후의 시점에 해당 객체들에 접근해야 합니다.



① Option API

② Composition API


당연하게도 ①에서의 created() 시점에서는 에러가 발생합니다. 이유는 위에서 설명했고, 에러 화면 한번 더 보라고 넣은 것은 아니며 이걸 보는 사람들이 한번 더 보고 이해해 줬으면 하는 마음에 포함시켰습니다..

참고로 Composition API에서는 Created 시점에 대한 Hook은 없습니다.

Setup 훅이 beforeCreate, Create를 대체하기 때문입니다.



B) Undefined 아닐 때 Window 객체 호출하기

위와 같이 객체를 호출하는 시점을 달리 하는 방법도 있지만, 다음과 같이 단순히 Window 객체가 Undefined가 아닐 때에만 호출하는 방법도 있긴 합니다.

이 외에도 특정 리소스를 클라이언트 측에서만 import하고 싶은 경우에는 process.client 변수를 사용하는 방법도 있습니다만, 이에 대해서는 조금 더 공부해봐야 할 필요가 있다고 생각해 추가하지 않았습니다.


참고로 A와 B의 방법을 함께 사용하는 것이 가장 안전핟자고 합니다.

서버도 mounted 과정이 있을 수 있기 때문이라는데, 이에 대해서도 역시 정확한 지식이 없기 때문에 추후에 기회가 있다면 다시 찾아오도록 하겠습니다.



©2023 thecompass. All rights reserved

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari