배경
Google에서 거의 모든 주제를 검색하면 즉시 알아볼 수 있는 의미 있고 관련성 높은 결과 페이지가 표시됩니다. 특정 시나리오에서 이 검색 결과 페이지가 서비스 작업자라는 강력한 웹 기술에 의해 제공된다는 사실을 깨닫지 못했을 것 입니다 .
성능에 부정적인 영향을 미치지 않으면서 Google 검색에 대한 서비스 작업자 지원을 시작하려면 여러 팀에서 일하는 수십 명의 엔지니어가 필요했습니다. 이것은 배송된 제품, 성능 측정 방법 및 절충 사항에 대한 이야기입니다.
서비스 워커를 찾는 주요 이유
웹 앱에 서비스 작업자를 추가하는 것은 사이트의 아키텍처를 변경하는 것과 마찬가지로 명확한 목표를 염두에 두고 수행해야 합니다. Google 검색 팀의 경우 서비스 워커를 추가하는 것이 가치 있는 몇 가지 주요 이유가 있었습니다.
제한된 검색 결과 캐싱
Google 검색 팀은 사용자가 짧은 시간 내에 동일한 용어를 두 번 이상 검색하는 것이 일반적이라는 사실을 발견했습니다. 검색 팀은 동일한 결과를 얻기 위해 새로운 백엔드 요청을 트리거하는 대신 캐싱을 활용하고 이러한 반복 요청을 로컬에서 이행하기를 원했습니다.
신선함의 중요성은 무시할 수 없으며, 때때로 사용자는 진화하는 주제이기 때문에 동일한 용어를 반복적으로 검색하고 새로운 결과를 기대합니다. 서비스 작업자를 사용하면 검색 팀이 로컬로 캐시된 검색 결과의 수명을 제어하는 세분화된 논리를 구현하고 속도와 최신성의 정확한 균형을 달성하여 사용자에게 최상의 서비스를 제공할 수 있습니다.
의미 있는 오프라인 경험
또한 Google 검색 팀은 의미 있는 오프라인 경험을 제공하고자 했습니다. 사용자가 주제에 대해 알고 싶을 때 활성 인터넷 연결에 대해 걱정하지 않고 바로 Google 검색 페이지로 이동하여 검색을 시작하기를 원합니다.
서비스 작업자가 없으면 오프라인 상태에서 Google 검색 페이지를 방문하면 브라우저의 표준 네트워크 오류 페이지로 연결되며 사용자는 연결이 복구되면 다시 돌아와서 시도해야 한다는 사실을 기억해야 합니다. 서비스 워커를 사용하면 맞춤 오프라인 HTML 응답을 제공하고 사용자가 검색 쿼리를 즉시 입력할 수 있습니다.
인터넷에 연결될 때까지 결과를 사용할 수 없지만 서비스 워커는 기기가 백그라운드 동기화 API를 사용하여 다시 온라인 상태가 되는 즉시 검색을 연기하고 Google 서버로 보낼 수 있도록 합니다 .
더 스마트한 JavaScript 캐싱 및 서빙
또 다른 동기는 검색 결과 페이지에서 다양한 유형의 기능을 지원하는 모듈화된 JavaScript 코드의 캐싱 및 로드를 최적화하는 것이었습니다. JavaScript 번들링은 서비스 작업자가 관여하지 않을 때 의미가 있는 많은 이점이 있으므로 검색 팀은 단순히 번들링을 완전히 중단하고 싶지 않았습니다.
서비스 작업자의 기능을 사용하여 런타임에 세분화된 JavaScript 청크를 버전화하고 캐싱함으로써 검색 팀은 캐시 변동량을 줄이고 향후에 재사용되는 JavaScript를 효율적으로 캐싱할 수 있다고 생각했습니다. 서비스 작업자 내부의 논리는 여러 JavaScript 모듈이 포함된 번들에 대한 발신 HTTP 요청을 분석하고 로컬로 캐시된 여러 모듈을 결합하여 이를 이행할 수 있습니다. 가능한 경우 효과적으로 "번들 해제"할 수 있습니다. 이렇게 하면 사용자 대역폭이 절약되고 전반적인 응답성이 향상됩니다.
성공
또한 서비스 작업자가 제공하는 캐시된 JavaScript를 사용하면 성능상의 이점이 있습니다. Chrome에서는 해당 JavaScript의 구문 분석된 바이트 코드 표현이 저장되고 재사용되므로 JavaScript를 실행하기 위해 런타임에 수행해야 하는 작업이 줄어듭니다. 그 페이지.
과제 및 솔루션
다음은 팀이 명시한 목표를 달성하기 위해 극복해야 할 몇 가지 장애물입니다. 이러한 문제 중 일부는 Google 검색에만 해당되지만 대부분은 서비스 작업자 배포를 고려하고 있는 광범위한 사이트에 적용할 수 있습니다.
문제: 서비스 워커 오버헤드
Google 검색에서 서비스 작업자를 시작하는 데 있어 가장 큰 과제이자 진정한 장애물은 사용자가 인지하는 지연 시간을 증가시킬 수 있는 작업을 수행하지 않도록 하는 것이었습니다. Google 검색은 성능을 매우 중요하게 여기며 과거에는 특정 사용자 집단에 대해 수십 밀리초의 추가 지연 시간이 발생하더라도 새로운 기능의 출시를 차단했습니다.
팀이 초기 실험에서 성능 데이터를 수집하기 시작했을 때 문제가 있음이 분명해졌습니다. 검색 결과 페이지에 대한 탐색 요청 에 대한 응답으로 반환되는 HTML은 동적이며 검색 웹 서버에서 실행해야 하는 논리에 따라 크게 달라집니다. 현재로서는 서비스 워커가 이 로직을 복제하고 캐시된 HTML을 즉시 반환할 수 있는 방법이 없습니다. 서비스 워커가 할 수 있는 최선의 방법은 네트워크 요청이 필요한 백엔드 웹 서버에 탐색 요청을 전달하는 것입니다.
서비스 작업자가 없으면 이 네트워크 요청은 사용자 탐색 즉시 발생합니다. 서비스 워커가 등록되면 가져오기 핸들러가 네트워크로 이동하는 것 외에 다른 작업을 수행할 가능성이 없는 경우에도 항상 시작되고 fetch이벤트 핸들러 를 실행할 기회가 주어져야 합니다. 서비스 작업자 코드를 시작하고 실행하는 데 걸리는 시간은 모든 탐색 위에 추가되는 순수한 오버헤드입니다.
이로 인해 서비스 작업자 구현은 다른 이점을 정당화하기에는 지연 시간이 너무 많이 걸립니다. 또한 팀은 실제 장치에서 서비스 작업자 부팅 시간을 측정한 결과 시작 시간이 광범위하게 분포되어 일부 저가형 모바일 장치에서 서비스 작업자를 시작하는 데 거의 시간이 걸린다는 사실을 발견했습니다. 결과 페이지의 HTML에 대한 네트워크 요청을 수행합니다.
솔루션: 내비게이션 프리로드 사용
Google 검색 팀이 서비스 워커 출시를 진행할 수 있도록 한 가장 중요한 단일 기능은 탐색 사전 로드 입니다 . 내비게이션 사전 로드를 사용하는 것은 내비게이션 요청을 충족하기 위해 네트워크의 응답을 사용해야 하는 모든 서비스 작업자에게 중요한 성능 향상입니다. 서비스 작업자가 시작됨과 동시에 탐색 요청을 즉시 시작하도록 브라우저에 힌트를 제공합니다.
서비스 워커를 시작하는 데 걸리는 시간이 네트워크에서 응답을 받는 데 걸리는 시간보다 짧은 한 서비스 워커에 의해 발생하는 대기 시간 오버헤드가 없어야 합니다.
검색 팀은 또한 서비스 작업자 부팅 시간이 탐색 요청을 초과할 수 있는 저가형 모바일 장치에서 서비스 작업자를 사용하지 않아야 했습니다. 무엇이 "로우엔드" 장치를 구성하는지에 대한 엄격한 규칙이 없기 때문에 그들은 장치에 설치된 총 RAM을 확인 하는 휴리스틱을 고안했습니다. 2GB 미만의 메모리는 서비스 작업자 시작 시간이 허용되지 않는 저가형 장치 범주에 속했습니다.
향후 사용을 위해 캐시할 전체 리소스 집합이 몇 메가바이트까지 실행될 수 있으므로 사용 가능한 저장 공간은 또 다른 고려 사항입니다. 인터페이스 navigator.storage를 통해 Google 검색 페이지는 데이터 캐시 시도가 스토리지 할당량 실패로 인해 실패할 위험이 있는지 여부를 미리 파악할 수 있습니다.
이로 인해 검색 팀은 서비스 작업자를 사용할지 여부를 결정하는 데 사용할 수 있는 여러 가지 기준을 갖게 되었습니다. , 여유 저장 공간이 충분하면 서비스 워커가 등록됩니다 . 해당 기준을 충족하지 않는 브라우저나 기기는 서비스 워커로 끝나지 않지만 이전과 동일한 Google 검색 환경을 계속 볼 수 있습니다.
이 선택적 등록의 한 가지 이점은 더 작고 더 효율적인 서비스 작업자를 배송할 수 있다는 것입니다. 상당히 현대적인 브라우저를 대상으로 서비스 작업자 코드를 실행하면 이전 브라우저에 대한 트랜스파일 및 폴리필의 오버헤드가 제거됩니다. 이로 인해 서비스 작업자 구현의 전체 크기에서 약 8KB의 압축되지 않은 JavaScript 코드가 제거되었습니다.
문제: 서비스 작업자 범위
검색 팀이 충분한 대기 시간 실험을 실행하고 탐색 사전 로드를 사용하면 서비스 작업자를 사용하기 위한 실행 가능하고 대기 시간 중립적인 경로가 제공된다는 확신이 들면서 몇 가지 실제적인 문제가 전면에 등장하기 시작했습니다. 이러한 문제 중 하나는 서비스 작업자의 범위 지정 규칙 과 관련이 있습니다 . 서비스 워커의 범위는 잠재적으로 제어할 수 있는 페이지를 결정합니다.
범위 지정은 URL 경로 접두사를 기반으로 작동합니다. /단일 웹 앱을 호스팅하는 도메인의 경우 일반적으로 도메인 아래의 모든 페이지를 제어할 수 있는 최대 범위의 서비스 워커를 사용하므로 이는 문제가 되지 않습니다 . 하지만 Google 검색의 URL 구조는 조금 더 복잡합니다.
서비스 워커에 의 최대 범위가 주어지면 서비스 워커 /는 아래(또는 이에 상응하는 지역)에서 호스팅되는 모든 페이지를 제어할 수 있게 되며 www.google.com해당 도메인 아래에는 Google 검색과 관련이 없는 URL이 있습니다. 보다 합리적이고 제한적인 범위는 /search최소한 검색 결과와 전혀 관련이 없는 URL을 제거하는 것입니다.
불행하게도 해당 /searchURL 경로는 표시되는 특정 유형의 검색 결과를 결정하는 URL 쿼리 매개 변수와 함께 다양한 Google 검색 결과 간에 공유됩니다. 이러한 특징 중 일부는 기존 웹 검색 결과 페이지와 완전히 다른 코드베이스를 사용합니다. 예를 들어 이미지 검색과 쇼핑 검색은 둘 다 /search다른 쿼리 매개변수를 사용하여 URL 경로에서 제공되지만 이러한 인터페이스 중 어느 것도 자체 서비스 작업자 경험을 제공할 준비가 되지 않았습니다(아직).
솔루션: 디스패치 및 라우팅 프레임워크 생성
서비스 작업자 범위를 결정하기 위해 URL 경로 접두사보다 더 강력한 것을 허용하는 몇 가지 제안이 있지만 Google 검색 팀은 제어하는 페이지의 하위 집합에 대해 아무 작업도 수행하지 않는 서비스 작업자를 배포하는 데 어려움을 겪었습니다.
이 문제를 해결하기 위해 Google 검색 팀은 클라이언트 페이지의 쿼리 매개변수와 같은 기준을 확인하고 이를 사용하여 내려갈 특정 코드 경로를 결정하도록 구성할 수 있는 맞춤형 디스패치 및 라우팅 프레임워크를 구축했습니다. 규칙을 하드코딩하는 대신, 시스템은 유연하게 구축되었으며 이미지 검색 및 쇼핑 검색과 같은 URL 공간을 공유하는 팀이 구현하기로 결정한 경우 자체 서비스 워커 로직을 라인 아래로 드롭할 수 있습니다.
문제: 개인화된 결과 및 지표
사용자는 Google 계정을 사용하여 Google 검색에 로그인할 수 있으며 검색 결과 환경은 특정 계정 데이터를 기반으로 맞춤설정될 수 있습니다. 로그인한 사용자는 유서 깊고 널리 지원되는 표준인 특정 브라우저 쿠키 로 식별됩니다.
그러나 브라우저 쿠키 사용의 한 가지 단점은 쿠키가 서비스 작업자 내부에 노출되지 않으며 자동으로 해당 값을 검사하고 사용자 로그아웃 또는 계정 전환으로 인해 변경되지 않았는지 확인할 방법이 없다는 것입니다. ( 서비스 작업자에게 쿠키 액세스를 제공하기 위한 노력이 진행 중이지만 이 글을 쓰는 시점에서 접근 방식은 실험적 이며 널리 지원되지 않습니다.)
현재 로그인한 사용자에 대한 서비스 워커의 보기와 Google 검색 웹 인터페이스에 로그인한 실제 사용자 간의 불일치로 인해 잘못 개인화된 검색 결과 또는 잘못된 측정항목 및 로깅이 발생할 수 있습니다. 이러한 실패 시나리오는 모두 Google 검색 팀에 심각한 문제가 될 것입니다.
해결 방법: postMessage를 사용하여 쿠키 보내기
실험적 API가 실행되어 서비스 작업자 내부의 브라우저 쿠키에 대한 직접 액세스를 제공할 때까지 기다리지 않고 Google 검색 팀은 서비스 작업자가 제어하는 페이지가 로드될 때마다 페이지에서 관련 쿠키를 사용하여 postMessage()서비스 작업자에게 보냅니다.
그런 다음 서비스 작업자는 현재 쿠키 값을 예상 값과 비교하여 확인하고 일치하지 않는 경우 스토리지에서 사용자별 데이터를 제거하는 단계를 수행하고 잘못된 개인 설정 없이 검색 결과 페이지를 다시 로드합니다.
서비스 작업자가 항목을 기준으로 재설정하기 위해 수행하는 특정 단계는 Google 검색의 요구 사항에 따라 다르지만 동일한 일반적인 접근 방식이 브라우저 쿠키에서 키가 제거된 개인화된 데이터를 처리하는 다른 개발자에게 유용할 수 있습니다.
문제: 실험과 역동성
언급한 바와 같이 Google 검색 팀은 프로덕션에서 실험을 실행하고 기본적으로 새 코드 및 기능을 켜기 전에 실제 세계에서 그 효과를 테스트하는 데 크게 의존합니다. 이는 캐시된 데이터에 크게 의존하는 정적 서비스 작업자에게는 약간의 문제가 될 수 있습니다. 사용자를 실험에 참여시키거나 제외하려면 종종 백엔드 서버와의 통신이 필요하기 때문입니다.
솔루션: 동적으로 생성된 서비스 워커 스크립트
팀이 선택한 솔루션은 미리 생성되는 단일 정적 서비스 워커 스크립트 대신 웹 서버에서 각 개별 사용자에 대해 사용자 정의한 동적으로 생성된 서비스 워커 스크립트를 사용하는 것이었습니다. 일반적으로 서비스 작업자의 동작이나 네트워크 요청에 영향을 미칠 수 있는 실험에 대한 정보는 이 사용자 정의된 서비스 작업자 스크립트에 직접 포함됩니다. 사용자의 활성 경험 세트 변경은 브라우저 쿠키와 같은 기존 기술의 조합과 등록된 서비스 작업자 URL에 업데이트된 코드 제공을 통해 수행됩니다.
동적으로 생성된 서비스 작업자 스크립트를 사용하면 서비스 작업자 구현에 피해야 하는 치명적인 버그가 있는 드문 경우에 탈출구를 더 쉽게 제공할 수 있습니다. 동적 서버 작업자 응답은 no-op 구현 일 수 있으며 현재 사용자의 일부 또는 전체에 대해 서비스 작업자를 효과적으로 비활성화합니다.
문제: 업데이트 조정 #
실제 서비스 작업자 배포가 직면한 가장 어려운 과제 중 하나는 캐시를 선호하는 네트워크를 피하는 동시에 기존 사용자가 배포 후 곧 중요한 업데이트 및 변경 사항을 받도록 보장하는 것 사이에서 합리적인 절충안을 고안하는 것입니다. 생산에. 올바른 균형은 많은 요인에 따라 달라집니다.
- 웹 앱이 사용자가 새 페이지로 이동하지 않고 무한정 열어 두는 수명이 긴 단일 페이지 앱 인지 여부입니다.
- 백엔드 웹 서버 업데이트에 대한 배포 주기입니다.
- 일반 사용자가 웹 앱의 약간 오래된 버전을 사용하는 것을 용인할지, 아니면 신선도가 최우선 순위인지 여부.
서비스 작업자를 실험하는 동안 Google 검색 팀은 여러 예약된 백엔드 업데이트에서 실험을 계속 실행하여 측정항목과 사용자 경험이 실제 사용자가 보게 될 것과 더 가깝게 일치하도록 했습니다.
주의
해결책: 신선도와 캐시 활용도의 균형
다양한 구성 옵션을 테스트한 후 Google 검색 팀은 다음 설정이 최신성과 캐시 활용 사이에 적절한 균형을 제공한다는 사실을 발견했습니다.
서비스 작업자 스크립트 URL은 Cache-Control: private, max-age=1500(1500초 또는 25분) 응답 헤더와 함께 제공되며 헤더가 적용되도록 'all'로 설정된 updateViaCache에 등록 됩니다. Google 검색 웹 백엔드는 상상할 수 있듯이 가능한 한 100%에 가까운 가동 시간을 요구하는 전 세계적으로 분산된 대규모 서버 집합입니다. 서비스 작업자 스크립트의 콘텐츠에 영향을 주는 변경 사항 배포는 롤링 방식으로 수행됩니다.
사용자가 업데이트된 백엔드에 도달한 다음 아직 업데이트된 서비스 작업자를 받지 못한 백엔드에 도달하는 다른 페이지로 빠르게 이동하면 버전 간에 여러 번 플립플롭하게 됩니다. 따라서 마지막 확인 이후 25분이 경과한 경우에만 업데이트된 스크립트를 확인하도록 브라우저에 지시하는 것은 큰 단점이 없습니다. 이 동작에 대한 옵트인의 장점은 서비스 워커 스크립트를 동적으로 생성하는 엔드포인트에서 수신하는 트래픽을 크게 줄이는 것입니다.
또한 서비스 작업자 스크립트의 HTTP 응답에 ETag 헤더가 설정되어 25분이 지난 후 업데이트 확인이 수행될 때 서비스에 대한 업데이트가 없는 경우 서버가 HTTP 304 응답으로 효율적으로 응답할 수 있습니다 . 임시 배치된 작업자.
Google 검색 웹 앱 내의 일부 상호작용은 단일 페이지 앱 스타일 탐색(예: History API 를 통해 )을 사용하지만 대부분의 경우 Google 검색은 "실제" 탐색을 사용하는 기존 웹 앱입니다. 팀에서 서비스 작업자 업데이트 수명 주기를 가속화하는 두 가지 옵션인 clients.claim()및 를 사용하는 것이 효과적이라고 결정했을 때 이 기능이 작동합니다 skipWaiting(). Google 검색의 인터페이스를 클릭하면 일반적으로 새 HTML 문서로 이동하게 됩니다. 호출하면 skipWaiting업데이트된 서비스 워커가 설치 직후 이러한 새 탐색 요청을 처리할 수 있는 기회를 얻을 수 있습니다. 마찬가지로 호출은 clients.claim()업데이트된 서비스 워커가 서비스 워커 활성화 후 제어되지 않는 열려 있는 Google 검색 페이지를 제어할 수 있는 기회를 얻는다는 것을 의미합니다.
Google 검색의 접근 방식이 반드시 모든 사람에게 적합한 솔루션은 아닙니다. 가장 적합한 옵션을 찾을 때까지 제공 옵션의 다양한 조합을 신중하게 A/B 테스트한 결과였습니다. 백엔드 인프라를 통해 업데이트를 더 빠르게 배포할 수 있는 개발자는 항상 HTTP 캐시를 무시하여 브라우저에서 가능한 한 자주 업데이트된 서비스 작업자 스크립트를 확인하는 것을 선호할 수 있습니다 . 사용자가 오랫동안 열어 둘 수 있는 단일 페이지 앱을 빌드하는 경우 사용하는 것이 올바른 skipWaiting()선택이 아닐 수 있습니다 . 오래 사는 클라이언트.
주요 내용
기본적으로 서비스 작업자는 성능 중립적이지 않습니다.
웹 앱에 서비스 작업자를 추가한다는 것은 웹 앱이 요청에 대한 응답을 받기 전에 로드하고 실행해야 하는 추가 JavaScript 부분을 삽입하는 것을 의미합니다. 이러한 응답이 네트워크가 아닌 로컬 캐시에서 오는 경우 서비스 워커를 실행하는 오버헤드는 일반적으로 캐시 우선으로 전환하여 얻을 수 있는 성능에 비해 무시할 수 있습니다. 그러나 서비스 작업자가 탐색 요청을 처리할 때 항상 네트워크를 참조해야 한다는 것을 알고 있다면 탐색 사전 로드를 사용하는 것이 성능에 중요한 이점입니다.
서비스 작업자는 (여전히!) 점진적인 향상입니다.
서비스 근로자 지원 이야기는 1년 전보다 오늘날 훨씬 더 밝습니다. 모든 최신 브라우저는 이제 서비스 워커에 대한 최소한의 지원을 제공 하지만 불행히도 백그라운드 동기화 및 탐색 사전 로드와 같은 일부 고급 서비스 워커 기능은 보편적으로 출시되지 않습니다. 필요하다고 알고 있는 기능의 특정 하위 집합에 대한 기능을 확인하고 해당 기능이 있는 경우에만 서비스 작업자를 등록하는 것은 여전히 합리적인 접근 방식입니다.
마찬가지로 실제 환경에서 실험을 진행했고 저가형 장치가 서비스 워커의 추가 오버헤드로 인해 성능이 저하된다는 사실을 알고 있다면 이러한 시나리오에서도 서비스 워커를 등록하지 않을 수 있습니다.
서비스 워커 는 모든 전제 조건이 충족되고 서비스 워커가 사용자 경험과 전반적인 로딩 성능에 긍정적인 무언가를 추가할 때 웹 앱에 추가되는 점진적 향상 으로 계속 취급해야 합니다 .
모든 것을 측정
서비스 작업자 배송이 사용자 경험에 긍정적인 영향을 미쳤는지 부정적인 영향을 미쳤는지 알아낼 수 있는 유일한 방법은 결과를 실험하고 측정하는 것입니다.
의미 있는 측정 설정의 세부 사항은 사용 중인 분석 공급자와 배포 설정에서 일반적으로 실험을 수행하는 방법에 따라 다릅니다. Google Analytics를 사용하여 메트릭을 수집하는 한 가지 접근 방식은 Google I/O 웹 앱에서 서비스 작업자를 사용한 경험을 기반으로 하는 이 사례 연구 에 자세히 설명되어 있습니다.
비 목표
웹 개발 커뮤니티의 많은 사람들이 서비스 작업자를 Progressive Web Apps 와 연결하지만 "Google 검색 PWA"를 구축하는 것은 팀의 초기 목표가 아니었습니다. Google 검색 웹 앱은 현재 웹 앱 매니페스트를 통해 메타데이터를 제공하지 않으며 사용자가 홈 화면에 추가 흐름을 거치도록 권장하지도 않습니다 . 검색 팀은 현재 Google 검색의 기존 진입점을 통해 웹 앱을 방문하는 사용자에 만족하고 있습니다.
Google 검색 웹 경험을 설치된 애플리케이션에서 기대할 수 있는 것과 동일하게 바꾸려고 하기보다 초기 롤아웃의 초점은 기존 웹 사이트를 점진적으로 개선하는 것이었습니다.
감사의 말
서비스 작업자 구현 작업에 참여하고 이 기사를 작성하는 데 사용된 배경 자료를 공유해 준 전체 Google 검색 웹 개발 팀에 감사드립니다. Philippe Golle, Rajesh Jagannathan, R. Samuel Klatchko, Andy Martone, Leonardo Peña, Rachel Shearer, Greg Terrono, Clay Woolam에게 특별히 감사드립니다.
업데이트(2021년 10월): 이 문서가 처음 게시된 이후 Google 검색팀은 현재 서비스 작업자 아키텍처의 이점과 장단점을 재평가했습니다. 위에 설명된 서비스 작업자가 사용 중지됩니다. Google 검색 웹 인프라가 발전함에 따라 팀은 서비스 작업자 디자인을 다시 검토할 수 있습니다.
※ 쿠팡 파트너스 활동을 통해 일정액의 수수료를 제공 받을 수 있습니다
'∮adsense ≒ 애드센스' 카테고리의 다른 글
수익형 블로그 애드센스 수익의 조건과 장단점 (0) | 2023.03.10 |
---|---|
구글 애드센스를 활용하여 수익을 창출하는 방법 (0) | 2023.03.10 |
이슈 블로그 만드는 방법 [상위 노출 방법] 이슈블로그 만들기 (0) | 2023.03.03 |
구글 애드센스 결제 정보 입력(은행 입력) (0) | 2023.03.02 |
구글 애드센스 광고 수익 잘 내기 위한 방법 (0) | 2023.02.20 |
댓글