콘텐츠로 이동

Cron 작업 (자동화 스케줄)

문서 역할

  • 역할: 설명
  • 문서 종류: architecture
  • 충돌 시 우선 문서: 작업 목록/실행 주기/트리거 방식은 이 문서, 도메인별 상태 전이/환불/삭제/알림 판정은 각 정책 문서
  • 기준 성격: as-is

주기적으로 실행되는 자동화 작업을 정리한 문서이다. 이 문서가 우선하는 범위는 작업 목록, 실행 주기, 트리거 방식이다. 도메인별 상태 전이, 환불, 삭제, 알림 판정 규칙의 원문 SoT는 각 정책 문서를 따른다.

작업 목록

API route 배포와 운영 scheduler 활성화는 별개다. 아래 기준 주기는 의도한 운영 주기이며, 의도적 중지는 route는 배포되어 있지만 운영 scheduler가 호출하지 않는 상태다. route가 존재한다는 사실만으로 운영 실행 중이라고 판정하지 않는다.

작업 기준 주기 운영 호출 설명
checkSignup 매일 13시, 17시 활성 가입심사 미완료 알림
match2Day 30분 간격 활성 D-2일 매칭 채팅 활성화
matchToday 매일 10시 활성 D-day 매칭 알림
checkReview 30분 간격 활성 만남 3시간 후 후기 상태 전환
finishGroupMeetings 매시 00·30분 활성 N:N D-1 13시 개방 알림·시작 24시간 후 종료 영속화
checkMeetMember 30분 간격 활성 모임 30분 전 인원 미달 체크
checkMatch 1분 간격 활성 만료 매칭 자동 취소·CMS 미로그인 카드 분류
checkMember 매일 0시 의도적 중지 6개월 미접속 → HOLD
checkMatchCall 30분 간격 활성 만남 15분 전 보이스콜 활성화
checkDirectFinishMember 매일 0시 5분 활성 직진만남일 10일 경과 처리
autoDeleteMember 매일 활성 정책 기준 경과 후 데이터 삭제
remindMatchCard 1분 간격 활성 카드 만료 3시간 전 알림
sendAutoMatching 30분 간격 활성 예약 매칭 자동 발송
cleanupOldProfileVersions 매일 의도적 중지 정책 기준 프로필 버전 정리

match2Day의 현재 운영 root crontab 표현은 *,30 * * * *이므로 실효 주기는 매분이다. 위 30분 기준과 다른 현행 설정이며, 정상화 전까지 실제 호출은 매분 발생한다. 후속 정상화는 기술 부채 정리match2Day 운영 scheduler 주기 드리프트에서 추적한다.

매칭 자동 상태 변경

  • 매칭 상태 전이, 만료 판정, 환불 규칙의 원문 SoT는 매칭 운영 정책을 따른다.
  • 이 섹션은 어떤 cron 작업이 어떤 시점의 매칭을 다루는지 설명하는 요약본이다.

D-2일 (48시간 전)

SUGGEST_LOCATION  CHAT_OPEN
male_badge: NORMAL
female_badge: NORMAL

만남 3시간 경과

CHAT_OPEN  REVIEW_REQUIRE
match_expire_date: 만남일 + 3 23:59:59

만료 시 자동 취소

작업 설명 상세 기준
checkMatch 만료 조건에 도달한 매칭을 스캔해 종료 처리하고, 신규 CMS 여성 수신 카드의 발송 후 로그인 증가가 0회이면 낭비 카드로 분류한다. 상태 전이/환불/낭비 카드 기준은 매칭 운영 정책, 상태 도표는 매칭 FSM
remindMatchCard 카드 만료 전 사용자 리마인드 알림을 발송한다. 카드 만료 상태와 알림 의미는 매칭 운영 정책, 알림 타입은 푸시알림 운영 정책

미팅 자동 상태 변경

시점 변경
예정시간 1시간 경과 status → FINISH
예정시간 2시간 경과 chat_open → FINISH, 후기 알림
30분 전 인원 미달 status → FINISH, 삭제 알림

N:N 그룹미팅 채팅 개방 알림과 자동 종료

  • 채팅 접근 권한 자체는 cron이 아니라 최신 event_at으로 계산한다. 최초 모집 마감으로 채팅이 초기화된 활성 행사는 달력상 전날 KST 13시에 즉시 접근 가능하다.
  • finishGroupMeetings는 같은 실행에서 아직 처리하지 않은 현재 개방 경계를 최대 100건씩 따라잡아 호스트와 현재 APPROVED 참가자에게 채팅 개방 알림을 보낸다. 행사 일시 변경으로 경계가 달라지면 새 경계를 기준으로 다시 한 번 처리하며 같은 경계는 중복 처리하지 않는다.
  • 채팅이 열린 뒤 새로 승인된 참가자의 채팅 개방 알림은 cron 재실행이 아니라 Admin 승인 명령이 승인 알림과 함께 해당 참가자에게 직접 보충한다. 승인 transaction이 새 구성원의 개방 경계를 먼저 기록하므로 다음 cron은 같은 승인자를 다시 포함하지 않는다.
  • Admin 즉발과 cron은 채팅 구성원별 현재 개방 경계를 같은 중복 방지 기준으로 사용한다. cron은 미처리 구성원만 claim하고 행사 단위 marker는 batch 요약으로만 갱신한다. 수신자 준비 또는 t_alarm 저장이 실패하면 선점한 구성원별 marker와 cron의 행사 요약 marker를 이전 값으로 복구한다.

  • 업무 판정의 기준은 KST event_at + 24시간이다. 정확히 경계 시각부터 API가 유효 상태를 FINISHED로 계산하므로 후기 작성, 미작성 후기 신청 제한, 채팅 쓰기 차단과 Admin 변경 차단은 cron 지연·중단의 영향을 받지 않는다.

  • finishGroupMeetings는 채팅이 초기화된 저장 상태 OPEN·CONFIRMED 종료 대상을 한 번에 최대 100건씩 FINISHED로 영속화하고, 감사 로그·종료 시스템 메시지·후기 가능 알림을 따라잡는 sweeper다. 이미 후기를 쓴 회원에게는 뒤늦은 후기 알림을 보내지 않는다.
  • 개발계 dispatcher는 매분 실행하지만 이 job은 매시 00분·30분에 선택되므로 정상 상태의 영속화와 종료 시스템 메시지·후기 가능 알림·감사 로그는 최대 약 30분 늦을 수 있다. flock 대기, handler 실패, 배포 중단이나 backlog가 있으면 더 늦어질 수 있으며 이 지연을 사용자 권한의 정확성 근거로 삼지 않는다.
  • 운영 호출 설정은 repository가 아니라 외부 scheduler가 소유한다. 운영도 매시 00분·30분에 호출하도록 설정하고 배포 Gate에서 실제 주기와 인증·실패 관측을 별도로 확인한다.

회원 자동 상태 변경

조건 변경
마지막 로그인 6개월 경과 status → HOLD
탈퇴/차단 정책 기준 경과 개인정보 삭제

FCM 알림 발송

작업 알림 타입
checkSignup SIGNUP_PROFILE_EDIT_AGAIN, SIGNUP_FAVOR_INFO, SETTING_MEMBER_REVIEW_DENY_AGAIN
match2Day MATCH_D_DAY_2
matchToday MATCH_DAY
checkReview MATCH_4_HOUR_PASSED
checkMatchCall MATCH_VOICE_CALL(모바일 알림 노출 제외)
checkMeetMember MEET_DELETED
remindMatchCard MATCH_CARD_WILL_DISAPPEAR

데이터 정리

autoDeleteMember

탈퇴/차단 회원이 정책 기준 자동 정리 조건에 도달하면:

  • 개인정보 삭제 (이름, 직업, 위치 등)
  • 키 = 0 초기화
  • 연관 데이터 삭제 (19개 테이블)
  • 매칭/서비스 이용 기록은 보관
  • 삭제 범위와 예외 기준은 데이터 거버넌스 정책을 따른다.

cleanupOldProfileVersions

프로필 버전이 정책 기준 자동 정리 조건에 도달하면:

  • finalize된 이전 버전 삭제
  • 관련 이미지 파일 삭제
  • 현재 버전은 유지
  • 보관 기한과 삭제 예외는 데이터 거버넌스 정책을 따른다.

API 엔드포인트

모든 작업은 HTTP GET으로 트리거:

GET /admin/cron/checkSignup
GET /admin/cron/match2Day
GET /admin/cron/matchToday
GET /admin/cron/checkReview
GET /admin/cron/finishGroupMeetings
GET /admin/cron/checkMeetMember
GET /admin/cron/checkMatch
GET /admin/cron/checkMember
GET /admin/cron/checkMatchCall
GET /admin/cron/checkDirectFinishMember
GET /admin/cron/autoDeleteMember
GET /admin/cron/remindMatchCard
GET /admin/cron/sendAutoMatching
GET /admin/cron/cleanupOldProfileVersions

실행 방식

  • 운영은 root crontab의 외부 스케줄러에서 HTTP 호출
  • API 배포는 root crontab을 추가·수정하지 않으므로 route와 운영 호출 상태를 별도로 확인
  • 의도적 중지 작업은 route를 제거하지 않고 root crontab에서 호출하지 않음
  • 내부 node-cron 등 미사용

운영 API 배포 뒤 route와 root crontab을 대조하는 절차는 API 운영 배포 런북을 따른다.

개발계 안전 실행

  • 개발계 EC2의 user crontab에는 endpoint별 curl을 직접 등록하지 않는다.
  • coupler-api/ops/cron/development.crontab은 1분마다 단일 dispatcher를 실행하고, dispatcher가 Asia/Seoul 기준 due job을 manifest 순서대로 실행한다. 서로 다른 job도 같은 매칭·미팅 행을 변경할 수 있으므로 병렬 실행하지 않는다.
  • dispatcher는 loopback URL만 허용하고 x-dev-cron-token 비밀 헤더로 API에 인증한다. 토큰은 repository나 crontab에 넣지 않고 mode 600/etc/coupler-api/dev-cron.env에서 API와 dispatcher가 함께 읽는다.
  • flock으로 이전 run이 끝나지 않은 동안 다음 dispatcher의 중복 실행을 막는다.
  • API는 handler가 반환한 작업이 끝날 때까지 dev-data CLI와 같은 전역 MySQL advisory lock을 유지한다. lock을 획득하지 못하면 handler를 실행하지 않고 x-dev-cron-result: maintenance로 건너뛴다.
  • installer는 repository .runtime을 mode 700, log·lock을 mode 600으로 준비한다. dispatcher log는 10 MiB에서 최근 파일 하나로 회전한다.
  • 개발 cron 문맥에서는 DEV_CRON_EXTERNAL_DELIVERY_ENABLED=false를 기본값으로 사용해 FCM 외부 전송만 차단한다. 화면 검증에 필요한 t_alarm과 도메인 상태 변경은 유지한다.
  • autoDeleteMember, cleanupOldProfileVersionsDEV_CRON_DESTRUCTIVE_ENABLED=false에서 scheduler 대상과 API handler 양쪽이 fail-closed한다.
  • DEV_CRON_* 설정은 production startup에서 거부한다. 운영 cron의 실행 방식과 환경은 이 개발계 설정으로 변경하지 않는다.
  • 합성 member root가 한 건이라도 존재하면 모든 개발 cron handler를 실행하지 않고 maintenance SKIP한다. 합성 target 소유권 graph나 job별 lease를 cron에 복제하지 않는다.
  • 합성 root가 없을 때만 정상 개발 데이터를 대상으로 handler를 실행한다. DB 연결·root 확인·lock 해제에 실패하면 성공이나 maintenance로 완화하지 않고 CRON_DEV_DATA_FENCE_UNAVAILABLE로 실패한다.
  • 공통 exact parser는 lock 결과를 number 0|1, 합성 root count를 단일 row의 0 이상 number safe integer로만 허용한다. 문자열·boolean·null·array를 강제 변환하지 않는다. handler가 작성한 HTTP 응답은 메모리에 지연하고 advisory lock 해제가 number 1로 성공한 뒤에만 실제 response로 내보낸다.
  • GET_LOCK query 실패나 malformed 결과로 소유 여부가 불명확한 connection은 pool에 반환하지 않고 파기한다. 정확한 GET_LOCK=0만 미소유 connection으로 반환한다.
  • advisory lock 해제 실패와 정확한 해제 뒤 pool 반환 실패는 모두 connection을 파기하고 fence 오류로 처리한다. handler가 undefined 같은 non-Error로 reject해도 지연된 성공 응답은 재생하지 않는다.

설치·검증·삭제성 작업의 일회성 실행과 rollback은 개발계 cron 운영 흐름을 따른다.

관련 문서