[Django] webhook receiver (웹훅 수신)

2022. 6. 29. 22:51· Framework/Django

보통 웹훅을 사용하기 위한 코드를 구현하고

웹훅을 받는 부분에 대해 생각을 해본적이 없을 것이다.

현재 회사에서 메신저를 담당하고 있고 웹훅 수신(webhook receiver)를 구현 할 수 있는 기회가 생겨서
얼마 전 (2022년 2월) 에 배포를 했고, 약 4개월 정도 하루에 1000개 정도의 웹훅을 수신 하고 있다.

 

Django 로 웹훅 수신 (webhook receiver) 부분을 구현했고 고민 했던 부분들을 기록에 남기려고 한다.

누군가에게 도움을 받거나, 방향성을 제시 받은 부분이 아니라 옳지 않은 방법 일 수도 있지만 나중에 다시 보았을 때 

무엇을 고려하지 못했는지 깨달으면 더 좋을 것 같아서 남기는 것이 기록에 좋다고 생각했다.

 

1. 토큰

웹훅을 사용하면 보통 각자 고유의 토큰이 발급 된다.

Django auth token, Django jwt token 을 임의로 부분을 잘라 사용해서 인증을 하려고도 생각을 했었고,

다른방법으로 난수를 생성해서 database 에 넣고 인증 하려고도 생각했다.

구현 방법은 난수를 생성해서 database 에 넣고 클라이언트가 웹훅 수신쪽으로 POST 요청 할 때 인증을 한다. 

난수 생성 방법은 python module secrets 을 import 해서 사용했다.

https://docs.python.org/ko/3/library/secrets.html

 

secrets — 비밀 관리를 위한 안전한 난수 생성 — Python 3.10.5 문서

secrets — 비밀 관리를 위한 안전한 난수 생성 소스 코드: Lib/secrets.py secrets 모듈은 암호, 계정 인증, 보안 토큰 및 관련 비밀과 같은 데이터를 관리하는 데 적합한 암호학적으로 강력한 난수를 생

docs.python.org

secrets.token_hex([nbytes=None])

limjian@Jians-MacBook-Pro-13 ~ % python3
Python 3.9.10 (v3.9.10:f2f3f53782, Jan 13 2022, 17:02:14)
[Clang 6.0 (clang-600.0.57)] on darwin

Type "help", "copyright", "credits" or "license" for more information.
>>> import secrets
>>> secrets.token_hex(24)
'fab18d59cffd09ab7d8fa22d10fad18e4e9b0828d7788a38'
>>> secrets.token_hex(10)
'9fe2614c593bbcff1f20'
>>> secrets.token_hex(16)
'a54a07b48ca9ef881fa07173b3f3b104'
>>>

이런식으로 사용이 가능해서 클라이언트가 웹훅을 만들면 토큰을 바로 생성해 database 에 저장한다.

 

 

 

2. 수신 횟수 (ratelimit)

https://django-ratelimit.readthedocs.io/en/stable/

 

Django Ratelimit — Django Ratelimit 3.0.1 documentation

© Copyright 2020, James Socol Revision cc1c3d70.

django-ratelimit.readthedocs.io

Django ratelimit module 을 사용해 구현을 했다.

ip 에 따라 초, 분 당 수신 횟수에 대한 제한을 걸 수 있었지만, 테스트를 많이 해봤는데 가끔 요청 횟수가 넘어 갈 때가 있기는 한 것 같다. 

@ratelimit(key='ip', rate='60/m', method='POST')
def webhook():
	
    pass


두번째로 생각한 방법은 nginx 에서도 ratelimt 이 있지 않을까 생각을 했고,

찾아보니까 많은 결과가 나왔지만 직접 사용해 보진 않았고, 현재는 django module ratelimit 을 사용중이다.

 

3. log

비 정상적으로 Post 요청이 많이 올 수 있는 상황을 대비 해서 ratelimt 을 사용했지만,

혹시 모를 상황에 log 를 syslog file 에 찍히도록 해놓았다. 

logging module 을 사용했고

logging 을 사용해서 Django settings.py 설정, webhook receiver 함수 에서 log 를 찍는다.

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': "[%(asctime)s.%(msecs)03d] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
            'datefmt': "%d/%b/%Y %H:%M:%S"},
            'simple': {'format': '%(levelname)s %(message)s'},
    },
    'filters': {
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
        'webhook': {
            'level': 'DEBUG',
            'class': 'logging.handlers.SysLogHandler',
            'address': '/dev/log',
        },
    },
    'loggers': {
        'webhook': {
            'handlers': ['webhook'],
            'level': 'DEBUG',
            'propagate': True,
        },
    }
}
 
4. 그 외
프론트 (vue.js) 부분도 전부 직접 만들었기 때문에 생각 한 부분도 많았고.. 
비 정상적인 데이터 길이, 비 정상적인 데이터 형식 등 정말 많은 부분을 생각 했던 것 같다.



production 상태에서는 monitoring 툴 Sentry 도 사용을 하고 있는데
다행히  웹훅 수신 (webhook receiver)부분에서는 문제 발생이 되지 않는다.
웹훅 수신 (webhook receiver) 을 만든 이유는 고객이 요청해서 만들었고, 기한이 조금 촉박 했었지만
지금 그 요청한 고객들, 또 다른 고객들이 너무나 잘 사용하고 있어 만족감을 느낀다.
특히 같은 회사 개발자들에게도 편하다는 이야기를 종종 듣는다.


나중에.. 몇 달 뒤 구현해 놓은 코드를 다시 보면서, 더 생각해 봐야 될 부분과 문제점에 대해 생각을 해 봐야겠다. 
(nginx ratelimit 에 대해서도 한번 해보고 알아 놓아야 할 듯)
 

 

'Framework > Django' 카테고리의 다른 글

[Django] redis.exceptions.AuthenticationError (Authentication required)  (0) 2022.10.12
[Django] CORS (Cross-Origin Resource Sharing)  (0) 2022.07.16
[Django] models cached_property decorator  (0) 2022.02.23
[Django] models property decorator (@property)  (0) 2022.02.23
[Django] Ratelimit (django-ratelimit)  (0) 2022.02.17
'Framework/Django' 카테고리의 다른 글
  • [Django] redis.exceptions.AuthenticationError (Authentication required)
  • [Django] CORS (Cross-Origin Resource Sharing)
  • [Django] models cached_property decorator
  • [Django] models property decorator (@property)
임쟌
임쟌
임쟌
Jian's Blog
임쟌
전체
오늘
어제

공지사항

  • [자기소개]
  • 쟌's Blog (227)
    • Language (32)
      • Python (8)
      • Go (24)
      • Java (0)
    • Framework (10)
      • Django (9)
      • Gin (1)
      • Spring boot (0)
      • Fiber (0)
    • Database (10)
      • PostgreSQL (8)
      • MySQL (0)
      • Redis (2)
    • Server (51)
      • Linux (16)
      • Git (12)
      • Oracle Cloud Infrastructure (13)
      • Mac (4)
      • Docker (4)
      • RabbitMQ (0)
      • ETC (2)
    • Operating System (0)
      • OS (0)
    • Algorithm (22)
      • Go (22)
      • Python (0)
    • Exam Certification (4)
    • Daily Life (27)
      • Review (21)
      • Diary (6)
    • 이공계전문기술연수 (71)
      • Java (17)
      • Database (8)
      • HTML | CSS (13)
      • JavaScript | jQuery (6)
      • Servlet | JSP (16)
      • Spring Framework (11)

인기 글

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
임쟌
[Django] webhook receiver (웹훅 수신)
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.