개요 — 무엇을 하나
Service ▸ Web 카드의 순 방문자 옆 두 아이콘이 각각 모달을 엽니다.
| 아이콘 | 모달 | 원천 |
|---|---|---|
| 사람 | 방문자 분석 | Google Analytics 4 (Analytics Data API) |
| 돋보기 | 검색 유입 | Google Search Console (Search Analytics API) |
카드의 nginx_meta_ct 접속 인텔이 "우리 서버가 무엇을 받았나"를 말한다면, 이 두 모달은 **"방문자가 어디에서 왔고 어떤 검색어로 들어왔나"**를 말합니다. 서버 로그에는 없는 정봅니다.
워드프레스의 Site Kit 이 하던 일의 본질은 리포트 요청을 대신 만들어 주는 것입니다. Laravel 에서는 그 요청을 직접 만들면 동등하므로 플러그인도
google/apiclient도 쓰지 않습니다 — 필요한 일은 "개인키로 JWT 를 서명해 액세스 토큰으로 교환"뿐이고 서버가 이를 자체적으로 처리합니다. REST 두 곳을 부르자고 큰 의존 트리를 들이지 않습니다.
언제 쓰나
- 카드의 순 방문자가 늘었을 때 어느 채널·어느 소스에서 왔는지 되짚을 때.
- 어떤 검색 키워드로 노출·클릭이 발생하는지, 그 키워드가 어느 페이지로 들어오는지 볼 때.
- 신규 방문자 비중·기기 구성·유입 성격 같은 구성비를 한눈에 확인할 때.
- 콘텐츠 배포 후 노출·클릭·평균 순위의 추이를 추적할 때.
화면 구성
두 모달 모두 개요 / 검색 키워드 / 유입 통계 탭으로 나뉩니다(검색 키워드 탭은 검색 유입 모달 전용). 긴 스크롤 대신 탭으로 접근합니다. 기간은 7 / 28 / 90일 중 선택하며 이는 서버 화이트리스트와 같은 집합입니다.
방문자 분석 (GA4)
- KPI 6종: 방문자·신규 방문자·세션·페이지뷰·참여율·평균 세션시간. 각 값에 직전 동일 기간 대비 증감이 붙습니다.
- 구성비 3종: 방문자 충성도(신규/재방문) · 기기 구성(데스크톱/모바일·태블릿) · 유입 성격(검색/그 외). 셋 다 2분할이라 시각 언어가 같고, 큰 숫자는 KPI 가 이미 말하므로 여기서는 비율만 보여줍니다.
- 추이 차트: 방문자·세션·페이지뷰 3계열.
- 패널 6종(유입 통계 탭): 유입 채널 · 유입 소스 · 도시 · 국가 · 기기 · 인기 페이지.
유입 채널과 유입 소스는 다릅니다. 채널은 묶음 답(
Organic Search)이고 소스는 구체 답(naver·github.com)입니다. 국내 사이트는 naver ↔ google 구분이 유입 전략 자체를 가르므로 두 패널을 함께 봅니다.
검색 유입 (Search Console)
- KPI 5종: 클릭 · 노출 · CTR · 평균 순위 · 키워드 수.
- 워드클라우드: 크기·색 = 노출수, ● 표시 = 실제 클릭이 발생한 키워드, 숫자는
~1일 / ~7일 / 전체노출. - 키워드 표: 클릭·노출·CTR·순위.
- 유입 페이지 × 키워드: 페이지를 펼치면 그 페이지로 들어온 키워드가 칩으로 나옵니다.
- 패널 3종: 유입 페이지 · 국가 · 기기.
평균 순위는 노출 가중 평균입니다. 단순 평균을 쓰면 1회 노출된 1위 키워드가 1만 회 노출된 40위 키워드를 상쇄해 실제보다 좋아 보입니다.
사용법
1. 서비스 계정 만들기 (Google Cloud)
- Google Cloud Console → 프로젝트 선택/생성 → IAM 및 관리자 ▸ 서비스 계정 → 서비스 계정 만들기. 프로젝트 레벨 역할은 필요 없습니다.
- 생성한 계정 → 키 탭 → 키 추가 ▸ 새 키 만들기 ▸ JSON → 파일 다운로드.
- API 및 서비스 ▸ 라이브러리에서 Google Analytics Data API 와 Google Search Console API 를 사용 설정.
2. InfraGuard 에 등록
Service ▸ Web ▸ 웹사이트 관리 ▸ 해당 사이트 편집 탭의 Google 연동 구획에서:
| 입력 | 값 | 확인 위치 |
|---|---|---|
| GA4 속성 ID | 숫자만 (예 550688232) |
GA4 관리 ▸ 속성 세부정보, 또는 URL #/a<계정>p<속성>/ 의 p 뒤 |
| Search Console 속성 | sc-domain:example.com 또는 https://example.com/ |
Search Console 좌상단 속성 선택기에 표시된 문자열 그대로 |
| 서비스 계정 자격 (JSON) | 다운로드한 JSON 전문 붙여넣기 | — |
GA4 속성 ID 는 계정 ID 가 아니다. URL
#/a405285491p550688232/에서a뒤는 계정,p뒤가 속성입니다. 구글은 "그런 속성 없음"과 "권한 없음"을 구분해 알려주지 않으므로(속성 존재 여부 자체가 정보 노출), 번호가 틀려도 권한 오류처럼 보입니다. 조회가 안 되면 속성 ID 부터 대조하세요.
Search Console 속성은 도메인에서 유추하지 않습니다. 도메인 속성(
sc-domain:)으로 검증했는지 URL 접두(https://…/)로 검증했는지는 등록한 본인만 압니다. 틀리면 오류가 아니라 빈 결과가 옵니다.
3. 서비스 계정을 속성에 초대
자격 JSON 은 신분증일 뿐이고 접근권은 속성마다 따로 줘야 합니다. 저장 후 화면에 표시되는 client_email 을 복사해서:
| 속성 | 위치 | 역할 |
|---|---|---|
| GA4 | 관리 ▸ 속성 액세스 관리 ▸ + |
뷰어 |
| Search Console | 설정 ▸ 사용자 및 권한 ▸ 사용자 추가 | 전체 |
GA4 는 계정 액세스 관리가 아니라 속성 액세스 관리입니다(왼쪽 열이 계정, 가운데가 속성). Search Console 은 제한됨이 아니라 전체 여야 합니다 — Search Analytics API 가 제한됨 사용자를 거부합니다. 서비스 계정은 메일함이 없으므로 초대 시 알림 메일 체크는 해제합니다.
4. 연동 테스트
관리 모달 하단 [연동 테스트] 가 저장된 자격·속성으로 두 API 를 각각 1회(최근 7일) 조회해 결과를 항목별로 보여줍니다.
| 상태 | 뜻 |
|---|---|
ok |
구글이 응답했습니다. 0건도 ok — 신규 사이트·GSC 지연은 오류가 아니다 |
fail |
구글이 돌려준 사유를 그대로 표시 + 초대할 client_email |
skip |
속성이 지정되지 않아 건너뜀(실패 아님) |
자격이 아예 없으면 두 API 를 호출하지 않습니다(외부 요청 0). 저장하지 않은 변경은 테스트에 반영되지 않으므로 먼저 저장합니다.
정합성 규약 — 왜 이렇게 계산하나
Site Kit 이 검증해 온 함정들을 그대로 따릅니다. 전부 실측 근거가 있는 규칙입니다.
| 규약 | 이유 |
|---|---|
| 창은 어제로 끝납니다 | 오늘은 부분 집계라 넣으면 그래프 우측 끝이 항상 급락한다 |
GA4 는 metricAggregations:['TOTAL'] 의 totals[0] 을 읽는다 |
limit 이 걸린 rows 를 합치면 헤드라인이 과소 집계된다 |
모든 GA4 요청에 hostName in-list 필터 |
한 속성에 여러 호스트가 있으면 카드가 속성 전체 트래픽을 보여줍니다. 여기에는 그 서비스가 보유한 전 도메인(주+추가+www)을 넣어 카드의 vts 합산 집합과 일치시킨다 |
랭킹은 keepEmptyRows:false + notExpression{emptyFilter} |
GA4 의 (not set) 이 실제 도시·소스보다 위에 오는 일이 잦다 |
시계열은 keepEmptyRows:true |
트래픽 0인 날이 축에서 사라지면 안 된다 |
GSC 는 dataState:'all' + 약 2일 지연 반영 |
없으면 최근 며칠이 0 으로 와 "트래픽이 죽었습니다"고 오진한다 |
도메인 속성은 page contains 로 스코프 |
sc-domain: 은 전 서브도메인을 포함해 형제 사이트의 키워드가 섞인다 |
데이터 소스
| 대상 | 커넥션 / 위치 | 역할 |
|---|---|---|
infr_web_service.ga4_property_id · gsc_site_url |
기본(000771) | 사이트별 속성 매핑 |
infr_web_service.google_cred_enc · google_cred_email |
기본(000772) | 사이트별 서비스 계정 자격(Crypt · write-only) |
Analytics Data API properties/{id}:runReport |
외부 | 방문자 리포트 |
Search Console searchAnalytics/query |
외부 | 검색 유입 리포트 |
서비스: Services\Google\{GoogleTokenService, GoogleReportService, SiteInsightService} · 엔드포인트 Service\WebController@insight{Visitors,Search,Test}.
캐시: 리포트 응답은 캐시되며 캐시 키에 요청 주체(client_email)가 포함됩니다. 같은 URL·본문이라도 다른 계정으로 요청한 것은 다른 권한이므로, 키를 공유하면 한 사이트가 남의 캐시 응답을 받게 됩니다.
자격은 왜 사이트별인가
전역 .env 키 하나로는 성립하지 않습니다. 등록 사이트들이 서로 다른 소유자·구글 계정에 속하므로, 서비스 계정 하나는 자신이 초대된 속성만 읽습니다 — 고객이 둘이 되는 순간 한쪽은 반드시 실패합니다. 그래서 웹 인터페이스에서 사이트마다 붙여넣어 저장합니다.
- 저장은
Crypt(APP_KEY) · write-only. 모델이 암호문을$hidden처리하므로 화면에는 보유 여부와 비밀이 아닌client_email만 나옵니다. 개인키는 들어가면 나오지 않습니다. - 저장 시 3중 검증: JSON 형식 ·
client_email/private_key존재 · 실제로 서명에 쓸 수 있는 키인지. 키가 잘려 붙여넣어지는 사고가 흔한데, 통과시키면 나중에 "권한 없음"처럼 보여 원인을 구글 IAM 에서 찾게 됩니다. - 서버에 등록된 공용 자격은 단일 계정 배포용 폴백으로 남아 있으며, 사이트 자기 자격이 항상 이깁니다.
자격 필드는 건드렸을 때만 전송됩니다. 폼이 개인키를 되돌려 받지 않으므로, "미전송"을 해제로 해석하면 메모만 고쳐도 자격이 지워집니다. 명시적으로 비우는 것만 해제로 처리됩니다.
권한
- 조회: 로그인(
infr.auth) — 레벨 ≥ 1. 외부 통계를 조회만 하고 InfraGuard·Google 어느 쪽도 변경하지 않으므로 step-up·감사가 없습니다(IP 평판 조회와 같은 규율). - 자격·속성 저장:
user_level >= 2(웹사이트 저장 권한과 동일) +infr_audit_log기록.
조회 대상은 등록된 사이트 id 로만 지정되며 속성 ID 를 파라미터로 넘길 수 없습니다. 요청자가 속성을 지정할 수 있으면 우리 서비스 계정 권한으로 남의 GA4/Search Console 속성을 조회하는 통로가 됩니다(Catalog 라이브 테스트의 SSRF 회피와 같은 규율). 기간도 7/28/90 으로 서버에서 화이트리스트합니다.
문제해결 · FAQ
- 카드에 아이콘이 안 보입니다 — 그 사이트에 자격과 속성 매핑이 모두 있어야 버튼이 뜹니다. 판정은 사이트별이므로 전역
.env가 비어 있어도 자기 자격이 있으면 나타납니다. 저장 후 새로고침하세요. - 모든 점검이 초록인데 계속 0 건 — 수집 문제이지 조회 문제가 아니다. ① 창이 어제로 끝나므로 오늘 설치한 태그의 데이터는 아직 창 밖입니다. ② 사이트에 실제로 심긴 측정 ID(
G-…)가 조회 중인 속성의 데이터 스트림인지 확인하세요(GA4 관리 ▸ 데이터 스트림). 다른 속성에 쌓이고 있으면 영원히 0 입니다. ③ Search Console 은 약 2일 지연 + 신규 사이트는 노출 자체가 없을 수 있습니다. User does not have sufficient permissions— 3단계(속성 초대)가 빠졌거나 GA4 속성 ID 가 틀렸습니다. 두 경우의 문구가 같으므로 속성 ID 를 먼저 대조하세요.- Search Console 만 빈 결과 — 속성 표기가 실제와 다를 가능성이 높습니다(
sc-domain:↔https://…/). 오류가 아니라 빈 결과로 오므로 속성 선택기의 문자열과 대조하세요. - 저장했는데 자격이 사라졌습니다 — 자격 칸을 비운 채 저장하면 명시적 해제로 처리됩니다. 건드리지 않으면 유지됩니다.
- 모달에
샘플배지가 있습니다 — 아직 수집된 데이터가 없어 디자인 재현용 예시를 보여주는 중입니다. 실제 데이터가 들어오면 자동으로 전환됩니다.
관련 항목
- Service ▸ Web — 카드·가동율·인증서 등 웹 관제 본체
- 공개 랜딩 · 방문자 분석 태그 — 수집 쪽(gtag/GTM·Search Console 소유 확인)
- IP 평판 조회 — 같은 "외부 조회 전용" 권한 규율
