들어가며
최근 다니는 회사에서 사내 라이브러리 개선을 진행하고 있습니다. 그래서 이벤트에 대해 이것저것 학습하고 있는데요, 신기한 키워드에 대해 학습을 해서 기록겸 정리해둡니다.
PostgreSQL의 LISTEN
과 NOTIFY
를 이용하여 이벤트 기반 아키텍처를 구축할 수 있다는 사실을 아셨나요?
Redis Pub/Sub 처럼 PostgreSQL도 데이터 변경에 대해 구독할 수 있고 변경사항을 받아 처리할 수 있답니다.
해당 기능에 대해 요약하자면 '트랜젝션이 종료되고 commit 된 시점에 서버가 해당 이벤트를 받아 알 수 있는 기능' 입니다.
PostgreSQL LISTEN & NOTIFY
LISTEN 과 NOTIFY
는 PostgreSQL 이 제공하는 이벤트기반 비동기 처리 방식입니다. 한쪽에서는 특정 이벤트를 LISTEN으로 알리고, 다른 쪽에서는 LISTEN 을 통해 이벤트를 수신할 수 있습니다.
- 장점
- Polling 없이도 실시간 변경사항 유무를 받을 수 있음
- 이벤트가 발생할 때만 처리해주면 되므로 불필요한 부하 감소
- PostgreSQL 클라이언트 라이브러리에서 지원하는 API 활용 가능
LISTEN & NOTIFY 기본 사용법
1. NOTIFY – 이벤트 발생
NOTIFY
는 특정 채널에 알림을 보내는 역할을 합니다.
NOTIFY new, 'https://test.com/post/1';
위 쿼리는 newanswer
라는 채널을 구독하고 있는 모든 세션에 해당 URL을 알림으로 보냅니다.
2. LISTEN – 이벤트 구독
LISTEN
을 사용하면 특정 채널을 구독할 수 있습니다.
LISTEN new;
이제 해당 세션은 newanswer
채널에서 NOTIFY
가 오면 알림을 받을 수 있습니다.
3. 이벤트 감지 (LISTEN 대기)
아래는 파이썬 코드 예시입니다.
cursor = conn.cursor()
cursor.execute("LISTEN new;")
while True: # 계속해서 발행된 이벤트에 대해 poll합니다.
if select.select([conn], [], [], 5) == ([], [], []):
continue # 타임아웃 대기
conn.poll()
while conn.notifies:
notify = conn.notifies.pop(0)
주의할 점
- LISTEN을 등록한 세션이 닫히면 자동으로 해제됩니다.
- 🔥
NOTIFY
를 보냈을 때 LISTEN을 하고 있는 세션이 없으면 해당 알림은 유실됩니다. - 특정 세션만
NOTIFY
를 받을 수 있도록 설정하는 기능은 없으며, 채널 단위로만 작동합니다. - 오랫동안 실행되는 프로세스에서는 LISTEN을 계속 유지할 수 있도록 세션이 닫히지 않게 관리해야 합니다.
- 하지만 새로 연결된 세션에서는 LISTEN을 다시 실행하지 않으면 알림을 받을 수 없습니다. LISTEN은 세션별로 유지되기 때문에 연결이 끊어지면 다시 등록해야 합니다.
- 같은 채널을 LISTEN을 하고 있더라도 세션이 다르면 각자 이벤트를 받게 됩니다. 즉, 다른 세션이 해당 알림을 가져갔다고 해서 내 세션에서 사라지는 것이 아닙니다.
참고링크
- https://postgresql.kr/docs/current/sql-notify.html
- https://postgresql.kr/docs/current/sql-listen.html
- https://m-falcon.tistory.com/528