[Next.js] noscript를 _document.tsx에 둬야 하는 이유
왜 _app.tsx에 두면 제대로 동작하지 않을까?
이슈
Google Analytics와 Google Tag Manager를 설정하는 과정에서 noscript 태그를 _app.tsx의 AnalyticScript 컴포넌트 내부에 작성했습니다.
하지만 noscript 태그는 JavaScript가 비활성화되어 있을 때 대체 콘텐츠를 제공하는 역할을 하므로, JS가 실행되기 전 HTML 파싱 단계에서 존재해야 합니다.
\_app.tsx vs \_document.tsx
\_app.tsx
The App component is used to initialize pages.
참고: Custom App
- _app.tsx는 모든 페이지의 공통 React Wrapper
- JavaScript가 실행된 이후에 실행되는 파일입니다.
- React 컴포넌트가 hydration된 이후에 동작합니다.
👉 _app.tsx 내부에 있는 컴포넌트는 JS가 실행되지 않으면 존재할 수 없습니다. 즉, _app.tsx 안에 noscript가 있어도 의미가 없습니다.
\_document.tsx
_document is only rendered on the server and not on the client.
참고: Custom Document
- _document.tsx는 서버에서 한 번만 실행되어 초기 HTML 구조를 생성합니다.
- 이 단계는 JavaScript가 실행되기 전, 즉 HTML 파싱 단계입니다.
<Html>,<Head>,<Main />,<NextScript />의 위치가 명확히 정의되어 있습니다.
👉 따라서 JS 비활성 환경에서도 반드시 노출되어야 하는 noscript는 _document.tsx에 위치해야만 합니다.
해결 방법
noscript 태그는 JS가 실행되기 전에 보여져야 하므로 _document.tsx의 <body> 태그 내부, <Main /> 이전에 위치해야 합니다.
1. 상수 분리
GA_ID와 GTM_ID를 별도의 상수 파일로 분리하여 재사용성을 높였습니다.
export const GA_ID = "G-코드";
export const GTM_ID = "GTM-코드";
2. AnalyticNoscript 컴포넌트 분리
기존 AnalyticScript 컴포넌트에서 noscript 부분만 분리하여 새로운 컴포넌트를 생성했습니다.
const AnalyticNoscript = () => {
return (
<noscript>
<iframe
src={`https://www.googletagmanager.com/ns.html?id=${GTM_ID}`}
height="0"
width="0"
style=
></iframe>
</noscript>
);
};
export default AnalyticNoscript;
3. AnalyticScript 컴포넌트 수정
noscript 부분을 제거하고 상수를 import하여 사용하도록 수정했습니다.
const AnalyticScript = () => {
// <noscript></noscript> 부분 제거
};
4. \_document.tsx에 AnalyticNoscript 추가
_document.tsx의 <body> 태그 내부, <Main /> 이전에 AnalyticNoscript 컴포넌트를 추가했습니다.
// src/pages/_document.tsx
export default function Document() {
return (
<Html lang="ko">
<Head>{IS_PROD && <NaverSearchAdvisor />}</Head>
<body>
{IS_PROD && <AnalyticNoscript />}
<Main />
<NextScript />
</body>
</Html>
);
}
결론
noscript 태그를 올바른 위치인 _document.tsx로 이동시킴으로써
- JavaScript가 비활성화된 환경에서도 Google Tag Manager가 정상적으로 동작할 수 있게 되었습니다.
- 코드의 책임이 명확해져 유지보수가 용이해졌습니다.
- 상수 분리를 통해 코드의 재사용성이 향상되었습니다.
Next.js에서 _app.tsx와 _document.tsx의 차이를 이해하고, 각 컴포넌트의 실행 시점을 고려하여 적절한 위치에 코드를 배치하는 것이 중요합니다.
댓글남기기