Python에서 방문자 카운터를 만드는 방법에 대하여 알아봅니다.


! 방문자 카운터를 만들기 전에 생각할 부분
먼저 어떻게 구현할까를 생각해야겠죠. 고민이 필요한 부분은 크게 두 가지 입니다.

하나. 방문자 기준은 어떻게 세울 것인가?
방문자를 측정하는 기준을 세션으로 정했습니다. 즉 세션이 늘어나면 방문자 수가 카운트 업되어 나타나게 됩니다. 만약 다른 값인 페이지 뷰 또는 사용자 수를 고려하기 위해서는 더 많은 부분을 고민해야합니다. 사용자라면 ip, 회원 id 등 기준이 필요하며 서버에 정보를 저장하고 있어야하죠. 하지만 세션이라면? 세션 유지 여부만 판별하면 되므로 가장 간단하게 구현할 수 있게됩니다. 다만 방문자 = 세션 수라는 기준이 필요합니다.

둘. 어디에 어떻게 저장할 것인가?
기준이 정해지면 어떻게 무엇을 저장할지 필요합니다. 가장 간단한 기준으로 만들 것이므로 아래의 값만 사용하여 저장하려고 합니다.

- 년월 // 컬럼 1
- 일 // 컬럼 2
- 카운트 // 컬럼 3

매우 간단하죠? 세 개의 컬럼을 가진 데이터베이스를 만들어 저장하고자 합니다. 아래 예제는 몽고DB라는 가정으로 하였지만 어떤 DB를 사용하든 큰 차이는 없을 것 같습니다.


  [참고] 파일 저장소를 생각하는 건 어떨까?  
사실 간단한 카운트와 날짜만 저장하면 되므로 파일을 생성하는 부분에 대하여 고민했습니다. 파일을 사용해도 성능도 큰 문제 없고 파일 저장도 간단하기 때문입니다. 다만 방문자 수를 읽어야 하는데 오늘 방문자라면 큰 문제는 없겠지만 주간, 월간, 이전 데이터를 가져오기 위해서는 아무래도 간단한 데이터베이스가 효과적일 것 같아 결정했습니다. 그렇지만 파일 저장소를 사용하는 것도 생각해볼 만 합니다.


이제 아래부터는 실제로 구현된 코드를 보면서 자세히 알아보겠습니다.

스크린샷) 웹이즈프리에 동작하는 방문자 카운트 모습



# 파이썬 방문자 구현하기 예제 보기
그럼 직접 구현된 코드를 살펴보겠습니다. 그 전에 아래 코드는 다음의 프로세스로 실행되게 됩니다.

  • 1. 특정 페이지 방문시 파이썬의 get_update_visit() 함수를 호출
  • 2. get_update_visit() 함수는 세션을 확인해 새로운 세션만 카운터를 +1
  • 3. get_update_visit()에서 현재 방문자 수를 리턴함
  • 4. 페이지에서 현재 방문자 수를 화면에 출력함

프로세스를 보면 더 간단합니다. 이제 새로운 방문자가 site.py라는 페이지에 접근한다고 생각해봅시다.

@ site.py
cursor = get_update_visit();
return cursor['count']

site.py에서 방문자를 가져오는 이외의 코드는 모두 생략하고 단순히 방문자 숫자만 출력하도록 하였습니다. 이때 get_update_visit() 함수가 가장 중요한 부분입니다. 이 코드는 아래와 같습니다.
def get_update_visit():
  collection = 'visitCount'
  today = datetime.datetime.now()
  year = str(today.year)
  month = str(today.month)
  day = str(today.day)
  if len(month) == 1:
    month = '0' + month

  isNotCountUp = session.get('isNotCountUp') != 1

  # isNewSession? Add plus one and return count
  if isNotCountUp:
    session['isNotCountUp'] = 1

    # Update DB, visitCount
    query1 = {
      'year_month': year + month,
      'day': day
    }
    query2 = {
      '$inc': {
        'count': 1
      }
    }
    isUpsert = True
    mongoUpdate(collection, query1, query2, isUpsert)

  # Get and return the count of visit
  query3 = {
    'year_month': year + month,
    'day': day
  }
  cursor = mongoGet(collection, query3)

return toJson({ 'count': cursor['count'] })

위 코드를 나누어 설명하면 다음과 같습니다.

- 날짜와 방문자 수를 데이터베이스에 저장
- 이때 isNotCountUp 이름의 세션을 하나 만듦
- 세션 값이 1이 아닌 경우 오늘 날짜의 값에 1을 더하고 현재 카운트 출력
- 세션 값이 1이면 현재 카운트를 불러와 출력

이와 같이 동작하게 됩니다. 여기서 중요한 부분은 세션을 저장하고 저장된 세션 값을 기준으로 카운트 +1을 할 지의 여부를 결정한다는 사실입니다. 이 부분이 가장 핵심적인 부분이고 부수적으로 아래의 함수 세 가지는 위에서 사용된 함수(데이터베이스 연동 등등)입니다. 같이 Python 파일에 추가해 사용하면 됩니다.

@ MongoDB 관련
client = mongoService.getClient()
db = client.데이터베이스이름

def mongoUpdate(_collection, _query1, _query2, _isUpsert= False):
  collection = db[_collection]
  collection.update(_query1, _query2, upsert=_isUpsert)
  return 200

def mongoGet(_collection, _query):
  collection = db[_collection]
  cursor = collection.find_one(_query)
  return cursor

데이터 베이스에 접근해 값을 가져오기 위해 만든 간단한 get, update 함수입니다. 여기서 upsert 값을 True를 주면 만약 값이 없는 경우 insert로 동작하게 됩니다.

@ Cursor to JSON
from bson import json_util

def toJson(data):
  return json.dumps(data, default=json_util.default)

이 toJson()은 몽고DB에서 전달받은 커서를 JSON으로 변환할 때 자주 사용하는 방법입니다.

여기까지 모든 과정이 완료 되었습니다. 비교적 간단하게 방문자 카운터를 구현할 수 있었습니다.



# 마치면서
방문자를 어떻게 어떤 방식으로 구현할 것인가에 대한 고민이 많이 필요했습니다. 단순하게 금일, 전일, 금 주 방문자 수만 구현하면 되었고 처음에는 자바스크립트를 사용하여 api 형식으로 호출할까도 생각해 보았지만 카운트를 위한 DB 참조(인덱싱)가 빠르기 때문에 간단하게 내부 함수로 호출하도록 하였습니다.

추가적으로 유료 및 무료 툴, 라이브러리를 많이 찾을 수 있습니다. 그 중 하나가 바로 https://www.cutercounter.com 입니다. 무료이면서 필수 노출(?)해야 할 부분이 없고 스타일이 다양하며 사용도 매우 쉽더군요.

링크 바로가기 >
 https://www.cutercounter.com

다만 클릭시 해당 사이트로 이동하는 부분만 조금 걸렸는데 그 정도만 감수하면 꽤 괜찮은 방문자 수를 구현할 수 있습니다.

이 외에도 구글 Analytics의 API를 활용할 수도 있습니다. 또한 Python, 자바 등 여러 소스를 제공하는 것도 장점입니다. 단점이라면 앱ID 등 필수적인 설정 단계가 필요합니다. 물론 대부분의 API를 사용할 경우 사용 플랫폼, 앱ID 등등 설정이 필요하죠. 다양한 방법을 알아두는 것도 좋을 것 같습니다.