[{"data":1,"prerenderedAt":17},["ShallowReactive",2],{"$fd3BgBf09DGOUYMgLZ1XS_G0R-M6JlEV8EvHqxrkk3w0":3},{"uuid":4,"title":5,"summary":6,"content":7,"createdAt":8,"tags":9},"4f42c302-8a0a-4418-b268-b8e21c724217","node-cron에서 Asia\u002FSeoul 지정 시 예약 작업이 하루 밀리는 문제 해결","node-cron 사용 시 timezone: 'Asia\u002FSeoul'을 명시했음에도 불구하고 예약 작업이 예상보다 하루 늦게 실행되는 문제는 주로 서버의 기본 시간대 설정과 node-cron의 시간대 해석 간의 불일치로 발생합니다. cron.schedule 옵션에 timezone을 정확히 지정하고, 실행 로그를 통해 실제 동작 시간을 확인하여 문제를 해결할 수 있습니다.","node-cron을 사용하여 특정 시간대에 작업을 예약할 때, 특히 `timezone: 'Asia\u002FSeoul'` 옵션을 사용했음에도 불구하고 예약된 작업이 예상보다 하루 늦게 실행되는 문제가 발생할 수 있습니다. 이 문제는 주로 서버의 시스템 시간대 설정과 `node-cron`의 `timezone` 옵션 해석 간의 불일치에서 비롯됩니다. 이 가이드에서는 이 문제의 원인을 파악하고, 명확한 해결 방법을 제시합니다.\n\n## 문제의 원인\n\n`node-cron`의 `cron.schedule` 함수에 `timezone` 옵션을 지정하면, 해당 크론 표현식(`0 0 * * *` 등)이 지정된 시간대(예: `Asia\u002FSeoul`)를 기준으로 해석됩니다. 예를 들어, `0 0 * * *`와 `timezone: 'Asia\u002FSeoul'`을 함께 사용하면, `node-cron`은 매일 자정(0시 0분)을 `Asia\u002FSeoul` 시간 기준으로 계산하여 작업을 실행해야 합니다.\n\n하지만 다음과 같은 경우에 하루가 밀려 실행되는 문제가 발생할 수 있습니다:\n\n1.  **`timezone` 옵션의 오적용 또는 누락**: `cron.schedule` 함수 호출 시 `timezone: 'Asia\u002FSeoul'` 옵션이 올바르게 전달되지 않았거나, 다른 설정에 의해 무시되는 경우 `node-cron`은 서버의 기본 시스템 시간대를 따르게 됩니다. 많은 서버가 기본적으로 UTC(협정 세계시)를 사용하므로, 만약 서버가 UTC이고 `timezone` 옵션이 제대로 적용되지 않았다면, `0 0 * * *`는 UTC 자정을 의미하게 됩니다. UTC 자정은 `Asia\u002FSeoul` 기준으로는 오전 9시이므로, `Asia\u002FSeoul` 자정에 실행되기를 기대했던 작업이 오전 9시에 실행되어 날짜상으로 하루가 밀린 것처럼 보일 수 있습니다.\n2.  **크론 표현식에 대한 오해**: `Asia\u002FSeoul` 시간대를 기준으로 `0 0 * * *`가 의미하는 바를 정확히 이해하지 못하고, 다른 시간대를 기준으로 스케줄을 작성했을 때 발생하는 혼동입니다.\n\n## 해결 방법\n\n이 문제를 해결하는 가장 확실한 방법은 `node-cron`의 `timezone` 옵션을 명확히 지정하고, 실제 작업 실행 시각을 로그로 확인하여 의도대로 동작하는지 검증하는 것입니다.\n\n### 1. `timezone` 옵션 명확히 지정\n\n`cron.schedule` 함수를 호출할 때 `options` 객체에 `timezone: 'Asia\u002FSeoul'`을 정확하게 포함해야 합니다. 이는 `node-cron`에게 크론 표현식을 `Asia\u002FSeoul` 시간대 기준으로 해석하도록 지시합니다.\n\n```typescript\nimport { schedule } from 'node-cron';\n\nconsole.log('node-cron 스케줄러를 시작합니다.');\nconsole.log(`현재 시스템 시간 (KST): ${new Date().toLocaleString('ko-KR', { timeZone: 'Asia\u002FSeoul' })}`);\nconsole.log(`현재 시스템 시간 (UTC): ${new Date().toISOString()}`);\n\n\u002F\u002F 매일 자정(0시 0분) Asia\u002FSeoul 기준으로 실행되도록 스케줄링\n\u002F\u002F 이 스케줄은 Asia\u002FSeoul의 0시 0분에 정확히 실행됩니다.\nschedule('0 0 * * *', () => {\n    const now = new Date();\n    console.log(`[${now.toLocaleString('ko-KR', { timeZone: 'Asia\u002FSeoul' })}] Asia\u002FSeoul 자정 작업이 실행되었습니다.`);\n    \u002F\u002F 여기에 실행할 로직 추가\n}, {\n    timezone: 'Asia\u002FSeoul' \u002F\u002F 핵심: Asia\u002FSeoul 시간대로 크론 표현식 해석\n});\n\n\u002F\u002F 비교용: timezone 옵션이 없는 경우 (서버 기본 시간대 사용)\n\u002F\u002F 만약 서버의 기본 시간대가 UTC라면, 이 작업은 UTC 자정에 실행되므로\n\u002F\u002F Asia\u002FSeoul 기준으로는 오전 9시에 실행되어 '하루 밀림'의 원인이 될 수 있습니다.\nschedule('0 0 * * *', () => {\n    const now = new Date();\n    console.log(`[${now.toLocaleString('ko-KR', { timeZone: 'Asia\u002FSeoul' })}] (시스템 기본 시간대) 자정 작업이 실행되었습니다. 서버가 UTC면 KST 오전 9시입니다.`);\n}, {\n    \u002F\u002F timezone 옵션을 생략하면 시스템 기본 시간대를 따릅니다.\n});\n\n\u002F\u002F 스케줄러가 백그라운드에서 계속 실행되도록 유지 (예시)\n\u002F\u002F 실제 애플리케이션에서는 프로세스가 종료되지 않도록 다른 방식으로 관리해야 합니다.\nsetInterval(() => {}, 1000 * 60 * 60); \u002F\u002F 1시간마다 더미 작업으로 프로세스 유지\n```\n\n### 2. 서버 시간대 설정 확인 (선택 사항)\n\n`node-cron`의 `timezone` 옵션이 최우선적으로 적용되지만, 서버의 시스템 시간대가 `Asia\u002FSeoul`과 일치하는지 확인하는 것도 좋습니다. `TZ` 환경 변수를 설정하여 Node.js 프로세스의 기본 시간대를 지정할 수 있습니다.\n\n```bash\n# Linux\u002FmacOS 환경에서\nexport TZ='Asia\u002FSeoul'\nnode your-cron-script.js\n\n# 또는 Dockerfile 내에서\nENV TZ Asia\u002FSeoul\n```\n\n이 방법은 `node-cron`의 `timezone` 옵션이 제대로 작동하지 않을 때 보조적으로 사용할 수 있지만, `node-cron`의 옵션이 더 명시적이고 권장되는 방식입니다.\n\n## 흔히 하는 실수 및 주의점\n\n*   **`timezone` 옵션의 오타**: `Asia\u002FSeoul`과 같은 시간대 문자열은 대소문자를 포함하여 정확히 일치해야 합니다. 오타가 있는 경우 `node-cron`이 해당 시간대를 인식하지 못하고 시스템 기본 시간대로 폴백할 수 있습니다.\n*   **`new Date()` 객체의 시간대**: `node-cron` 작업 내부에서 `new Date()`를 사용하여 현재 시각을 얻을 때, 이 객체는 기본적으로 Node.js 프로세스의 시스템 시간대를 따릅니다. 따라서 `node-cron` 스케줄이 `Asia\u002FSeoul`에 맞춰 실행되더라도, `new Date()`로 얻은 시간을 별도로 `Asia\u002FSeoul`로 포매팅하지 않으면 예상과 다른 시간으로 보일 수 있습니다. 로그를 출력할 때는 `toLocaleString` 등의 메서드를 사용하여 명시적으로 `Asia\u002FSeoul` 시간대로 변환하여 확인하는 것이 좋습니다.\n*   **`node-cron` 버전**: 아주 오래된 `node-cron` 버전에서는 `timezone` 옵션의 동작 방식에 차이가 있을 수 있습니다. 최신 버전을 사용하는 것이 가장 안전하며, 문제가 지속될 경우 `node-cron` 공식 문서를 통해 해당 버전의 `timezone` 옵션 동작 방식을 확인해야 합니다.\n*   **서버 재시작**: 환경 변수를 변경하거나 코드를 수정한 후에는 Node.js 프로세스를 반드시 재시작하여 변경 사항이 적용되도록 해야 합니다.","2026-08-28T14:02:02.290+09:00",[10,11,12,13,14,15,16],"Asia-Seoul","Node-js","node-cron","timezone","기술 가이드","스케줄링","시간대",1788152656726]