개발일지 - 방문자 수집( 봇, 관리자, 크롤러 제외하기)
개발일지 · 2026.03.15 · 조회 4
Django 방문자 집계 만들기
웹사이트, 블로그를 운영하다 보면 가장 기본적으로 확인하고 싶은 것이 바로 방문자 수입니다.
얼마 전 방문자 수를 확인하기 위해 웹사이트에 접속하는 사용자의 방문자를 모두 기록 했더니 실제 접속했을 사용자보다 훨씬 많은 숫자에 놀랐습니다.
그 이유는 검색엔진 봇 (googlebot, Bingbot, Naverbot) 과 같은 검색엔진 봇(Bot)이나 SEO 크롤러 (Ahrefs, Semrush 등) 그 외 모니터링 프로그램, 관리자 페이지 접속, 동일 사용자의 반복 새로고침 등의 이유로 방문자 수가 급증하게 됩니다.
대표적인 검색엔진 봇 : Googlebot, Bingbot, Yandexbot, DuckDuckBot, BaiduSpider
SEO 분석 도구들이 수집하는 SEO 크롤러 : AhrefsBot, SemrushBot, MJ12Bot
프로그램 기반 접속 : python-requests, curl, wget, httpclient
그리고 의미 없는 경로로의 접속 : /admin, /static, /media, /favicon.ico, /robots.txt, /sitemap.xml, /manager
이전 방문 로그를 저장 하는 모델에 is_bot = models.BooleanField(default=False) 필드를 추가 했습니다.
def is_bot_traffic(user_agent: str) -> bool:
if not user_agent:
return True
ua = user_agent.lower()
bot_keywords = [
"bot", "spider", "crawl", "slurp", "crawler",
"googlebot", "bingbot", "yandexbot",
"duckduckbot", "baiduspider",
"semrushbot", "ahrefsbot", "mj12bot",
"python-requests", "wget", "curl"
]
return any(keyword in ua for keyword in bot_keywords)user_agent 는 브라우저 정보를 저장하는데 브라우저 정보에서 bot으로 판별되는 키워드들을 찾아 해당 키워드가 있다면 봇으로 처리하는 코드를 삽입해주었습니다.
def should_exclude_path(path):
excluded_prefixes = [
"/admin/",
"/manager/",
"/static/",
"/media/",
]
excluded_exact = [
"/favicon.ico",
"/robots.txt",
"/sitemap.xml",
]
if path in excluded_exact:
return True
return any(path.startswith(prefix) for prefix in excluded_prefixes)또 정상 경로가 아닌 의미 없는 접속이나 관리자 모드로 들어왔을 때 관리자를 제외하기 위한 것과 구글 서치나 네이버 서치어드바이저 등등 포털사이트에 직접 등록한 sitemap.xml 같은 파일로 접속되는 통계 모두 제외시켜 주었습니다.
def save_visitor_log(request):
path = request.path
user_agent = request.META.get("HTTP_USER_AGENT", "")
referer = request.META.get("HTTP_REFERER", "")
ip = get_client_ip(request)
if should_exclude_path(path):
return
is_bot = is_bot_traffic(user_agent)
VisitorLog.objects.create(
ip_address=ip,
path=path,
user_agent=user_agent,
referer=referer,
is_bot=is_bot
)
if not is_bot:
today = timezone.localdate()
session_key = f"visitor_{today}"
if not request.session.get(session_key):
daily, _ = DailyVisitor.objects.get_or_create(date=today)
daily.count += 1
daily.save()
request.session[session_key] = True하루 한 번만 방문자 증가와 함께 봇 여부와 관리자 페이지 제외까지 합니다.
class VisitorCountMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
save_visitor_log(request)
return response미들웨어에 등록하여 모든 요청에서 방문 로그를 자동으로 저장하도록 했습니다.
개인 서버에서 웹사이트를 운영중이고 메모리 용양의 한계가 있습니다. 집에서 사용하는 서버이다 보니 혼자서 사용하던 데이터나 그 외 마인크래프트 서버나 이것저것 자료가 많아서 데이터 용량이 많은데
DB에 데이터를 계속해서 저장하게 되면 접속량이 많은 봇들 때문에 DB가 사용량이 늘어나게 될텐데.. 봇을 로그에 저장할 건지 아니면 봇을 제외하고 일반 사용자만 저장할 것인지 고민하다가
우선 나중에 유저 데이터를 정확하게 분석하거나 특정 접속을 막기 위해서는 로그가 필요 할 것 같아 우선 데이터베이스에 넣고 나중에 관리자 페이지에서 필요없는 봇 데이터는 제거하는 기능을 만들기로 생각했습니다.
아직 까지는 봇 데이터를 저장한다고 문제가 될 것은 없기에 이런 기능은 나중에 추가될 것 같네요.