본문 바로가기

비개발자의 개발 일지

현장 팀장에서 수출 ERP까지 — AI와 함께 시스템을 만든 기록

시리즈 보기
php

PHP header(Location) — 페이지 리다이렉션 · exit 필수 · 301/302 완전 정리

by 왕진 2026. 7. 11.
반응형

 

 

Web Development · PHP 서버 함수

PHP header("Location:...") — 페이지를 이동시키는 리다이렉션

exit 필수 · 출력 전 호출 · 302 임시 vs 301 영구 리다이렉션 완전 정리
시작 오늘 분석할 코드

header()는 HTTP 응답 헤더를 전송하는 함수입니다. Location: 헤더를 보내면 브라우저가 지정한 URL로 즉시 이동합니다. 중요한 것은 header() 이후 반드시 exit;를 호출해야 한다는 점입니다 — exit 없이는 이동은 되어도 남은 PHP 코드가 계속 실행되어 보안 문제나 예기치 않은 동작이 생길 수 있습니다.

<?php // 네이버로 이동 header("Location:http://www.naver.com/"); exit; // exit 이후 코드는 실행되지 않음 // 브라우저는 즉시 naver.com으로 이동 ?>
실제 출력 미리보기
PHP 실행
header("Location:...")
HTTP 302 응답
브라우저 이동
목적지 페이지

사용자 브라우저에 HTML이 표시되지 않고 즉시 이동 — 기본 302(임시 리다이렉션)

용어 용어 정리
header()HTTP 응답 헤더 전송 함수. 출력 전에만 호출 가능
Location: URL리다이렉션 헤더. 브라우저가 URL로 이동하는 명령
exit; / die;header 이후 필수. 남은 PHP 코드 실행 중단
302 Found임시 리다이렉션 — header("Location:...") 기본 상태코드
301 Moved Permanently영구 리다이렉션 — 검색 엔진이 새 URL을 색인
출력 전 제약header()는 HTML·echo·공백 출력 이전에만 사용 가능
ob_start()출력 버퍼링 — 출력 후에도 header를 사용할 수 있게 해줌
open_basedirLocation에 외부 URL 허용 여부는 서버 설정에 따라 제한 가능

1 exit 없으면 — 보안 취약점이 되는 이유
header() 이후에도 PHP 실행은 계속됨

header("Location:...")를 전송해도 PHP 스크립트는 즉시 멈추지 않습니다. 클라이언트는 이동하지만 서버에서는 남은 코드가 그대로 실행됩니다. 그 코드에 관리자 페이지나 데이터베이스 조작이 있다면 그대로 실행됩니다.

// ❌ exit 없음 — 보안 문제 if (!isset($_SESSION['user'])) { header("Location:/login.php"); // exit 없으면 아래 코드가 실행됨! } // 로그인 안 된 상태에서 이 코드가 실행된다 $users = getAllUsers(); // 취약점! // ✅ exit 있음 — 안전 if (!isset($_SESSION['user'])) { header("Location:/login.php"); exit; }

2 출력 전 제약 — "headers already sent" 오류
echo, HTML, 공백 출력 후에는 header() 사용 불가
// ❌ 출력 후 header() — 오류 발생 echo "안녕하세요"; // 출력 발생! header("Location:/page.php"); // Warning: Cannot modify header information — headers already sent // ✅ 출력 전에 header() 호출 header("Location:/page.php"); exit; // 또는 ob_start()로 출력 버퍼링 사용 ob_start(); echo "이 출력은 버퍼에 저장됨"; header("Location:/page.php"); // 버퍼링 중이면 가능 exit;
⚠️ 파일 맨 앞에 BOM(바이트 순서 표시)이 있어도 "headers already sent"가 발생합니다. UTF-8 BOM 없이 저장된 파일을 사용하세요.

3 301 vs 302 — 리다이렉션 종류
SEO와 캐싱에 영향을 미치는 상태코드 선택
// 302 임시 리다이렉션 (기본값) header("Location:/new-page.php"); exit; // 301 영구 리다이렉션 — SEO에 유리 header("HTTP/1.1 301 Moved Permanently"); header("Location:/new-page.php"); exit; // 303 See Other — POST 후 GET 리다이렉션 (PRG 패턴) header("HTTP/1.1 303 See Other"); header("Location:/result.php"); exit;

 

반응형

 

4 PRG 패턴 — 폼 중복 제출 방지
Post → Redirect → Get 패턴으로 새로고침 중복 제출 방지
// POST 처리 후 GET 페이지로 리다이렉션 (PRG 패턴) if ($_SERVER['REQUEST_METHOD'] === 'POST') { // 폼 데이터 처리 (DB 저장 등) saveToDb($_POST); // 처리 완료 후 결과 페이지로 이동 header("Location:/board.php?saved=1"); exit; // 사용자가 새로고침해도 POST 재전송 없음 }

5 자주 하는 실수
실수 증상 해결
header 이후 exit 생략 이동은 되지만 남은 코드 실행 — 보안 취약점 header("Location:..."); exit; 세트로 사용
echo/HTML 출력 후 header 호출 Warning: headers already sent header를 출력 이전으로 이동, 또는 ob_start() 사용
BOM 있는 UTF-8 파일 파일 맨 앞 보이지 않는 출력 → headers already sent BOM 없이(UTF-8 without BOM) 저장
상대 경로 vs 절대 URL 혼동 일부 서버에서 상대 경로 Location이 작동 안 함 Location: 뒤에 절대 URL 또는 절대 경로 사용 권장
301 캐시 문제 잘못된 301 설정 후 브라우저 캐시 때문에 되돌리기 어려움 테스트 중에는 302, 확정 후 301로 변경

핵심 한 줄 요약

header("Location:URL")브라우저를 URL로 즉시 이동 — 기본 302 리다이렉션
exit 필수header 이후 반드시 exit — 생략 시 남은 코드 실행 = 보안 위험
출력 전 제약echo/HTML 출력 전에만 호출 가능 — 이후면 "headers already sent"
302 vs 301302=임시(기본), 301=영구(SEO), 303=POST→GET(PRG 패턴)
PRG 패턴POST 처리 후 header(Location) → exit — 새로고침 중복 제출 방지

Tags

#PHP #header #Location #리다이렉션 #페이지이동 #exit #301 #302 #PHP서버함수 #PHP함수 #PHP학습 #웹개발 #티스토리
▼ 티스토리 태그 입력란 복사용
PHP, header, Location, 리다이렉션, 페이지이동, exit, 헤더함수, 301, 302, PHP서버함수, PHP함수, PHP학습, 웹개발, 티스토리
반응형

댓글