배포는 성공했는데 화면은 왜 그대로일까: Laravel 배포 검증의 네 단계
작성: 라라벨 코리아
발행: 2026년 10월 10일
HTTP 200, 실제 본문, 빌드 자산, 장기 실행 프로세스를 나누어 확인합니다. Laravel·Inertia 콘텐츠 사이트에서 빈 HTML과 오래된 워커를 구분하고, 헬스 체크가 보장하는 범위도 테스트합니다.
성공한 명령과 이용자가 보는 결과 사이
배포 로그의 마지막 줄이 “완료”여도 새 화면이 보인다고 단정할 수는 없습니다. 파일은 바뀌었지만 워커는 이전 코드를 실행할 수 있고, 브라우저에서는 화면이 보여도 최초 HTML에는 본문이 없을 수 있습니다. 같은 “그대로예요”라는 신고라도 확인할 계층이 다릅니다.
이 글은 Laravel 13 + Inertia 콘텐츠 사이트를 운영할 때 사용하는 점검 순서입니다. 라라벨 코리아 저장소의 /up, Vite 빌드, deploy:check를 사례로 삼습니다. 명령을 그대로 한꺼번에 실행하는 배포 스크립트가 아니라 원인을 구분하는 절차입니다.
1단계: 요청이 앱까지 도착하는가
도메인 대신 example.com을 그대로 호출하지 말고 자신이 관리하는 스테이징 주소를 지정합니다. 아래 예시의 SITE_URL 값부터 바꾸세요.
SITE_URL='https://your-staging-domain.example'curl --fail --silent --show-error --output /dev/null \ --write-out 'health=%{http_code}\n' "$SITE_URL/up"/up은 이 앱의 bootstrap/app.php에서 지정한 경로입니다. 다른 앱은 다른 경로일 수 있습니다. 정상 설정이라면 200을 기대합니다. DNS·TLS 단계에서 실패하면 앱 코드를 고치기 전에 연결을 해결해야 합니다. 인증 화면으로 이동하거나 404가 나오면 호스트·웹 루트·라우팅부터 확인하세요. 헤더에 표시된 상태와 curl 종료 코드를 함께 기록합니다.
기본 /up의 200은 DB·Redis·SMTP·검색·큐가 모두 정상이라는 뜻이 아닙니다. 필요한 종속성 검사는 DiagnosingHealth 이벤트에 명시적으로 추가해야 합니다. 연결 실패를 일부러 일으킨 테스트도 있어야 실제 장애 때 500이 되는지 확인할 수 있습니다. 추가 검사에 느린 외부 API를 무제한 호출하면 헬스 체크 자체가 부하 원인이 됩니다.
2단계: 200 응답 안에 필요한 본문이 있는가
curl --fail --silent --show-error "$SITE_URL/" --output /tmp/site-home.html다운로드한 HTML을 텍스트 편집기에서 열어 다음을 확인합니다.
<title>과 canonical이 현재 페이지에 맞는가.- 화면에 보이는 주요 제목과 본문이 HTML 요소로 들어 있는가.
- 로그인 화면이나 오류 메시지를 200으로 반환하고 있지는 않은가.
- JS 파일 경로가 존재하며 404가 나지 않는가.
문자열 검색만으로 SSR 성공을 판정하지 마세요. Inertia 초기 데이터의 JSON 속성 안에도 제목과 본문이 들어갈 수 있습니다. “본문 문자열을 찾았다”와 “서버가 본문 요소를 렌더링했다”는 다릅니다. 브라우저에서 JavaScript를 끈 상태나 파싱한 본문 요소를 함께 확인하면 구분하기 쉽습니다.
클라이언트 렌더링만 하는 앱이 항상 잘못된 것은 아닙니다. 다만 읽기 중심의 공개 콘텐츠를 최초 응답에 제공하려는 사이트에서는, 서버 렌더링 실패를 운영 점검 항목으로 두는 것이 유용합니다. SSR이 켜졌다고 검색 노출이나 광고 심사 승인이 보장되는 것은 아닙니다.
3단계: 현재 릴리스의 빌드와 설정을 읽고 있는가
라라벨 코리아 저장소에서는 다음 명령으로 클라이언트와 SSR 번들을 만듭니다. npm run build가 무엇을 하는지는 프로젝트의 package.json을 먼저 확인해야 합니다.
npm cinpm run buildphp artisan deploy:check이 프로젝트의 deploy:check는 Vite manifest, SSR 번들·서버 응답, sitemap, 필수 공개 파일, 앱 키, DB 연결을 검사합니다. 읽기 전용 명령은 아닙니다. 개발 서버 표시 파일 public/hot이 있으면 삭제하므로, 개발 서버가 실행 중인 작업 폴더에서 습관적으로 호출하지 마세요. 배포 대상 릴리스 디렉터리에서 사용합니다.
다음 표로 실패한 계층을 좁힙니다.
| 보이는 현상 | 확인 대상 | 해결 후 다시 볼 증거 |
|---|---|---|
| manifest 관련 오류 | 현재 릴리스의 public/build/manifest.json | 빌드 성공과 자산 URL의 200 |
| 개발 서버 주소로 JS 요청 | 배포 폴더의 public/hot | 브라우저 네트워크의 실제 자산 경로 |
.env를 바꿔도 설정 그대로 | 설정 캐시와 프로세스가 읽는 릴리스 | 새 설정으로 동작하는 실제 요청 |
| SSR 번들은 있는데 최초 본문 없음 | SSR 프로세스 로그·접속 주소·노드 버전 | 본문 요소를 포함한 최초 HTML |
| 일부 이용자만 이전 화면 | CDN·브라우저 캐시·배포 노드 간 차이 | 응답 자산 해시·응답 헤더 비교 |
운영 설정 캐시는 최종 환경 변수를 준비한 뒤 생성합니다. 런타임 코드에서 env()를 직접 읽는 대신 설정 파일에 환경 변수를 모으고 config()로 읽어야 캐시 전후의 차이를 줄일 수 있습니다. 모든 캐시를 지우는 명령부터 실행하면 원인을 놓치거나 이용자 세션·캐시 데이터에 영향을 줄 수 있으니 대상 캐시를 먼저 구분하세요.
4단계: 오래 살아 있는 프로세스가 새 코드를 읽는가
웹 요청이 정상이어도 큐 워커·SSR·Octane 같은 장기 실행 프로세스는 별도입니다. 일반적인 queue:work 워커는 코드 변경을 자동으로 다시 읽지 않습니다.
php artisan queue:restart이 명령은 기존 작업을 마친 워커가 종료하도록 알립니다. 새 프로세스를 띄워주는 감독 프로세스까지 대신하는 명령은 아닙니다. Supervisor·systemd·호스팅 관리자 등의 재기동 설정이 필요하고, 워커들이 재시작 신호를 읽는 캐시 저장소도 확인해야 합니다. Horizon을 사용한다면 그 운영 방식에 맞는 종료·재기동 절차를 사용하세요.
웹 요청과 워커의 릴리스 디렉터리가 다르면 다시 시작해도 오래된 코드가 실행될 수 있습니다. 감독 설정의 작업 디렉터리, 실행 명령, 배포한 버전을 비교하세요. 부작용 없는 스테이징 작업 하나를 보내 처리 결과와 로그를 확인하면 단순히 PID가 바뀌었다는 확인보다 유용합니다.
SSR도 빌드 완료와 실행 중인 서버 교체를 구분해야 합니다. 프로세스를 멈춘 뒤 자동으로 살아나는지, 해당 Inertia 버전이 어떤 런타임과 실행 명령을 사용하는지 공식 문서와 실제 배포 설정을 대조하세요.
헬스 체크의 실패 경로를 테스트로 남긴다
다음 Pest 테스트는 이 저장소의 /up 경로를 사용합니다. 새 Laravel 앱에서는 먼저 health 경로를 확인하세요.
<?php
use Illuminate\Foundation\Events\DiagnosingHealth;
use Illuminate\Support\Facades\Event;
test('health endpoint responds when the app boots', function () {
$this->get('/up')->assertOk();
});
test('health endpoint fails when a diagnostic throws', function () {
Event::listen(DiagnosingHealth::class, function (): void {
throw new RuntimeException('Synthetic dependency failure');
});
$this->get('/up')->assertStatus(500);
});여기서 두 번째 테스트는 DB를 실제로 끊지 않습니다. 진단 이벤트가 실패했을 때 상태 코드가 바뀌는 연결 경로만 검증합니다. 실제 DB 검사를 추가했다면 그 검사 코드가 DB 오류를 감지하는 테스트는 따로 필요합니다. 테스트의 통과 범위를 운영 장애 복구 완료로 확대해 해석하지 마세요.
배포 기록에 남길 최소 증거
“정상”이라는 한 단어 대신 배포 버전, 확인 시각, /up 응답, 대표 콘텐츠 URL의 본문, JS 자산 응답, 워커 처리 결과를 남깁니다. 실패했다면 새 릴리스를 계속 노출할지 이전 릴리스로 되돌릴지 판단합니다. DB 변경이 이전 코드와 호환되는지 확인하지 않은 채 마이그레이션을 되돌리지는 마세요.
읽기 요청이 느리다면 N+1 쿼리 측정 가이드, 작업 재시도에서 데이터가 중복된다면 멱등한 집계 가이드로 이어집니다. 세 점검은 각각 조회 비용, 처리 효과, 배포 상태를 다룹니다.
출처와 검증 범위
Laravel Deployment, Queue Workers and Deployment, Inertia SSR를 대조했습니다. 프로젝트 고유 명령의 동작은 저장소 코드를 확인했습니다. AI 작성·원문 대조이며, 독자의 서버에서 실제 배포하거나 복구한 기록은 아닙니다.