로컬에선 되는데 배포하면 404, React SPA 새로고침 404, API 404, Nginx·Apache 설정 문제까지. 원인별로 해결 방법을 정리한다. Next.js getStaticPaths fallback 설정, Vercel·Netlify 리다이렉트 설정 포함.
한 줄 요약: HTTP 404는 "요청한 주소에 해당하는 파일이나 페이지가 서버에 없다"는 뜻이다. 브라우저가 보내는 에러가 아니라 서버가 돌려주는 응답이라는 게 핵심이다. 원인은 크게 4가지다: ① 주소를 잘못 입력했거나, ② 실제로 파일이 없거나, ③ 서버 라우팅 설정 문제이거나, ④ 배포 과정에서 파일이 안 올라갔거나.
이런 상황에서 이 글이 필요하다
로컬에서는 되는데 배포하면 404가 뜨는 경우
React·Next.js SPA에서 새로고침하면 404가 나오는 경우
Nginx·Apache 설정 후 특정 경로에서만 404가 나오는 경우
API 요청에서 404가 오는 경우
링크를 클릭하면 404인데 직접 주소를 입력하면 되는 경우
404가 정확히 뭔가
HTTP 상태 코드는 서버가 브라우저에게 "요청 결과가 어떻다"고 알려주는 숫자다. 404는 "Not Found", 즉 해당 주소에 있어야 할 것이 없다는 뜻이다.
코드
뜻
누구 책임
400
요청 자체가 잘못됨
요청 보낸 쪽(클라이언트)
404
해당 주소에 파일/페이지 없음
주로 서버 설정 또는 주소 오류
500
서버 내부 오류
서버 쪽
403
접근 권한 없음
권한 설정 문제
404는 "서버가 살아있고, 요청도 받았는데, 그 주소에 맞는 게 없다"는 뜻이다. 서버 자체가 죽으면 502나 503이 뜬다.
케이스 1 — 주소 자체가 틀린 경우
원인: URL에 오타가 있거나, 대소문자가 다르거나, 슬래시(/) 유무가 다르거나, 주소가 바뀌었는데 예전 주소로 접근하는 경우다.
확인 방법:
URL을 다시 한 번 읽어본다. 특히 /users인데 /user로 입력한 것처럼 단복수나 오타가 많다.
Linux 서버는 대소문자를 구분한다. /About과 /about은 다른 경로다.
뒤에 /가 있고 없고에 따라 달라지는 경우도 있다. (/product와 /product/)
해결: 올바른 주소를 확인하고 직접 수정한다. 예전 주소에서 새 주소로 영구 이동이라면 서버에서 301 리다이렉트를 걸어줘야 한다.
서버가 요청한 경로에 맞는 파일을 찾지 못했을 때 404 응답이 반환된다
케이스 2 — React·Next.js SPA에서 새로고침하면 404
원인: React처럼 클라이언트 사이드 라우팅을 쓰는 앱은 /about이나 /products/1 같은 주소가 실제 서버 파일로 존재하지 않는다. 브라우저에서 링크를 클릭해서 이동할 때는 JavaScript가 처리하니까 괜찮은데, 직접 주소를 입력하거나 새로고침하면 서버가 그 경로에 맞는 파일을 찾다가 없어서 404를 뱉는 것이다.
해결 — Nginx 설정: 모든 요청을 index.html로 돌리도록 설정한다.
Nginx — SPA 404 해결 설정 (nginx.conf 또는 sites-available)
server {
listen 80;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
# 파일 있으면 그 파일, 없으면 index.html로 넘긴다
}
}
Next.js는 SPA 404 문제가 없다: Next.js는 파일 시스템 기반 라우팅이라 pages/about.js를 만들면 /about 주소가 자동으로 생긴다. 새로고침해도 서버가 처리할 수 있다. Next.js에서 404가 뜬다면 파일이 실제로 없거나, getStaticPaths 설정 문제일 가능성이 높다.
케이스 3 — API 요청에서 404가 오는 경우
원인: 백엔드 API 서버에 해당 경로에 맞는 라우트(엔드포인트)가 등록되지 않았거나, 요청 경로가 틀렸거나, API 버전이 바뀐 경우다.
확인 방법:
실제 API 문서(Swagger, Postman)와 요청 URL을 대조한다.
베이스 URL이 올바른지 확인한다. (https://api.example.com/v1이 맞는데 /v2로 보내는 경우)
HTTP 메서드가 맞는지 확인한다. GET으로 해야 하는데 POST로 보내면 404가 뜨는 서버가 있다.
Express.js — 라우트가 없는 경우 예시
// 이렇게 등록되어 있으면
app.get('/api/users', handler)
// 아래 요청은 404가 된다
// GET /api/user (단수 오타)
// POST /api/users (메서드 다름)
// GET /api/v2/users (버전 다름)
케이스 4 — 로컬에선 되는데 배포하면 404
가장 많이 접하는 상황이다. 원인을 순서대로 확인한다.
확인 1 — 빌드 파일이 실제로 서버에 올라갔는지: 배포 자동화가 실패했거나, 빌드 결과물이 잘못된 폴더에 올라간 경우다. 서버에 직접 접속해서 파일이 있는지 확인한다. ls /var/www/html 또는 CI/CD 로그에서 배포 성공 여부를 확인.
확인 2 — 대소문자 차이: 로컬(Mac·Windows)은 파일명 대소문자를 구분 안 하지만, Linux 서버는 구분한다. 로컬에서 Image.jpg로 저장했는데 코드에서 image.jpg로 불러오면 로컬에선 되고 서버에선 404가 뜬다.
확인 3 — Next.js getStaticPaths fallback 설정: Next.js 정적 생성 페이지에서 fallback: false로 설정하면 getStaticPaths에서 정의하지 않은 경로는 전부 404가 된다. 동적으로 생성되는 경로가 있다면 fallback: 'blocking' 또는 true로 바꿔야 한다.
확인 4 — 환경변수 차이: 로컬 .env에는 API 베이스 URL이 있는데 배포 환경에 환경변수가 없어서 요청 주소가 undefined/api/...처럼 이상하게 만들어지는 경우다. 배포 환경(Vercel, AWS 등)의 환경변수 설정을 확인한다.
Next.js에서 404 페이지 직접 만들기
Next.js에서 존재하지 않는 경로로 접근했을 때 기본 404 페이지 대신 직접 만든 페이지를 보여주고 싶다면 pages/404.js 파일을 만들면 된다.
pages/404.js — 커스텀 404 페이지
// pages/404.js
export default function Custom404() {
return (
<div style={{ textAlign: 'center', padding: '80px 20px' }}>
<h1>404 — 페이지를 찾을 수 없습니다</h1>
<p>주소를 다시 확인해주세요.</p>
<a href="/">홈으로 돌아가기</a>
</div>
)
}
// 빌드 시 정적 생성
export function getStaticProps() {
return { props: {} }
}