안녕하세요, 하랑입니다.
지난 4월 11일 포스팅으로 GitHub Actions로 Supabase 무료 플랜의 자동 휴면을 방지하는 방법을 소개드렸는데요. 그 이후 뿌듯하게 세팅 완료! 하고 넘겼는데… 며칠 뒤 GitHub에서 메일이 한 통 날아왔습니다.
“Supabase Keep Alive #3 — ping: Process completed with exit code 6.”
워크플로우가 실패했다는 알림이었어요. 😱
Supabase가 잠들지 않게 깨워주려고 만든 워크플로우가 오히려 에러를 뱉고 있다니… 당황스러웠지만 차근차근 원인을 파악해보니 해결 방법이 명확했습니다. 같은 상황을 겪는 분들을 위해 오늘은 이 트러블슈팅 과정을 기록으로 남겨볼게요.
관련 포스팅: Supabase 무료 플랜, 2주면 잠든다? GitHub Actions로 자동 깨우는 법
📬 ping 이 실패했다고요?
GitHub Actions는 워크플로우가 실패하면 자동으로 등록된 이메일로 알림을 보냅니다. 제가 받은 메일의 내용은 이랬어요.

- 워크플로우 이름: Supabase Keep Alive
- 실패한 Job: ping
- 오류 메시지:
Process completed with exit code 6 - 소요 시간: 불과 2초 (즉, 연결 시도 자체가 실패한 것)
GitHub Actions 화면에서도 빨간 ❌ 표시와 함께 “ping: Process completed with exit code 6.” 라는 Annotation이 남아있었습니다.
🔍 Exit Code 6이 의미하는 것
exit code 6은 curl 명령어의 오류 코드입니다. curl의 공식 오류 코드표에 따르면:
Exit code 6 = Could not resolve host (호스트를 찾을 수 없음)
즉, curl이 지정된 URL의 도메인 주소를 DNS로 해석하지 못했다는 뜻입니다. 쉽게 말하면 “그 주소로 연결 자체가 안 됐어요” 라는 의미예요.
curl 주요 exit code를 간단히 정리하면 아래와 같습니다.
| Exit Code | 의미 |
|---|---|
| 0 | 성공 |
| 3 | URL 형식 오류 |
| 6 | 호스트 주소를 찾을 수 없음 (DNS 해석 실패) |
| 7 | 서버에 연결 실패 |
| 22 | HTTP 오류 응답 (4xx, 5xx) |
| 28 | 연결 타임아웃 |
제 경우에는 exit code 6, 즉 URL 자체를 인식하지 못한 상황이었습니다.
🧐 왜 이런 일이 발생했을까?
GitHub Actions 실행 기록을 보면 상황이 명확하게 보입니다.

4월11일에는 스케줄된 워크플로우가 성공했는데 4월 16일의 워크플로우만 실패했다는 게 핵심 단서입니다. Secret 설정이 문제였다면 #2도 실패했을 테니까요. 즉, 워크플로우 설정 자체는 잘못된 게 없었습니다.
진짜 원인: cron 주기와 Supabase Pause 타이밍이 겹쳤다
Supabase의 안내메일을 확인해보니 Supabase가 4월 16일, 워크플로우 실행과 같은 날 Pause 처리됐습니다.
타임라인을 재구성하면 이렇습니다.
- Apr 11 — 워크플로우 #2 성공 → Supabase 활성 상태 유지
- 그 이후 5일간 — Supabase에 아무 활동 없음
- Apr 16 — Supabase가 7일 비활성 기준에 의해 Pause 처리됨
- Apr 16 같은 날 — 워크플로우 #3 실행 → 이미 Paused 상태라 DNS 자체가 응답 안 함 → exit code 6
깨우러 갔더니 이미 문이 잠겨있던 상황이었던 거예요. 😅
왜 5일 주기인데 Pause가 됐을까?
지난 포스팅에서 cron을 */5 * * * (5일마다)로 설정했는데, 이론상으로는 Supabase 휴면 기준인 7일보다 짧으니 괜찮아 보입니다. 하지만 여기에 함정이 있었어요.
GitHub Actions의
schedule트리거는 정확한 실행 시간을 보장하지 않습니다.
GitHub 공식 문서에도 명시되어 있듯이, Actions 서버의 부하 상황에 따라 예약된 시간보다 수 분에서 수십 분, 심한 경우 몇 시간까지 지연될 수 있습니다. 실제로 저의 경우도 워크플로우가 실행되기 직전에 Supabase가 먼저 Pause 상태로 전환된 것으로 보입니다.
5일 주기 설정은 7일 기준에 얼핏 여유 있어 보이지만, 실제로는 아슬아슬한 간격이었던 거예요.
그 외 발생할 수 있는 원인들
처음 설정할 때 겪을 수 있는 다른 원인도 참고로 정리해 드립니다.
GitHub Secret이 비어있거나 잘못 등록된 경우 워크플로우 파일은 ${{ secrets.SUPABASE_URL }}처럼 Secret 값을 참조하는데, 아래 상황이라면 빈 값으로 치환되어 똑같이 exit code 6이 납니다.
- Secret 이름 오타 (예:
SUPABASE_URLS) - Secret 미등록 또는 삭제
- 값 앞뒤에 공백이 포함된 경우
https://없이 도메인만 입력한 경우
ping RPC 함수가 생성되지 않은 경우 지난 포스팅에서 Step 3를 선택사항으로 안내드렸는데요. ping() 함수를 생성하지 않으면 /rest/v1/rpc/ping 엔드포인트가 존재하지 않아 404 응답을 받거나 실패로 처리됩니다.
🛠️ 해결 방법
원인별로 대처 방법을 단계적으로 정리해볼게요.
✅ Step 1. GitHub Secrets 값 재확인
GitHub 저장소 > Settings > Secrets and variables > Actions로 이동해서 아래 두 가지를 확인합니다.
SUPABASE_URL이름이 정확히 일치하는지 (대소문자 구분!)SUPABASE_ANON_KEY도 동일하게 확인
Secret의 값은 보안상 등록 후에는 볼 수 없기 때문에, 의심스럽다면 Update를 눌러 값을 다시 붙여넣기 하세요. 이때 반드시 앞뒤 공백 없이 넣어야 합니다.
💡 팁: Supabase URL은
https://[프로젝트ID].supabase.co형식이어야 합니다.http://나 슬래시(/)로 끝나지 않도록 주의하세요.
✅ Step 2. Supabase 대시보드에서 프로젝트 상태 확인
Supabase 대시보드에 접속해서 해당 프로젝트가 Active 상태인지 확인합니다. 만약 Paused 상태라면:
- 프로젝트 카드에서 Restore 버튼 클릭
- 복구까지 수 분 대기
- 복구 완료 후 GitHub Actions에서 워크플로우를 수동 실행(Run workflow)해서 정상 동작하는지 확인
✅ Step 3. ping 함수 생성 여부 확인
Supabase 대시보드 > SQL Editor에서 아래 SQL을 실행해 ping 함수를 생성합니다. (이미 있다면 CREATE OR REPLACE이기 때문에 다시 실행해도 괜찮습니다.)
CREATE OR REPLACE FUNCTION ping()
RETURNS TEXT AS $$
BEGIN
RETURN 'pong';
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
✅ Step 4. 워크플로우 파일을 더 견고하게 수정하기
이번 트러블슈팅을 계기로, 워크플로우 파일을 좀 더 방어적으로 개선했습니다. 아래는 제가 수정한 최종 버전입니다.
가장 중요한 변경: cron 주기를 5일 → 3일로 줄였습니다.
5일 주기는 Supabase의 7일 기준에 이론상 여유가 있어 보이지만, GitHub Actions의 실행 지연을 감안하면 실제로는 아슬아슬합니다. 3일 주기로 설정하면 지연이 발생해도 충분한 버퍼가 생깁니다.
name: Supabase Keep Alive
on:
schedule:
- cron: '0 0 */3 * *' # ✅ 5일 → 3일로 변경!
workflow_dispatch:
jobs:
ping:
runs-on: ubuntu-latest
steps:
- name: Secret 값 확인
run: |
if [ -z "${{ secrets.SUPABASE_URL }}" ]; then
echo "❌ SUPABASE_URL이 설정되지 않았습니다!"
exit 1
fi
if [ -z "${{ secrets.SUPABASE_ANON_KEY }}" ]; then
echo "❌ SUPABASE_ANON_KEY가 설정되지 않았습니다!"
exit 1
fi
echo "✅ Secret 값 확인 완료"
- name: Supabase ping 호출 (최대 3회 재시도)
run: |
MAX_RETRY=3
WAIT_SEC=10
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_RETRY ]; do
ATTEMPT=$((ATTEMPT + 1))
echo "🔄 시도 $ATTEMPT / $MAX_RETRY"
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST '${{ secrets.SUPABASE_URL }}/rest/v1/rpc/ping' \
-H 'apikey: ${{ secrets.SUPABASE_ANON_KEY }}' \
-H 'Authorization: Bearer ${{ secrets.SUPABASE_ANON_KEY }}' \
-H 'Content-Type: application/json' \
--max-time 30)
echo "응답 코드: $RESPONSE"
if [ "$RESPONSE" -ge 200 ] && [ "$RESPONSE" -lt 300 ]; then
echo "✅ ping 성공 — Supabase가 살아있습니다!"
exit 0
fi
echo "⚠️ 응답 코드 $RESPONSE — ${WAIT_SEC}초 후 재시도합니다..."
sleep $WAIT_SEC
WAIT_SEC=$((WAIT_SEC * 2)) # 10초 → 20초 → 40초 (지수 백오프)
done
echo "❌ $MAX_RETRY 회 모두 실패했습니다."
exit 1
이전 버전과 다른 핵심 변경 사항은 다음과 같습니다.
- cron 주기 5일 → 3일: GitHub Actions 실행 지연을 감안한 안전한 간격
- 최대 3회 재시도 루틴 추가: 일시적인 네트워크 오류나 Supabase 응답 지연으로 실패한 경우 자동으로 재시도
- 지수 백오프(Exponential Backoff) 적용: 재시도 간격을 10초 → 20초 → 40초로 점점 늘려서 서버에 부담을 주지 않음
--fail옵션 대신 HTTP 상태 코드를 직접 캡처하여 로그에 출력하도록 변경- Secret 값이 비어있는지 사전 검증 단계 추가
--max-time 30으로 타임아웃 명시
💡 지수 백오프란? 재시도할 때마다 대기 시간을 2배씩 늘리는 방식입니다. 서버가 일시적으로 과부하 상태일 때 짧은 간격으로 계속 요청을 보내면 오히려 서버에 부담이 됩니다. 간격을 점점 늘려가며 재시도하는 것이 더 현명한 방법이에요.
📌 이번 경험에서 배운 것
사실 이런 트러블슈팅은 처음엔 당혹스럽지만, 결과적으로는 더 탄탄한 설정을 만들게 해줍니다. 이번에 배운 교훈을 정리하면:
- “이론상 괜찮다”와 “실제로 괜찮다”는 다르다. — 5일 주기는 7일 기준보다 짧으니 이론상 문제없어 보였지만, GitHub Actions의 실행 지연이라는 변수를 고려하지 못했어요. 자동화 설정은 항상 여유 버퍼를 넉넉하게 두는 게 맞습니다. 7일 기준이라면 절반인 3일 주기가 안전합니다.
- GitHub Actions 워크플로우 실패 알림을 무시하지 말자. — 귀찮더라도 원인을 꼭 파악해야 합니다. 특히 Supabase Keep Alive처럼 서비스 안정성과 직결된 워크플로우라면 더욱 그렇습니다.
- 실행 기록이 디버깅의 열쇠다. — #2는 성공, #3은 실패라는 기록 덕분에 “Secret 문제가 아니다”라는 걸 바로 좁혀낼 수 있었어요. GitHub Actions의 실행 히스토리는 꼭 확인하는 습관을 들이세요.
- 워크플로우에 검증 단계를 포함시키자. — 단순히 curl 한 줄만 넣는 것보다, 응답 코드를 로그에 남기는 것이 나중에 디버깅할 때 훨씬 편합니다.
- 비개발자도 GitHub Actions 오류를 읽을 수 있다. — 처음엔
exit code 6이라는 말 자체가 낯설었지만, 검색 한 번으로 curl 오류 코드표를 찾고, 원인을 역추적하는 과정이 생각보다 어렵지 않았어요. 무서워하지 않고 차근차근 읽어나가면 됩니다! 💪
✅ 최종 체크리스트
설정 완료 후 아래 항목을 한 번씩 확인해보세요.
- [ ]
SUPABASE_URLSecret이 정확히 등록되어 있다 - [ ]
SUPABASE_ANON_KEYSecret이 정확히 등록되어 있다 - [ ] Supabase SQL Editor에서
ping()함수가 생성되어 있다 - [ ] Supabase 프로젝트 상태가 Active이다
- [ ] GitHub Actions에서 Run workflow로 수동 실행 시 ✅ 표시가 뜬다
- [ ] cron 스케줄이 3일 이하 간격으로 설정되어 있다 (
*/3 * * *권장, 5일은 위험!)
이번 포스팅이 저처럼 Keep Alive 워크플로우를 설정해두고 갑자기 실패 메일을 받아 당황하신 분들께 도움이 됐으면 좋겠습니다. 비개발자 입장에서 “exit code 6이 뭐야…” 싶었던 순간부터, 차근차근 원인을 찾아 해결하는 과정을 담아봤어요.
이런 작은 트러블슈팅들이 쌓여서 나중엔 무서울 것 없는 풀스택 개발자가 되는 거 아닐까요? 😊
다음 포스팅에서 또 만나요!