Hong의 모든 글

리타겟팅(Retargeting) 나를 계속 따라다니는 광고

온라인 광고 기법 중에 리타겟팅(ReTargeting)이라는 것이 있습니다. 움직이는 타겟을 따라다닌다는 말인데 여기서 타겟은 인터넷 사용자를 말합니다.

자신이 한 번 본적이 있는 상품에 대한 광고를 계속해서 보여주는 광고입니다. 한 번 쯤은 목격했을 것입니다. 이거 신기해 보일 수 있지만 실상은 매우 간단한 것입니다.

어떻게 내가 봤던 물건을 나에게 다시 광고하는가?

간단하게 쿠키를 사용합니다. 제3자쿠키(3rd party cookie)라고 합니다.

예를 들어 웹브라우저로 A라는 회사의 노트북에 대한 정보를 접속해서 본다고 가정하겠습니다.

1. 웹브라우저로 그 상품에 대한 정보가 있는 페이지에서 광고회사(제3자)의 자바스크립트를 호출해서 사용자가 어떤 상품을 보고 있는지 누구인지 등의 정보를 넘겨주고 동시에 광고회사에서는 사용자의 브라우저에 식별이 가능하도록 쿠키를 심어 놓습니다. 이 때 광고회사는 여러군데일 수 있습니다. 동시에 한군데 일 수도 있고 10군데 일 수도 있습니다.

2. 사용자가 다른 웹사이트인 뉴스, 블로그, 커뮤니티 등에 접속하면 그 사이트들은 광고회사와 제휴를 하고 있을 수 있는데 구글, 페이스북, 네이버, 다음 그리고 특정 광고회사와 직접할 수도 있습니다.

이때 구글과 다음 등은 다른 회사에게 다시 광고를 또 중계해 주는 방식을 할 수도 있고 직접 광고를 할 수도 있습니다. 이간 복잡하니 지금은 설명을 건너 뜁니다.

어쨌든 광고를 제공할 수 있는 회사 중에 아까 1에서 쿠키를 심어 놓은 회사중 하나 또는 여럿이 있고 이 회사들이 광고를 내보내겠다고 응답한다면 그때 이 회사들은 사용자가 봤던 상품의 배너이미지를 화면에 보여줍니다.

이것이 리타겟팅입니다.

모바일에도 그러던데 대체 어떻게 하는 것일까?

모바일 윕브라우저를 사용한다면 동일한 방식을 씁니다. 모바일앱인 게임이나 다른애플리케이션에서 보이는 것은 ADID 또는 IDFA라는 스마트폰에 기록되어 있는 임의식별코드를 이용합니다. 이 코드는 스마트폰에 자동으로 부착되는데 변경하거나 막도록 설정할 수 있습니다.

원리는 쿠키와 동일한데 이 아이디를 블럭하면 아무 광고나 보이게 됩니다.

가는 곳마다 계속 따라다니는 것은 어떻게 하는 것일까?

광고회사는 여러 매체와 제휴를 맺습니다. 즉 여러분이 다니는 유명한 사이트들이 많은 광고회사와 제휴를 하고 있고 많은 광고회사에게 접속 정보가 전달됩니다. 가는 곳마다 따라다니는 것 처럼 보이는 것입니다. 하지만 외부 광고회사와 제휴를 하지 않은 사이트도 있기 때문에 그런 사이트에서는 적어도 따라다니는 광고는 보이지 않습니다.

막으려면 어떻게 하면 될까?

브라우저를 시크릿모드로 사용하거나 쿠키를 블럭시키는 보안 브라우저를 사용하면 따라다니는 광고는 잘 나오지 않습니다. 하지만 그 자리에 전혀 관련없는 엉뚱한 광고가 보이게 됩니다.

따라다니는 광고인 리타겟팅 광고가 보이지 않을 뿐이지 다른 기법의 광고나 무작위 광고는 여전히 보여집니다.

광고를 완전히 안보이게 할 수는 없을까?

광고를 불록하는 확장소프트웨어를 사용하면 되지만 완벽하게 막지 못하고 특정 사이트는 광고를 차단하는 경우 내용물이 안보이도록 해놓기도 합니다.

내 개인정보와 행적이 다 노출될까?

노출 안됩니다. 업체들끼리 데이터를 익명화하거나 그룹화해서 숨기도록 강제되어 있습니다.

개연의 행적을 알아내거나 개인정보를 알아내려면 업체들끼리 한통속으로 짬짜미를 해야 하는데 그러기가 어렵고 금융사, 포털사, 광고사, 매체 등이 일심 동체가 되어서 서로 정보를 교환하거나 제공해야 하는데 현실적으로 그렇게 못합니다.

행여 했다가 걸리면 정부의 처벌이 강력하며 작은 회사는 멸망하게 됩니다. 그래서 안합니다.

그리고 개인정보, 개인행적추적 등에 대한 규제가 점점 심해지고 있고 3rd cookie와 ADID는 이제 사라지게 될 운명입니다.

제3자 쿠키를 막을 수 없는가?

Mac/IOS의 사파리 브라우저에서는 이미 막혀 있습니다. 크롬과 크롬기반의 브라우저는 2023년 12월 31일 기점으로 제3자 쿠키를 쓸 수 없게 됩니다.

안드로이드의 ADID는 조만간 기본 설정이 정보제공이 자동 허용에서 비허용으로 변경될 예정입니다.

시스템 만들기와 기술적인 숙제

리타겟팅을 하기위한 기본 설계는 간단합니다. 리타겟팅의 문제는 비즈니스적인 문제와 서버비용입니다.

사용자의 universal id를 관리해야 하기 때문에 key-value NoSQL이 있어야 합니다.

나머지 부속 시스템은 살을 붙이면 됩니다.

트래킹태그와 광고송출은 견고한 자바스크립트를 작성해서 각각 심어두면 됩니다.

트래킹태그 호출과 광고호출을 받아줄 대몬을 각각 만들어야 하는데 AWS lamda같은 것을 쓸 수 있겠지만 네트워크나 비용문제로 인해 자체 서버로 구축합니다.

C++, Java, GoLang, Rust 등을 이용해서 만들면 됩니다.

왜 쉽게 못하는가?

위와 같이 하면 되지만 말은 간단하지만 시스템은 실상 살을 붙이고 고가용성 등을 보장하려면 많은 삽질이 필요합니다. 게다가 앞서 비즈니스적인 문제를 말했는데 매체와 광고주가 각각 자기 사이트에 Javascript 코드를를 심어줘야 하는 문제가 있습니다.

대량의 트래픽

수만개의 매체와 수만개의 광고주, 수천만개의 상품이 있다고 할 때 이 트래픽을 모두 처리하는 것도 숙제입니다. 트래픽을 받아줄 서버와 데이터를 저장할 빅데이터 처리를 위한 스토리지와 서버버가 필요합니다. 배보다 배꼽이 큽니다.

어떤 광고를 보여줄 것인가?

사용자가 가장 최근에 본 제품들. 그러니까 약 24사긴 이내에 여러 제품을 사용자가 살펴봐고 그 내역이 NoSQL에 기록되어 있다고 할 때 그 중에 어떤 것을 보여줄 것인가 하는 것입니다.

그냥 간단하게 가장 최근에 본 것을 보여주면 되겠지 싶지만 실상은 그렇지 않습니다. 어떤 상품의 광고를 보여주며 그 광고를 클릭하고 물건을 결국 사고야말지는 상황에 따라 사람에 따라 제품에 따라 제품 종류에 따라 브랜드에 따라 모두 각기 다릅니다. 이걸 잘 선택하는 것이 기술입니다.

깊은 얘기는 생략합니다.

Get “https://registry-1.docker.io/v2/”: proxyconnect tcp: tls: first record does not look like a TLS handshake

docker build를 하던 중에 이런 오류가 날 때가 있다.

서버가 방화벽 안쪽에 있고 외부 네트워크로 나가기 위해서는 proxy를 써야하는 환경에서 HTTP_PROXY를 지정하지 않았기 때문에 생긴다.

환경변수에 HTTP_PROXY를 적어주면 된다.

Get "https://registry-1.docker.io/v2/": proxyconnect tcp: tls: first record does not look like a TLS handshake

sudo: add-apt-repository: command not found

Ubuntu에서 패키지를 설치하다보면 패키지를 받아야 할 레파지토리를 추가해줘야 하는다 그때 add-apt-repository를 사용합니다.

그런데 제목과 같이 에러가 발생하는 경우가 있습니다.

에러

sudo: add-apt-repository: command not found

설치 방법

아래와 같이 software-properties-common 패키지를 설치해주면 됩니다.

sudo apt-get install software-properties-common

Ubuntu에서 Aerospike 제거 방법

Aerospike는 추가, 삭제가 빠른 SSD기반의 대용량 데이터를 처리할 수 있는 NoSQL입니다.

Schemaless(스키마 없는) NoSQL이라고 하지만 Schema의 변경이 아주 자유롭지는 않습니다.

제거가 조금 까다롭습니다.

설치 방법

설치 방법은 아래의 문서를 보고 따라서 하면 됩니다.

https://docs.aerospike.com/server/operations/install/linux/ubuntu

제거 방법

제거 방법은 아래의 문서를 참조하면 되는데 아래에 명령어 세트를 적어 두었으니 그걸 참고해서 지워도 됩니다.

https://discuss.aerospike.com/t/how-to-remove-and-clean-up-an-aerospike-server-installation/4839

제거 코멘드

# 패키지 확인
sudo dpkg -l | fgrep aerospike

# 패키지 제거
sudo dpkg -r aerospike-tools
sudo dpkg -r aerospike-server-community

# 디렉토리 확인
sudo ls -al /etc/aerospike
sudo ls -al /opt/aerospike
sudo ls -al /var/log/aerospike
sudo ls -al /var/run/aerospike

# 제거
sudo rm -Rf /etc/aerospike
sudo rm -Rf /opt/aerospike
sudo rm -Rf /var/log/aerospike
sudo rm -Rf /var/run/aerospike

# 아래의 파일이나 디렉토리가 없어야 함
sudo ls -al /etc/init.d/aerospike
sudo ls -al /etc/logrotate.d/aerospike
sudo ls -al /usr/bin/aql
sudo ls -al /usr/bin/asadm
sudo ls -al /usr/bin/asbackup
sudo ls -al /usr/bin/asgraphite
sudo ls -al /usr/bin/asinfo
sudo ls -al /usr/bin/asloglatency
sudo ls -al /usr/bin/asrestore
sudo ls -al /usr/bin/asd
sudo ls -al /usr/bin/asfixownership
sudo ls -al /usr/bin/asmigrate2to3

엘라스틱서치 필드값으로 집계하기 ElasticSearch Aggregation Query (group by)

ElasticSearch는 RDMS가 아닙니다. DB가 아닙니다.

넓은 의미로는 데이터베이스라고 할 수는 있습니다. 데이터를 넣고 분석하고 삭제하는 등의 관리를 할 수 있으니까요. 하지만 RDBMS가 가진 많은 기능을 제공하지는 않고 그 중에 어낼리틱스 기능또한 제공되지 않는 것 중 하나입니다.

하지만 DB처럼 사용하려는 사용자 요구가 많고 엘라스틱서치 측에서도 계속해서 그런 어낼리틱스 기능을 지원하려고 하고 있습니다.

집계 쿼리(Aggregation Query)는 DB의 “group by”같은 것을 말합니다.

집계 쿼리를 사용할 때 주의할 것

  • 엘라스틱서치의 집계 쿼리는 부하가 심합니다.
  • 집계하려는 필드가 색인에 들어있지 않은 경우는 더 심합니다.

쓰고 싶으믄 크지 않은 인덱스에 대해서 하고 가능하면 대상 필드에 색인을 걸어 두는 것이 좋습니다.

쿼리 예제

aggregation 쿼리의 예제입니다. “createDate”라는 날짜 포맷의 컬럼을 기준으로 몇개의 문서가 있는지 집계하는 쿼리입니다. range는 날짜 구간입니다. 아래와 같은 형식으로 쿼리를 작성해서 응용해서 쓰면 됩니다.

{
    "query": {
      "range": {
        "createdDate": {
          "gt": "20220423",
          "lte": "20220523"
        }
      }
    },
    "aggs": {
        "group_by_state": {
          "terms": {
            "field": "createdDate"
          }
        }
    }
}

위와 같이 하면 집계 결과와 검색결과가 같이 나오는데 검색결과에 모든 필드가 포함됩니다. 필요 없는 것을 빼고 비교적 간략하게 받으려면 _source를 지정해주면 조금 더 낫습니다.

{
    "query": {
      "range": {
        "createdDate": {
          "gt": "20220423",
          "lte": "20220523"
        }
      }
    },
    "aggs": {
        "group_by_state": {
          "terms": {
            "field": "createdDate"
          }
        }
    },
    "_source": [
      "createdDate",
      "doc_id"
    ]
}

아예 hits에 결과를 안넣고 받으려면 size를 0으로 해주면 됩니다.

{
  "size": 0,
  "query": {
    "range": {
      "createdDate": {
        "gt": "20220423",
        "lte": "20220523"
      }
    }
  },
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "createdDate"
      }
    }
  }
}