구글 태그 매니저, GTM의 원리

2025. 9. 26. 04:28·Develop/Frontend

사용자 행동 분석을 위해  구글 태그 매니저(GTM)와 구글 애널리틱스(GA4)를 사용하곤 합니다.
또한 Heat map 을 통해 사용자 경험을 분석하기 위해 Clarity도 GTM과 연결하여 사용하고 하죠.

 

종종 헷갈리는 사람이 있곤 하는데, GA4는 결국 GTM을 기반으로 동작합니다. 

GTM : 여러 분석·마케팅 태그(analytics, ads, pixel 등)를 코드 변경 없이 중앙에서 관리하게 해주는 컨테이너 기반 툴.
GA4 : 이벤트(event)-기반 분석 모델. 페이지뷰도 이벤트의 한 종류(page_view).

 

즉, GTM은 GA4(및 다른 태그)의 배포·관리 도구이고, GA4는 그로부터 수신한 이벤트 데이터를 수집·분석합니다.

GTM → (GA4 Configuration/GA4 Event 태그) → GA4 로 데이터가 전달됨의 과정을 거치는 것입니다.

 

오늘은 이 기반이 되는 GTM이 어떤 기술적 원리를 가지고 동작하는지 알아보겠습니다.

 

GTM에 삽입되는 script 와 noscript

(참고로 GTM-SECRET은 GTM 컨테이너 고유 ID입니다. )

<!-- 최대한 Head 태그 내에서 맨 위에 삽입을 추천-->
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'[https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f)](https://www.googletagmanager.com/gtm.js?id=%27+i+dl;f.parentNode.insertBefore(j,f));
})(window,document,'script','dataLayer','GTM-SECRET');</script>
<!-- End Google Tag Manager -->



<!-- Body 태그 바로 뒤에 삽입할 것 -->
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-SECRET"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

 

여기서 noscript라는 태그는 브라우저가 JavaScript를 지원하지 않거나 꺼져 있을 때  대체 수단으로 렌더링되는 태그입니다.

위의 경우에는 보이지 않는 인라인 프레임을 삽입하는 iframe 태그를 내부적으로 렌더링하여, 자바스크립트가 실행되지 않는 환경에서도 GTM이 실행되도록 보장합니다.

 

이제 핵심이 되는 script 부분의 난독화를 풀어서, 보기 좋게 정리하면 아래와 같이 됩니다.

<script>
(function(window, document, tagName, dataLayerName, containerId) {
  // dataLayer 초기화 (없으면 빈 배열로 생성)
  window[dataLayerName] = window[dataLayerName] || [];

  // GTM 시작 시점 이벤트를 dataLayer에 기록
  window[dataLayerName].push({
    'gtm.start': new Date().getTime(),
    event: 'gtm.js'
  });

  // 첫 번째 <script> 태그 찾기
  var firstScript = document.getElementsByTagName(tagName)[0];

  // 새로운 <script> 요소 생성
  var newScript = document.createElement(tagName);

  // dataLayer 이름이 기본값(dataLayer)이 아닐 경우 쿼리 파라미터에 추가
  var dataLayerParam = (dataLayerName !== 'dataLayer') ? '&l=' + dataLayerName : '';

  // async로 비동기 로드
  newScript.async = true;

  // GTM JS 파일(src) 세팅
  newScript.src = 'https://www.googletagmanager.com/gtm.js?id=' + containerId + dataLayerParam;

  // 기존 <script> 앞에 새로 만든 GTM <script> 삽입
  firstScript.parentNode.insertBefore(newScript, firstScript);

})(window, document, 'script', 'dataLayer', 'GTM-SECRET');
</script>

 

 

이 스크립트의 내용을 천천히 살펴보면 이해할 수 있듯, 

window에 dataLayer 프로퍼티를 추가하고, 그 dataLayer에 gtm이 초기화되었다는 것을 알리는 이벤트 신호 객체를 push 해둡니다.

그리고 gtm.js를 불러오는 스크립트 태그를 하나 만들어서,  삽입(실행)합니다. 

 

GTM의 동작 과정

위의 과정이 진행되면, 결국 비동기적으로 gtm.js가 로드됩니다.

그 gtm.js 대략 아래와 같이 작성되어 있습니다. (정확하지는 않습니다)

(function(){
  // GTM 초기화
  var dataLayer = window.dataLayer = window.dataLayer || [];

  // 원래 배열 push를 저장
  var originalPush = dataLayer.push;

  // push 오버라이드
  dataLayer.push = function() {
    // 1. 배열에 값 저장
    var result = originalPush.apply(dataLayer, arguments);

    // 2. GTM 이벤트 처리
    for (var i = 0; i < arguments.length; i++) {
      var eventData = arguments[i];
      if (eventData.event) {
        // GTM 내부 큐로 전달 → 트리거 확인 → 태그 실행
        processEvent(eventData.event, eventData);
      }
    }

    return result;
  };

  // "gtm.js"라는 초기 이벤트 푸시
  dataLayer.push({ event: "gtm.js", "gtm.start": new Date().getTime() });

  function processEvent(eventName, data) {
    // 내부적으로 등록된 트리거를 순회하고
    // eventName이 조건에 맞으면 연결된 태그 실행
    console.log("GTM received event:", eventName, data);
  }
})();

 

눈 여겨보면 좋을 부분은, gtm.js 내부에서 push라는 메서드가 오버라이딩 된다는 점입니다. 

그리고 맥락을 잃지 않기 위해 apply를 사용하고 있습니다.

 

결국 gtm.js가 실행되면서 처리하는 작업은 아래와 같습니다.

  1. 이미 dataLayer에 들어있는 값들을 전부 꺼내서 처리합니다.
    → 즉, 배열에 있던 { event: "gtm.js", "gtm.start": ... }를 읽습니다.
  2. "event": "gtm.js"는 특별히 "컨테이너 로드됨"이라는 초기 신호로 해석됩니다.
    → GTM 내부에서 페이지 로드 직후 발생한 기본 이벤트로 기록됩니다.
  3. 이후 개발자가 추가하는 dataLayer.push({ event: "page_view" }), add_to_cart, purchase 같은 이벤트들도 같은 방식으로 해석됩니다.

 

GTM + dataLayer를 쓰는 방법

GTM을 쓰면 대부분 코드를 수정할 필요 없이 플랫폼에서 처리 가능합니다.

방법 1: 자동 이벤트 트래킹 (GTM 기본 기능)

  • GTM에서 제공하는 Click / Link / Form / Element Visibility 트리거를 설정
  • 클릭할 버튼의 CSS 선택자, ID, 클래스 등 조건만 플랫폼에서 지정
  • GTM이 자체 JS를 사용해서 해당 이벤트를 감지하고 dataLayer.push로 이벤트를 만듦
  • 개발자는 HTML에 아무 코드도 추가하지 않아도 됨

ex) 트리거 타입조건 설정하는 예시

Click - All Elements Click ID = buyButton
Click - Just Links URL = /purchase
Form Submission Form ID = signupForm
  • 이렇게 설정하면 버튼이 클릭될 때 자동으로 dataLayer.push({event:'gtm.click', ...}) 발생
  • GTM UI에서 GA4 태그 연결 → 클릭 이벤트 전송

 

방법 2: 커스텀 이벤트 트리거

  • HTML 코드에서 data-attribute를 달아놓고, GTM에서 CSS selector로 감지하는 방식입니다. 
<button id="buyButton" data-gtm-event="add_to_cart">Buy</button>
  • GTM에서 트리거 설정
    • Trigger Type: Click - All Elements
    • Conditions: [data-gtm-event] equals add_to_cart
  • GTM이 클릭 이벤트를 자동으로 수집 → GA4 태그 실행

 

마무리

결국 GTM에서 사용자 행위를 분석하는 것은, 코드가 확장된 형태라고 이해하면 좋습니다.

사실 플랫폼이라는 것 자체가 코드가 추상화, 확장된 것이라고 생각하는데,

 

GTM 같은 경우에도 매번 개발자들이 작업을 해야하는 필요성을 줄이고, 기획자나 다른 팀원들도 같이 이벤트를 관리할 수 있게 만들어주는 도구(플랫폼)입니다.

 

단순히 연결만 하면 되긴 하지만, 이런 기술적인 원리들이 바탕이 되어 편리함을 주고 있었네요.

 

'Develop > Frontend' 카테고리의 다른 글

OAuth, 인증과 인가  (1) 2026.01.13
타입스크립트의 재귀는 몇번까지 허용될까?  (0) 2025.11.10
history stack  (2) 2025.06.26
브라우저 캐싱과 헤더 필드  (0) 2025.06.23
Tanstack Query (React Query) 필수 지식  (0) 2025.05.11
'Develop/Frontend' 카테고리의 다른 글
  • OAuth, 인증과 인가
  • 타입스크립트의 재귀는 몇번까지 허용될까?
  • history stack
  • 브라우저 캐싱과 헤더 필드
ocahs
ocahs
개발 내용을 담습니다.
  • ocahs
    ocahs 개발 블로그
    ocahs
  • 전체
    오늘
    어제
    • 분류 전체보기 (47)
      • Develop (47)
        • Frontend (25)
        • Javascript (7)
        • Algorithm (14)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    promise reject
    Promise
    line sweeping
    비트 연산자 활용 예시
    요청의 역사
    JS
    Working Set Model
    번들러
    재귀타입
    vite
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
ocahs
구글 태그 매니저, GTM의 원리
상단으로

티스토리툴바