👉 1. Composer: 현대 PHP의 심장
Composer와 Packagist 생태계
과거의 PHP는 외부 라이브러리를 사용하기 위해 파일을 직접 다운로드하고 복사해야 했습니다. 하지만 Composer의 등장으로 현대 PHP는 완전히 달라졌습니다.
마치 Node.js의 npm이나 Python의 pip처럼, 필요한 라이브러리를 선언만 하면 자동으로 다운로드하고 의존성을 관리해줍니다. Packagist라는 방대한 패키지 저장소를 통해 수많은 오픈소스 도구를 손쉽게 내 프로젝트에 통합할 수 있습니다.
👉 2. PSR-4 Autoloading
파일을 자동으로 불러오는 마법
기존에는 클래스 파일을 사용하기 위해 수많은 require_once를 작성해야 했습니다. PSR-4는 네임스페이스와 폴더 구조를 매핑하여, 클래스를 사용할 때 해당 파일을 자동으로 로드하는 표준 프로토콜입니다.
Composer와 함께 사용되며, 코드를 훨씬 깔끔하게 만들고 파일 관리의 부담을 덜어줍니다. 이제 네임스페이스 규칙만 잘 지키면 파일 로드는 Composer가 알아서 처리합니다.
👉 3. PHP Standard Recommendation (PSR)
PHP 생태계의 공통 표준
PHP Framework Interop Group(PHP-FIG)에서 제정한 PSR(PHP Standard Recommendation)은 다양한 프레임워크 간의 상호운용성을 위한 표준입니다.
코딩 스타일(PSR-12), 로깅 인터페이스(PSR-3), HTTP 메시지(PSR-7) 등 공통의 규격을 따름으로써, Laravel, Symfony 등 어떤 환경에서도 호환되는 코드를 작성할 수 있게 해줍니다.
PSR-4 Autoloading 매핑 원리
👉 4. Strict Typing (엄격한 타입)
런타임 안정성의 핵심
PHP는 기본적으로 느슨한 타입 언어(동적 타입)이지만, declare(strict_types=1);를 선언하면 엄격한 타입 체크를 강제할 수 있습니다.
이는 의도치 않은 타입 변환(예: 문자열 "1"이 정수 1로 변환되는 현상)을 막아주며, 예상치 못한 버그를 예방하고 코드의 예측 가능성을 크게 높여줍니다.
👉 5. Scalar & Complex Types
고도화된 타입 시스템
현대 PHP는 매우 강력한 타입 시스템을 갖추고 있습니다. Union Types(여러 타입 중 하나), Intersection Types(여러 인터페이스를 모두 만족) 등을 지원합니다.
여기에 어떤 값이든 될 수 있는 mixed나, 절대 반환하지 않는(예: 에러를 던지거나 종료) 함수를 위한 never 타입까지 추가되어, 더욱 견고한 코드를 작성할 수 있습니다.
Weak Typing vs Strict Typing
<?php
declare(strict_types=1);
function addNumbers(int $a, int $b): int {
return $a + $b;
}
// addNumbers("1", "2"); // 타입 에러 발생!👉 6. Constructor Property Promotion
보일러플레이트 코드 제거
생성자 속성 프로모션은 클래스를 정의할 때 발생하는 반복적인 코드를 획기적으로 줄여주는 기능입니다.
생성자 매개변수에 가시성(public, private, protected)을 지정하기만 하면, 속성 선언과 할당이 한 번에 자동으로 처리됩니다. 이로 인해 클래스가 훨씬 짧고 읽기 쉬워집니다.
👉 9. Readonly Properties & Classes
데이터 불변성 보장
Readonly는 한 번 초기화되면 값을 변경할 수 없도록 강제하는 기능입니다. DTO(Data Transfer Object)나 Value Object를 만들 때 매우 유용합니다.
PHP 8.2부터는 클래스 전체를 readonly로 선언할 수 있어, 클래스 내의 모든 속성이 자동으로 불변(immutable) 상태가 되며 예상치 못한 부작용(Side Effect)을 차단합니다.
👉 10. Native Enums
강력한 상태 값 관리
오랫동안 PHP에 없었던 열거형(Enum)이 네이티브로 지원됩니다. 단순한 상수(const) 배열을 넘어, 메서드를 가질 수 있고 인터페이스를 구현할 수 있는 일급 객체입니다.
상태 값, 카테고리 등 고정된 데이터 세트를 타입 안전하게 관리할 수 있어 도메인 로직의 안정성이 크게 향상됩니다.
// 이전 방식
class User {
private string $name;
public function __construct(string $name) {
$this->name = $name;
}
}
// PHP 8.0 프로모션 적용
class User {
public function __construct(
private string $name
) {}
}👉 7. Match Expression
더 안전하고 강력한 조건문
match 표현식은 기존의 switch 문을 개선한 기능입니다. 값을 반환할 수 있고(표현식), 일치 여부를 확인할 때 엄격한 비교(===)를 사용합니다.
또한 break를 생략해도 다음 케이스로 넘어가지 않으며(No type coercion, No fallthrough), 코드가 훨씬 간결하고 가독성이 뛰어납니다.
👉 8. Nullsafe Operator
안전한 체이닝 (Optional Chaining)
Nullsafe 연산자(?->)는 객체의 메서드나 속성에 연쇄적으로 접근할 때 유용합니다. 중간에 어느 하나라도 null이면 에러를 발생시키지 않고 전체 평가를 멈춘 뒤 null을 반환합니다.
이 기능 덕분에 불필요한 null 체크 조건문(if 문)을 대폭 줄일 수 있습니다.
👉 11. Attributes
코드 내장 메타데이터
Attributes(어트리뷰트)는 기존에 주석(DocBlock)으로 처리하던 메타데이터를 언어 차원의 공식 문법으로 대체한 것입니다.
주석을 파싱하는 대신 Reflection API를 통해 구조적이고 타입 안전하게 클래스, 메서드, 속성에 추가 정보를 부여할 수 있어 프레임워크 설계 시 핵심적으로 사용됩니다.
Match 표현식 (PHP 8.0+)
// switch 문 대체
$status = 200;
$message = match($status) {
200, 201 => 'Success',
400 => 'Bad Request',
404 => 'Not Found',
500 => 'Server Error',
default => 'Unknown Status',
};유연하고 테스트 가능한 설계
현대 PHP 개발의 핵심 패턴 중 하나는 의존성 주입(DI)입니다. 객체가 필요로 하는 의존성을 내부에서 직접 생성하지 않고 외부에서 주입받는 방식입니다.
이를 통해 모듈 간의 결합도를 낮추고 단위 테스트(Mocking)를 쉽게 만들 수 있습니다. 최신 프레임워크들은 강력한 DI Container를 내장하여 객체의 생성과 주입을 자동화합니다.
의존성 주입 (Dependency Injection)
// 의존성 주입 (DI)
class UserService {
public function __construct(
private UserRepository $repository
) {}
}
// DI 컨테이너가 의존성을 자동으로 해결
$userService = $container->get(UserService::class);👉 13. Static Analysis
실행 전 버그 찾기
PHP는 인터프리터 언어이지만, PHPStan이나 Psalm 같은 정적 분석(Static Analysis) 도구를 통해 컴파일 언어 수준의 타입 안정성을 확보할 수 있습니다.
코드를 실행하지 않고도 타입 불일치, 정의되지 않은 메서드 호출, 논리적 오류 등을 사전에 탐지하여 프로젝트의 품질을 비약적으로 높여줍니다.
👉 14. Pest Testing Framework
아름답고 직관적인 테스팅
기존의 PHPUnit이 클래스 기반의 다소 무거운 구조였다면, Pest는 현대적이고 서술적인(fluent) 함수형 인터페이스를 제공하는 테스팅 프레임워크입니다.
마치 JavaScript의 Jest처럼 직관적으로 코드를 작성할 수 있어, 개발자들이 테스트 작성에 느끼는 진입 장벽을 크게 낮춰줍니다.
정적 분석 (Static Analysis - PHPStan)
👉 15. Laravel Ecosystem
압도적인 생산성의 프레임워크
Laravel은 현대 PHP의 부흥을 이끈 가장 인기 있는 프레임워크입니다. 아름다운 문법과 강력한 ORM(Eloquent), 직관적인 템플릿 엔진(Blade)을 제공합니다.
또한 인증, 큐(Queue), 캐시, 브로드캐스팅 등 웹 개발에 필요한 모든 도구가 생태계 내에 완벽하게 통합되어 있어, 개발 생산성을 극대화합니다.
👉 16. Inertia.js & Livewire
모던 SPA의 새로운 접근법
전통적으로 SPA(Single Page Application)를 만들려면 백엔드 API를 구축하고 프론트엔드와 별도로 통신해야 했습니다.
Inertia.js는 API 구축 없이 React/Vue를 뷰 레이어로 사용하게 해주며, Livewire는 JavaScript 작성 거의 없이 PHP 코드만으로 리액티브한 동적 인터페이스를 만들 수 있게 해주는 혁신적인 도구입니다.
Laravel MVC 처리 흐름
// Eloquent ORM 예시
$users = User::where('active', 1)
->orderBy('created_at', 'desc')
->get();
return view('users.index', ['users' => $users]);👉 17. Swoole / RoadRunner / FrankenPHP
PHP-FPM을 넘어서는 비동기 아키텍처
기존 PHP는 매 요청마다 스크립트를 새로 로드하는 'Share-Nothing' 아키텍처(PHP-FPM)를 사용했습니다.
하지만 Swoole, RoadRunner, FrankenPHP 같은 서버를 사용하면, Node.js나 Go처럼 애플리케이션을 메모리에 상주(Persistent)시키고 비동기 처리를 지원하여, 웹소켓 등 실시간 통신과 압도적인 처리 속도를 구현할 수 있습니다.
👉 18. JIT (Just-In-Time) Compilation
극한의 성능 최적화
PHP 8부터 도입된 JIT(Just-In-Time) 컴파일러는, 코드를 실행할 때 머신 코드로 컴파일하여 캐싱하는 기술입니다.
웹 애플리케이션보다는 CPU 집약적인 복잡한 연산, 이미지 처리, 머신러닝 등 특정 작업에서 C 언어에 버금가는 획기적인 성능 향상을 가져다줍니다.
👉 19. Dockerized Environment
일관된 개발 및 배포 환경
현대의 PHP 프로젝트는 내 PC에 직접 PHP를 설치하지 않고, Docker를 활용한 컨테이너 환경에서 개발합니다.
Laravel Sail 같은 도구를 사용하면, 운영체제에 상관없이 팀원 모두가 완벽하게 동일한 버전의 PHP, DB, Redis 환경을 클릭 한 번(또는 명령어 한 줄)으로 구성할 수 있습니다.
PHP-FPM vs Swoole/FrankenPHP
// FrankenPHP (Caddy 기반 PHP 앱 서버)
// 메모리에 상주하며 요청을 처리 (비동기, 고성능)
// 터미널 실행 예시
// ./frankenphp php-server👉 PHP의 역사와 탄생
PHP (Hypertext Preprocessor)는 1995년 라스무스 러도프(Rasmus Lerdorf)가 자신의 웹 이력서 방문자를 추적하기 위해 만든 C 언어 기반의 간단한 스크립트 모음(Personal Home Page Tools)에서 출발했습니다.
초기의 단순한 형태를 넘어, 전 세계 웹 서버의 70% 이상을 구동하는 가장 대표적인 오픈 소스 백엔드 언어로 성장했습니다.
💡 PHP의 철학
"PHP는 무엇보다도 실용적(Practical)이어야 한다. 개발자가 웹 애플리케이션을 최대한 빠르고 쉽게 만들 수 있도록 돕는 가장 큰 목표다."👉 PHP 개발 환경 구축 (XAMPP/MAMP 설치)
PHP 첫걸음: 서버 환경 만들기 🛠️
PHP는 서버 측(Server-side) 스크립트 언어이므로, 내 컴퓨터를 서버처럼 동작하게 만들어주는 도구가 필요합니다.
- XAMPP (Windows): Apache(웹 서버), MariaDB(데이터베이스), PHP를 한 번에 설치해 주는 통합 패키지입니다.
- MAMP (Mac): Mac 환경에서 가장 널리 쓰이는 로컬 서버 환경 구축 도구입니다.
설치 후 htdocs 폴더에 .php 파일을 만들고 브라우저에서 localhost/파일명.php로 접속하면 실행됩니다.
👉 PHP 구문 기초와 Hello World 출력
PHP의 심장부: <?php ... ?> 🏁
PHP 코드는 항상 <?php로 시작해서 ?>로 끝납니다. 이 태그 밖의 내용은 일반 HTML로 취급됩니다.
화면에 무언가를 출력할 때는 주로 echo 또는 print를 사용합니다.
PHP 웹 서버 동작 원리
<!-- htdocs/index.php 파일에 아래 코드를 작성합니다 -->
<h1>로컬 서버 구동 성공!</h1>
<?php
// 서버 정보 출력하기
phpinfo();
?>👉 변수 선언과 데이터 타입
데이터를 담는 그릇: 변수(Variable) 📦
PHP에서 변수는 달러 기호($)로 시작합니다. 자바스크립트나 C와 달리 자료형을 미리 선언할 필요가 없습니다. (동적 타입 언어)
- String: 문자열 (따옴표 사용)
- Integer: 정수 (소수점 없는 숫자)
- Float/Double: 실수 (소수점 있는 숫자)
- Boolean: 참(true) 또는 거짓(false)
👉 상수(Constant) 정의와 사용법
절대 변하지 않는 값: 상수 💎
상수는 한 번 값을 정하면 스크립트 실행 중에 절대로 변경할 수 없는 식별자입니다. 주로 사이트 이름이나 DB 접속 정보 등을 저장합니다.
define() 함수 또는 const 키워드를 사용합니다.
PHP 데이터 타입 체계도
<?php
$name = "Minstudio"; // 문자열 (String)
$age = 25; // 정수 (Integer)
$height = 175.5; // 실수 (Float)
$isDeveloper = true; // 불리언 (Boolean)
echo "이름: " . $name . "<br>"; // 점(.)으로 문자열 연결
echo "나이: $age 세"; // 큰따옴표 안에서는 변수 직접 파싱 가능
?>👉 산술, 대입, 증감 연산자
수학 시간으로 돌아가기: 연산자 ➕
데이터를 계산하고 가공할 때 사용하는 필수 기호들입니다.
- 산술 연산자: +, -, *, /, % (나머지)
- 대입 연산자: =, +=, -=, *= (값을 할당)
- 증감 연산자: ++, -- (값을 1씩 올리거나 내림)
👉 비교 연산자와 논리 연산자
참과 거짓 판별하기 ⚖️
두 값을 비교하거나, 여러 조건을 결합할 때 사용합니다. 조건문(if)에서 핵심적인 역할을 합니다.
- 비교: == (같다), === (타입까지 같다), != (다르다), >, <, >=, <=
- 논리: && 또는 and (둘 다 참), || 또는 or (둘 중 하나라도 참), ! (반대)
논리 연산자 단축 평가 (Short-circuit)
<?php
$a = 10;
$b = 3;
echo "더하기: " . ($a + $b) . "<br>";
echo "나머지: " . ($a % $b) . "<br>";
$a += 5; // $a = $a + 5 와 동일 (15가 됨)
echo "대입 후: $a <br>";
$a++; // 1 증가
echo "증가 후: $a";
?>👉 if, else, elseif 조건문
프로그램의 갈림길: 조건문 🛣️
특정 조건이 true일 때만 코드를 실행하고 싶다면 if를 사용합니다.
조건이 여러 개일 경우 elseif로 연결하며, 모든 조건이 맞지 않을 때는 else를 사용합니다.
<?php
$score = 85;
if ($score >= 90) {
echo "A 등급입니다. 🌟";
} elseif ($score >= 80) {
echo "B 등급입니다. 👍";
} elseif ($score >= 70) {
echo "C 등급입니다. 😐";
} else {
echo "노력이 필요합니다. 📚";
}
?>
👉 switch case 분기문
명확한 값 매칭: switch 🎛️
변수의 값이 정확히 특정 값(문자열, 숫자 등)과 일치할 때 실행할 코드를 정의합니다. if-elseif가 길어질 때 사용하면 가독성이 좋습니다.
<?php
$grade = 'B';
switch ($grade) {
case 'A':
echo "최우수 성적입니다.";
break;
case 'B':
echo "우수한 성적입니다.";
break;
case 'C':
echo "보통 성적입니다.";
break;
default:
echo "재수강이 필요합니다.";
}
?>
if-elseif vs switch 흐름 비교
👉 while 및 do-while 반복문
무한 루프 조심! while 🔄
조건이 참(true)인 동안 코드를 계속 반복 실행합니다. do-while은 조건을 나중에 검사하므로 최소 1번은 무조건 실행되는 차이가 있습니다.
👉 for 반복문 기초
횟수가 정해진 반복: for 🎯
for (초기식; 조건식; 증감식) 구조로 작성하며, 반복 횟수가 명확할 때 가장 많이 쓰이는 반복문입니다.
👉 foreach와 배열 데이터 처리
배열의 단짝 친구: foreach 👯♀️
배열의 처음부터 끝까지 자동으로 순회하면서 값을 하나씩 꺼내줍니다. PHP에서 가장 사랑받는 배열 전용 반복문입니다.
for vs foreach 순회 구조
<?php
// 1부터 5까지 출력
for ($i = 1; $i <= 5; $i++) {
echo "반복 횟수: " . $i . "<br>";
}
echo "<br>";
// 10부터 2씩 감소
for ($k = 10; $k > 0; $k -= 2) {
echo "카운트다운: $k<br>";
}
?>👉 인덱스 배열과 연관 배열
숫자 방번호 vs 이름 방번호 🗄️
PHP의 배열은 크게 두 가지로 나뉩니다.
- 인덱스 배열(Indexed Array): 0, 1, 2... 순서대로 숫자가 매겨지는 일반적인 배열입니다.
- 연관 배열(Associative Array): 숫자 대신 '문자열(Key)'을 방 이름으로 사용하는 배열입니다. (JSON 객체와 유사함)
👉 다차원 배열의 이해와 활용
배열 안의 배열: 다차원 배열 🏢
하나의 배열 안에 또 다른 배열을 넣어서 복잡한 표(테이블) 구조의 데이터를 표현할 수 있습니다. 2차원 배열이 가장 흔히 쓰입니다.
배열의 종류: 인덱스 배열 vs 연관 배열
<?php
// 1. 인덱스 배열
$colors = array("Red", "Green", "Blue");
echo "첫 번째 색상: " . $colors[0] . "<br>";
// 2. 연관 배열 (=> 화살표 사용)
$user = [
"name" => "Kim",
"age" => 30,
"job" => "Developer"
];
echo "사용자 이름: " . $user["name"]; // Key로 접근
?>👉 함수 정의와 매개변수, 반환값
코드 재사용의 꽃: 함수(Function) 🛠️
자주 사용하는 코드를 블록으로 묶어 이름을 붙여둔 것입니다. 원할 때마다 이름을 불러(호출) 실행할 수 있습니다.
재료를 넣어주면(매개변수 Parameter), 결과물을 내뱉습니다(반환값 Return).
👉 변수의 범위 (Local, Global, Static)
변수의 생명 주기와 활동 영역 🌐
변수는 선언된 위치에 따라 접근할 수 있는 범위(Scope)가 다릅니다.
- Local(지역): 함수 안에서 선언. 밖에서는 못 씀!
- Global(전역): 함수 밖에서 선언. 함수 안에서 쓰려면
global키워드 필요! - Static(정적): 함수가 끝나도 값이 초기화되지 않고 유지됨.
👉 주요 내장 함수 (문자열, 숫자, 배열 관련)
바퀴를 다시 발명하지 마라: 내장 함수 ⚙️
PHP는 엄청나게 많은 기본 내장 함수를 제공합니다. 이를 잘 활용하면 수십 줄의 코드를 한 줄로 줄일 수 있습니다.
변수 스코프 (Local vs Global)
<?php
// 함수 정의
function calculateSum($a, $b) {
$result = $a + $b;
return $result; // 결과 반환
}
// 함수 호출
$total = calculateSum(10, 20);
echo "10 + 20 = $total <br>";
// 기본값이 있는 매개변수
function greet($name = "손님") {
echo "안녕하세요, $name 님!";
}
greet(); // 손님 출력
?>👉 HTML Form 태그와 PHP 연동 기초
사용자와 소통하기 🗣️
웹 개발의 핵심은 사용자가 HTML <form>에 입력한 데이터를 서버(PHP)가 받아서 처리하는 것입니다.
👉 $_GET과 $_POST 전역 변수 활용
데이터 전달의 양대 산맥 ⛰️
- $_GET: URL 주소 끝에 파라미터(
?id=1&name=kim)로 데이터를 달아서 보냅니다. (검색, 공유용) - $_POST: HTTP 본문 안에 데이터를 숨겨서 보냅니다. 길이 제한이 없고 보안에 유리합니다. (로그인, 회원가입용)
GET vs POST 전송 방식 차이
<!-- 폼 HTML (index.html 역할) -->
<form action="process.php" method="POST">
이름: <input type="text" name="username">
<button type="submit">전송</button>
</form>
<?php
/* process.php 파일 내부 */
// 사용자가 전송 버튼을 눌렀을 때만 처리
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// 전송된 데이터 받기
$name = $_POST["username"];
echo "환영합니다, $name 님!";
}
?>👉 세션(Session) 시작과 정보 관리
나를 기억해줘: 세션 🧠
웹 서버는 사용자가 누군지 기억하지 못합니다(Stateless). 세션은 서버 메모리에 사용자의 정보를 저장하여 로그인 상태 등을 유지하는 기술입니다.
모든 세션 사용 전에는 반드시 session_start()가 호출되어야 합니다.
👉 쿠키(Cookie) 설정 및 삭제
내 컴퓨터에 남는 흔적: 쿠키 🍪
세션이 '서버'에 저장된다면, 쿠키는 사용자의 웹 브라우저(로컬)에 저장되는 작은 텍스트 조각입니다. (예: "7일간 보지 않기", 장바구니)
Session vs Cookie 동작 원리
<?php
// 1. 세션 엔진 가동! (파일 맨 꼭대기에 위치해야 함)
session_start();
// 2. 세션 변수 굽기 (로그인 처리)
$_SESSION["userid"] = "admin123";
$_SESSION["role"] = "manager";
// 3. 세션 읽기
echo "현재 로그인된 아이디: " . $_SESSION["userid"] . "<br>";
// 4. 세션 삭제 (로그아웃 처리)
session_unset(); // 변수 비우기
session_destroy(); // 세션 완전 파괴
?>DB 없이 데이터 보관하기: 파일 I/O 📁
텍스트 파일을 읽어오거나 텍스트를 파일에 저장할 수 있습니다. 로그(Log)를 남길 때 주로 사용됩니다.
파일 입출력 생명주기
<?php
$filename = "log.txt";
// 1. 파일 쓰기 (w: 덮어쓰기, a: 이어쓰기)
$file = fopen($filename, "a") or die("파일을 열 수 없습니다.");
$txt = "새로운 로그 기록 - " . date("H:i:s") . "\n";
fwrite($file, $txt);
fclose($file);
// 2. 파일 존재 여부 확인 후 읽기
if (file_exists($filename)) {
// file_get_contents: 파일 내용을 한 번에 문자열로 가져옴
echo nl2br(file_get_contents($filename));
}
?>조립식 웹사이트 만들기 🧩
헤더, 푸터, DB 접속 코드처럼 모든 페이지에 공통으로 들어가는 코드를 별도의 파일로 빼서 불러옵니다.
include: 파일을 못 찾아도 경고만 띄우고 계속 실행합니다.require: 파일을 못 찾으면 치명적 오류를 내고 즉시 중단합니다. (DB 접속 등에 사용)
include vs require 에러 처리 차이
<!-- header.php 파일 -->
<header><h1>내 사이트</h1></header>
<?php
// index.php 메인 파일에서 불러오기
include 'header.php'; // 헤더 UI 불러오기
// DB 연결은 없으면 큰일나므로 require_once 사용 (한 번만 로드)
require_once 'db_connect.php';
echo "<main>메인 콘텐츠</main>";
?>👉 date 함수를 이용한 날짜와 시간 처리
시간을 지배하는 자 ⏰
게시글 작성 시간, 로그 기록 등을 남길 때 date() 함수를 사용하여 타임스탬프를 읽기 쉬운 문자열로 변환합니다.
👉 header 함수를 이용한 페이지 이동(Redirection)
다른 페이지로 강제 전송! 🚀
로그인을 성공했거나, 권한이 없는 페이지에 접근했을 때 브라우저의 URL을 강제로 변경하여 이동시킵니다.
⚠️ 주의: header() 함수 이전에 HTML이나 공백이 단 1글자라도 출력되면(echo) 에러가 발생합니다.
👉 기초적인 에러 메시지 확인 및 디버깅 방법
버그와의 전쟁 🐛
PHP는 기본적으로 실서버 환경에서 보안을 위해 에러 메시지를 숨깁니다. 하지만 개발 중에는 에러를 화면에 띄워야 문제를 고칠 수 있습니다.
HTTP Redirection 원리
<?php
$isLoggedIn = false;
if (!$isLoggedIn) {
// 권한이 없으므로 로그인 페이지로 강제 튕겨내기
header("Location: login.php?error=need_login");
// 리다이렉션 후 아래 코드가 실행되지 않도록 프로그램 강제 종료!
exit;
}
echo "비밀 관리자 페이지입니다.";
?>