티스토리 뷰

PM2로 Node 서버를 띄우고 있었던 프로젝트에 스케줄링(cron)을 돌리는 로직을 추가하면서

cron을 제어하기 위해 .env에 환경변수를 설정해두었는데

설정을 미실행으로 해놔도 cron이 돌아가고 있었다.

 

 

 

cron 설정 코드

if (process.env.NODE_APP_INSTANCE === '0') {
    cron.schedule('0 * * * *', expiredEmailVerification, cronOption);
}
  • NODE_APP_INSTANCE === "0" → cron 실행
  • != "0" → cron 미실행

 

 

.env 설정 (cron 미실행을 위한)

NODE_APP_INSTANCE=1

 

이렇게 하면 조건문에 걸리지 않으니까 cron이 실행되지 않을 거라고 생각했다.

 

 

그런데…

logs를 보니 스케줄링이 정상적으로 실행중이었다. 1시간마다 정확히 로그가 찍히고 있었다.

2026-05-10 13:00:00 [INFO] : 만료된 인증 요청이 없습니다.
2026-05-10 14:00:00 [INFO] : 학교 이메일 인증 만료 처리 완료: 1명 반려

 

 

 

스케줄링을 꺼놨는데 왜 돌아가지???

 

 

 

먼저 환경변수 로딩이 정상적으로 되고 있는지 콘솔을 찍어봤다.

const cron = require("node-cron");
const cronOption = { scheduled: true, timezone: "Asia/Seoul"};

console.log('INSTANCE:', process.env.NODE_APP_INSTANCE);

if (process.env.NODE_APP_INSTANCE === '0') {
    console.log('cron 등록됨');

    cron.schedule('0 * * * *', expiredEmailVerification, cronOption);
    } else {
    console.log('cron 스킵됨');
}

 

결과

INSTANCE: 0
cron 등록됨

 

 

 

.env에 1로 설정했는데 왜 0일까?

 

 

 

원인

NODE_APP_INSTANCE는 내가 설정한 .env의 환경변수이면서 PM2 내부 환경변수이기도 하다.

 

 

아래 명령어를 치면 확인할 수 있다.

pm2 env 0

 

결과

 

 

그래서 아무리 프로젝트의 env에서 값을 1로 지정하더라도 PM2 env 값으로 덮어쓰기 때문에 내가 설정한 값은 실제 실행 환경에서 무시되고 있었던 것이다.

 

 

 

 

왜?

PM2에서 단일 인스턴스로 실행하면 PM2는 자동으로 환경변수 NODE_APP_INSTANCE를 0으로 설정한다.

 

PM2는 클러스터 모드에서 프로세스 번호를 식별해야 해서 내부적으로 환경변수를 자동 생성한다.

프로세스 값 프로세스 번호
instance 1 0
instance 2 1
instance 3 2

NODE_APP_INSTANCE는 PM2 전용 내부 변수에 가깝다. (개발자가 제어하는 변수 X)

 

 

 

해결

NODE_APP_INSTANCE를 직접 제어하려 하지 말고 cron 전용 환경변수를 새로 만들었다.

 

.env

CRON_ENABLED=true
 

 

코드 수정

if (process.env.CRON_ENABLED === 'true') {
    cron.schedule('0 * * * *', expiredEmailVerification, cronOption);
}
 

이제는 PM2와 충돌할 일이 없이 스케줄링이 정상적으로 제어가 가능해졌다!

 

 

 

 

 

Total
Today
Yesterday