중복 광고 노출 방지(1) 클라이언트 식별 - 비로그인 유저를 어떻게 구분할 수 있을까?
프로젝트/수튜브 : 유튜브 클론코딩

중복 광고 노출 방지(1) 클라이언트 식별 - 비로그인 유저를 어떻게 구분할 수 있을까?

과거 프로젝트를 돌아보며

처음 Frontend 개발자를 희망했을 때 시작했던 개인 프로젝트 '수튜브'를 이어서 작업해보려고 합니다. 기획했던 기능을 다 개발하지 않고 방치해 두었던 것이 아쉬워서, 마무리를 짓는 것을 목표로 해보겠습니다.

 

 

제가 생각하는 '유튜브'를 구현하는 데 있어서 핵심 기능은 이 두 가지입니다.

 

1. 커스텀 비디오 컨트롤러
2. 광고 노출

 

유튜브를 참고하여 구현한 비디오 컨트롤러

 

 

광고 노출 기능

 

대략적인 화면 구현은 마쳤지만, 최종 목표는 같은 유저에게, 같은 광고를 중복 노출하는 것을 방지하는 것이었습니다. 이 플랫폼을 실제로 서비스한다면, 광고주는 많은 사람들이 광고를 보길 원할 것이고, 한 사람이 같은 광고를 계속해서 조회하는 일은 없어야 하기 때문입니다. (광고 노출 횟수당 광고 요금을 받는다고 가정했을 때..)

 

누가 어떤 광고를 봤는지 기록하기 위해서는, 우선 유저를 식별할 수 있어야 합니다. 특히, 이 프로젝트에서는 로그인 기능을 기획하지 않았기 때문에, 비로그인 유저도 식별할 수 있는 방법이 필요했습니다.

 

 

 


 

 

 

클라이언트 식별 : 비로그인 유저를 어떻게 구분할까?

로그인 외에 클라이언트를 식별할 수 있는 방법에 대해 알아보고, 이번 프로젝트에는 어떤 방법이 가장 적절한지 생각해 보았습니다.

 

식별 수단 식별 방법
HTTP헤더 Client-IP HTTP Client-IP 헤더의 IP 주소로 사용자 식별
From HTTP From헤더의 email 주소로 사용자 식별
쿼리 스트링 (뚱뚱한 URL) 쿼리스트링에 식별정보를 전달하여 활용
쿠키 쿠키에 식별정보를 저장하여 활용

 

 

1. HTTP 헤더의 사용자 정보로 식별하기

| Client-IP

제일 먼저 떠올렸던 것은 클라이언트 IP로 식별하는 방법입니다. 하지만 클라이언트 IP는 다양한 이유로 변화하기 때문에, 사용자 식별 용도로 활용하는 것은 어려워 보입니다.

 

IP가 변하는 다양한 원인들

  • 공유 IP 주소 : 공유기를 사용하여, 여러 사용자가 동일한 공인 IP 주소를 사용하는 경우
  • 프록시 서버 : 사용자가 프록시 서버를 통해 연결하여, 프록시 서버의 IP를 사용하는 경우
  • VPN : 사용자의 IP 주소를 숨기고, VPN 서버의 IP를 사용하는 경우
  • 네트워크 주소 변환 (NAT) : NAT(Network Address Translation)을 사용하여 IP를 변환하는 경우
  • Wifi 사용 : Wifi를 사용하여 IP주소가 동적 할당되는 경우 (다른 Wifi망으로 이동하면 IP가 변경됨)

 

| FROM

다음으로, HTTP From 요청 헤더는 email 주소를 담고 있습니다. 하지만 RFC7231을 살펴보면, 이를 접근제어나 인증의 용도로 활용해서는 안된다고 명확하게 언급하고 있습니다.

A server SHOULD NOT use the From header field for access control or authentication, since most recipients will assume that the field value is public information. (RFC7231 - 5.5.1 From)

 

From 헤더 필드는 크롤러와 같은 robot 사용자를 위한 것으로, robot이 과도하게 많은 요청을 보내면 서버 담당자가 연락을 취할 수 있도록 하기 위함이라고 합니다. 따라서 사용자 식별 용도로는 활용할 수 없습니다.

 

 

 

2. 쿼리 스트링에 사용자 식별 정보 담기 (뚱뚱한 URL)

뚱뚱한 URL은 쿼리 스트링에 사용자 식별정보를 담는 것을 의미합니다.

http://localhost:8080?uuid=2c606d8a-613f-43c6-9499-6afb9708e7a4

 

이런 URL은 미관상으로도 좋지 않지만, 유튜브처럼 사용자 간 URL 공유가 빈번한 서비스에는 적절하지 않다고 생각합니다. 또, 서비스를 이탈했다가 다시 접속하면 매번 다른 ID가 부여되니, 매번 다른 사용자로 인식할 것이고, 쿼리스트링 값이 변경될 경우 캐싱도 적용되지 않습니다.

 

 

 

3. 쿠키에 사용자 식별 정보 담기

마지막으로 쿠키에 사용자 식별 정보를 담는 방법입니다. 사용자가 처음 방문했을 때 ID를 생성하여 쿠키에 저장하고, 식별 정보로 활용하는 방법입니다.

 

쿠키에 저장된 uuid

 

물론 이 방법에도 단점은 있습니다. 사용자가 쿠키를 삭제하거나, 다른 브라우저/기기로 접속하는 경우, 다른 사용자로 인식하게 됩니다. 또, 같은 기기를 여러 사용자가 이용하는 경우에도 대응할 수 없습니다.

 

하지만 쿠키에는 IP와 달리 고유한 식별 값을 저장할 수 있고, 이 과정에서 뚱뚱한 URL처럼 미관을 해치지도 않습니다. 또한, Google Analytics의 GA4와 같은 많은 서비스에서 이미 이와 같은 방법을 활용하고 있습니다.

 

앞서 살펴본 방법들과 비교했을 때, 가장 단순하면서도 강력한 방법이기 때문에, 이번 프로젝트에서는 쿠키에 사용자 식별자를 생성하여 담아보았습니다.

 

 

| UUID 생성

비로그인 유저의 식별자로 중복 발생 확률이 적은 UUID를 선택했습니다. UUID는 간단하게 crypto 인터페이스의 randomUUID()를 활용하여 생성할 수 있습니다.

const uuid = self.crypto.randomUUID();

 

 

| 쿠키에 저장

쿠키는 name=value의 형식으로 이루어져 있으며, 다음 옵션을 설정할 수 있습니다.

 

속성 설명 비고
Expires 쿠키의 유효기간. GMT 형식의 Date. 만료 설정을 하지 않으면, Session과 같이, 브라우저 종료 시 사라짐. (Session Cookie)
Max-Age 쿠키의 만료일자(s).
Domain 쿠키가 전송될 도메인을 지정.
(미설정 시, 현재 도메인에서만 접근 가능)
-
Path 해당 path의 하위 경로에서만 쿠키에 접근 가능. -
Secure HTTPS 환경에만 Cookie를 전송하도록 제한. 쿠키 탈취 예방을 위한 보안 옵션.
HttpOnly 클라이언트 단에서 쿠키 탈취를 예방. javascript로 쿠키를 조회할 수 없음.
SameSite 쿠키가 같은 사이트로만 전송되도록 제한.
  • None: 제한 없음
  • Strict: 동일 사이트 요청에만 포함.
  • Lax: 외부로 POST하는 요청을 제외하고, 모든 요청에 포함.

 

 

아래는 간단하게 'uuid'라는 이름의 쿠키를 생성하고, Expires 속성을 설정하는 예시입니다.

const date = new Date();

date.setTime(date.getTime() + 48*60*60*1000);
document.cookie=`uuid=${uuid}; expires=${date.toGMTString()}`;

 

 

 

반응형