Why “window / document is not defined” Occurs in Next.js: The True Nature of SSR

1. Conclusion: Why Do We Need Client Components?

The reason why you need to specify 'use client' (Client Component) when using localStorage, sessionStorage, window, or document in Next.js is that these are “Browser APIs” that only exist within the browser (client-side).

Under the “Server Component” environment where code is executed on the server, these objects do not exist (undefined), which triggers a runtime error the moment they are accessed.


2. Mechanism: The Difference in “HTML Rendering” Between Server and Browser

Even though we say “rendering HTML on the server (SSR)”, the underlying mechanism is completely different between the server-side and the browser-side.

Key Differences Server-side (Next.js SSR) Browser-side (Traditional JS / Post-Hydration)
Environment Node.js (Server Environment) Web Browser (Chrome/Safari, etc.)
Operation Converts JSX into plain “String (Text)” Generates actual “DOM Objects”
Primary Method React’s internal string rendering engine DOM APIs like document.createElement()
window / document Not Defined Defined

Server-Side Rendering Concept

The server does not manage a live UI screen like a browser does. It simply takes your JSX and concatenates it into a single, long string.

// Conceptual image (Actual logic is more complex)
let html = "";
html += "<div>";
html += "<h1>" + props.title + "</h1>";
html += "</div>";
return html; // Result: "<div><h1>Title</h1></div>" as a plain string

Since it is merely performing string addition at this stage, the document object is neither required nor present.


3. The Lifecycle: From SSR to Screen Display

  1. [Server] String Compilation

    Next.js analyzes components, generates the HTML “string”, and sends it to the browser.

  2. [Browser] Parsing HTML

    The browser reads the incoming HTML string. At this exact moment, the window and document objects are created inside the browser, and the text or images instantly appear on the screen (though interactive elements like buttons don’t work yet).

  3. [Browser] Hydration

    The JavaScript that arrives later executes in the browser, attaching dynamic event listeners (like button clicks) to the pre-rendered HTML (DOM).

Next.js’s 'use client' (Client Component) directive is essentially a declaration stating, “This code should also run during steps 2 and 3 (browser-side).” This is why switching to a Client Component allows you to safely access window and document.

Leave a Comment

CAPTCHA