배치는 어떻게 하세요?

Pak Yeongjo·2022년 4월 7일
0

일 어떻게 하세요?

목록 보기
3/3

이 포스팅은 Django Crontab을 사용하여 Batch Job을 구현했던 경험에 대한 내용입니다.

0. Cron? Batch?

일괄 처리(batch processing)란 최종 사용자의 개입 없이 또는 (자원이 허가한다면) 실행을 스케줄링할 수 있는 작업(job)의 실행을 의미한다. 컴퓨터 프로그램 흐름에 따라 순차적으로 자료를 처리하는 방식이다. 초기의 일괄 처리 방식은 사용자와 상호작용하는 것이 불가능했지만, 운영 체제가 발전함에 따라 프로그램 입출력을 통해 상호작용하는 것이 가능해졌다. 일괄 처리는 1950년대 전자 컴퓨팅 초기 시절 이후 메인프레임 컴퓨터와 함께하고 있다.

소프트웨어 유틸리티 cron은 유닉스 계열 컴퓨터 운영 체제의 시간 기반 잡 스케줄러이다. 소프트웨어 환경을 설정하고 관리하는 사람들은 작업을 고정된 시간, 날짜, 간격에 주기적으로 실행할 수 있도록 스케줄링하기 위해 cron을 사용한다.

정기 결제 시스템을 생각해보자. 매일/매주/매월 정해진 날짜에 출근해서 결제 요청을 날리는게 즐겁지 않다면 정해진 스케줄대로 결제를 수행하는 프로그램을 세팅해두는게 맞을거다. 이걸 Batch, 혹은 Batch job이라고 하고 유닉스에서 이 작업을 도와주는게 cron이다. (사실 크론이라고 해도 알아듣고 배치라고 해도 먹히는거 같다.)

1. django-Crontab

역시 장고에는 이 작업을 수월하게 처리하기 위한 기깔난 라이브러리가 있다. release는 2016년이고 마지막 commit은 4년 전이라고 나와있지만 크게 신경쓰지 않기로 하자.

간단하게 소개하자면 얘를 쓰면 크론잡을 정말 쉽게 이용할 수 있다. 장고의 settings 부분에 CRONJOBS를 작성해주면 된다. 리스트 안에 튜플 형태로 각각의 잡을 선언해주면 되고 튜플은 cron expression, 실행할 함수 형태로 구성된다. 오래 된거라 그런가 cron expression이 묘하게 다른 느낌이긴 하지만 몇 번 맞추다보면 감이 온다.

선언이 끝났으면 python manage.py crontab add로 크론을 등록할 수 있다. 이 명령어는 장고에서 선언한대로 유닉스의 크론 스케줄러에 우리의 크론잡을 등록해준다.

끝이다. 난 방금 정기 결제 시스템을 설계하고 구현했다.

1.1 좋았던 점

역시 구현이 쉽다

리눅스의 스케줄링 시스템을 몰라도 상관없다. 처음부터 끝까지 파이썬 코드로 배치 액션을 구성할 수 있다. 심지어 크론을 모르는 사람에게 설명하기도 직관적이고 수월하다.

1.2 좋지 않았던 점

맥 OS에서는 확인이 안된다?

이 부분은 기억에 오류가 있을 수 있다. 직접 확인해보시길 권장한다.

맥도 당연히 유닉스 기반이다. 근데 맥에서는 이 크론잡을 수행할 수가 없다.
스케줄 표현식이 맞는지 확인하려면 리눅스 기반의 개발 서버나 테스트 서버에 올려보고 직접 돌려봐야 한다.

더 이상 업데이트 되지 않는 라이브러리다

굳이 모험을 감수할 필요는 없다고 생각한다.

배치 액션이 스케일아웃을 방해한다

리눅스 기반의 EC2 서버를 운영하고 있다고 생각해보자. 소스 코드는 어떤 방식으로든 서버에 올라갔을거고 서버에 직접 접속해서, 혹은 배포 세팅으로 크론잡을 등록했을 것이다. 이 크론은 정기 결제를 성실하게 수행한다.

이제 EC2에 auto scaling을 추가한다. 우리의 EC2는 2대로 늘었다. 배포 스크립트는 소스코드가 업데이트 될 때 크론잡에 변화가 있다면 리눅스 스케줄러에 새로운 크론잡을 등록하거나 삭제하는 커맨드를 수행한다.

사용자는 다음날 정기 결제가 같은 시간에 2번 수행된 경험을 겪게 될 것이다.

2. Lambda는 어떨까?

람다는 기본적으로 스케줄링을 지원한다.
다만 기존의 정기 결제 시스템은 아래와 같은 구성으로 되어있다.

  1. 당일의 결제 예정자를 찾는다.
  2. 개인의 결제 금액을 정한다.
  3. 결제를 요청한다.
  4. 결제 성공/실패에 따라 고객에게 메세지를 송신한다.
  5. 결제 성공/실패 내역을 저장한다.

1번부터 5번까지 모두 모놀리식 구조로 단일 서버와 단일 DB에 엮여있다.
당일 결제 예정자를 선별하는 작업과 결제 예정자들에게 결제를 요청하는 로직을 분리했으면 어떨까 싶다.

그러면 람다 크론으로 실행할 로직도 두 가지로 나뉜다.

  1. 운영 DB를 기반으로 결제 예정자, 결제 날짜, 결제 금액을 찾아서 운영 DB가 아닌 다른 저장소(SQS? DynamoDB?)에 적재하는 로직
  2. 1번의 저장소의 데이터를 기반으로 매일 당일의 결제 예정자에게 결제를 요청하는 로직

정기 결제와 같은 시스템의 경우에는 고객의 요청에 의해 정기 결제가 중단될 수도 있음을 생각해야 한다.

아 크론잡의 로깅도 생각해야 함

람다의 메모리나 실행 시간을 생각해봤을 때 대용량 배치 작업이 필요하면 람다는 부적합할수도 있음. 이 경우에는 EC2 기반의 AWS Batch가 대안이 될 수도

References

0개의 댓글