1 분 소요

왜 _app.tsx에 두면 제대로 동작하지 않을까?

이슈

Google Analytics와 Google Tag Manager를 설정하는 과정에서 noscript 태그를 _app.tsxAnalyticScript 컴포넌트 내부에 작성했습니다.

하지만 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로 이동시킴으로써

  1. JavaScript가 비활성화된 환경에서도 Google Tag Manager가 정상적으로 동작할 수 있게 되었습니다.
  2. 코드의 책임이 명확해져 유지보수가 용이해졌습니다.
  3. 상수 분리를 통해 코드의 재사용성이 향상되었습니다.

Next.js에서 _app.tsx_document.tsx의 차이를 이해하고, 각 컴포넌트의 실행 시점을 고려하여 적절한 위치에 코드를 배치하는 것이 중요합니다.

카테고리:

업데이트:

댓글남기기