launchd에서만 죽는 프론트 빌드 스크립트, 환경변수 휘발 디버깅기
터미널에선 잘 되던 Next.js 빌드·OG 이미지 스크립트가 launchd에선 죽는 이유와, 환경변수 휘발을 잡는 3단계 점검법을 정리했어요.
새벽에 블로그를 빌드하고 OG 이미지를 만들어 두는 스크립트를 launchd에 걸어 뒀어요. 터미널에서 손으로 돌리면 멀쩡한데, 새벽 3시 예약 실행만 조용히 실패하더라고요. 혹시 이런 적 없나요?
증상: 화면은 멀쩡한데 링크가 비어 있다
처음엔 빌드 에러도 아니었어요. 발행은 됐는데 공유 카드의 OG 이미지 주소 앞부분이 비어 있었죠. Next.js는 NEXT_PUBLIC_로 시작하는 환경변수를 빌드 시점에 코드 안에 박아 넣어요. 값이 없으면 컴포넌트는 빈 값을 그대로 이어 붙이고 넘어가요. 화면은 그려지니 알아채기 어려운 실패예요.
원인: launchd는 내 셸 설정을 읽지 않는다
직접 돌려 보니 원인은 단순했어요. launchd는 .zshrc를 읽지 않아요. 터미널에서 export한 값, 노드 버전 관리자가 잡아준 node 경로가 전부 사라진 채로 스크립트가 시작돼요. launchctl setenv로 넣은 값도 재부팅하면 사라지고요. 그래서 "터미널에선 되는데 예약 실행만 죽는" 모양이 나와요.
잡는 방법: 3단계면 끝나요
- 환경 덤프부터: 스크립트 첫 줄에
env | sort > 로그경로를 넣고 한 번 돌려요. 터미널 결과와 나란히 비교하면 빠진 변수가 바로 보여요. 저는 필요한 값 2개(사이트 주소, node 경로)가 통째로 없었어요. - plist에 명시: 값은
EnvironmentVariables딕셔너리에 직접 적어요. PATH도 node가 설치된 경로를 포함해 다시 써 줘야 해요. - 로그 파일 분리:
StandardOutPath와StandardErrorPath를 각각 지정해요. 파일 2개만 있어도 다음 실패는 5분 안에 원인이 나와요.
<key>EnvironmentVariables</key>
<dict>
<key>NEXT_PUBLIC_SITE_URL</key>
<string>https://example.com</string>
<key>PATH</key>
<string>/path/to/node/bin:/usr/bin:/bin</string>
</dict>적용해 봤더니 다음 날 새벽 실행부터 OG 이미지 주소가 제대로 들어갔어요. 셋 다 해도 10분 정도면 끝나요.
프론트 쪽에서 막는 1줄
환경 문제는 또 생겨요. 그래서 컴포넌트가 조용히 넘어가지 못하게 빌드 단계에 가드 1줄을 만들어 보니 마음이 편해졌어요.
if (!process.env.NEXT_PUBLIC_SITE_URL) throw new Error('NEXT_PUBLIC_SITE_URL missing');테스트해 보니 값이 빠지면 빌드가 바로 멈추고, 에러 메시지에 무엇이 없는지 그대로 찍혀요. 화면이 그려진 뒤에 깨진 링크를 발견하는 것보다 훨씬 나아요. 사용자에게 보이는 에러 화면도 같은 원칙이에요. 상황, 원인, 해결을 한 줄씩 보여 주면 다음 행동이 정해져요.
- 셸 설정은 launchd에 없다
- 값은 plist에 직접
- 로그는 파일로 분리
- 빌드 가드로 조용한 실패 차단
마무리
라이프케어로그 블로그처럼 혼자 운영하는 자동화는 실패가 조용할수록 오래 방치돼요. 돌아가는 것과 맞게 돌아가는 것은 다르니, 무인 실행엔 로그나 화면 결과 같은 실표면을 하나 붙여 두세요. 작은 가드 1줄이 새벽 디버깅을 줄여 줘요.
관련 글
댓글
아직 댓글이 없어요. 첫 댓글을 남겨주세요.