course-modernization-guide
PHP 강의 현대화 가이드 (PHP 5.x → PHP 8.x, 2026년 기준)
이 문서는 기존 PHP 5.x 기반 강의를 2026년 현업 표준에 맞게 전면 개편하기 위한 상세 가이드입니다.
강사와 콘텐츠 기여자 모두를 대상으로 작성되었습니다.
목차
1. 왜 지금 개편해야 하는가
PHP 버전 지원 현황 (2026년 기준)
| 버전 | 출시 | 지원 종료 | 상태 |
|---|---|---|---|
| PHP 5.6 | 2014 | 2018년 종료 | 완전 폐기 |
| PHP 7.4 | 2019 | 2022년 종료 | 폐기 |
| PHP 8.0 | 2020 | 2023년 종료 | 폐기 |
| PHP 8.1 | 2021 | 2025년 종료 | Security only |
| PHP 8.2 | 2022 | 2026년 12월 | 현재 지원 |
| PHP 8.3 | 2023 | 2027년 12월 | 현재 권장 |
| PHP 8.4 | 2024 | 2028년 12월 | 최신 안정 버전 |
기존 강의의 PHP 5.x 코드는 현재 모든 프로덕션 환경에서 실행 자체가 불가능합니다.
특히 mysql_* 함수는 PHP 7.0에서 완전 제거되어 학습자가 그대로 따라 하면 오류만 발생합니다.
2. 반드시 제거해야 할 레거시 기능
2-1. mysql_* 함수 전체 — 최우선 제거 대상
PHP 7.0에서 완전 삭제된 함수들입니다. 강의 내 모든 예제를 교체해야 합니다.
// ❌ 절대 사용 금지 (PHP 7.0+ 에서 Fatal Error)
$conn = mysql_connect("localhost", "root", "password");
mysql_select_db("mydb");
$result = mysql_query("SELECT * FROM users");
$row = mysql_fetch_array($result);
mysql_close($conn);
// ✅ PDO로 교체 (권장)
$pdo = new PDO("mysql:host=localhost;dbname=mydb;charset=utf8mb4", "root", "password", [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
$row = $stmt->fetch();
// ✅ MySQLi로 교체 (차선책)
$conn = new mysqli("localhost", "root", "password", "mydb");
$conn->set_charset("utf8mb4");
$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
PDO를 권장하는 이유: MySQL뿐 아니라 PostgreSQL, SQLite 등 여러 DB를 동일한 코드로 다룰 수 있어 이식성이 높습니다.
2-2. Short Open Tag <? — 제거
short_open_tag 옵션에 의존하는 코드는 환경마다 동작이 달라집니다.
// ❌ 환경 의존적, 사용 금지
<? echo $name; ?>
// ✅ 항상 표준 태그 사용
<?php echo $name; ?>
// ✅ echo 단축 태그는 PHP 5.4+부터 short_open_tag와 무관하게 항상 사용 가능
<?= $name ?>
2-3. 구버전 슈퍼전역변수 — 제거
PHP 5.4에서 완전 삭제된 변수들입니다.
// ❌ 삭제됨
$HTTP_POST_VARS['name']
$HTTP_GET_VARS['id']
$HTTP_SERVER_VARS['REMOTE_ADDR']
// ✅ 슈퍼전역변수 사용
$_POST['name']
$_GET['id']
$_SERVER['REMOTE_ADDR']
2-4. 클래스 프로퍼티 var 키워드 — 교체
// ❌ PHP 4 스타일 — 가시성(visibility) 명시 없음
class User {
var $name;
var $email;
}
// ✅ 명시적 가시성 키워드 사용
class User {
public string $name;
protected string $email;
private int $id;
}
2-5. 인용부호 없는 배열 키 — 수정
// ❌ PHP 8.0+ 에서 오류 발생
echo $row[name];
echo $_GET[id];
// ✅ 반드시 문자열 키에 따옴표 사용
echo $row['name'];
echo $_GET['id'];
2-6. SQL 직접 삽입 (SQL Injection) — 보안 취약점 제거
강의 내 모든 SQL 예제에 보안 취약점이 있습니다.
// ❌ SQL Injection 취약점 — 절대 사용 금지
$id = $_GET['id'];
$result = mysql_query("SELECT * FROM board WHERE id=$id");
// ✅ PDO Prepared Statement 사용
$id = (int) $_GET['id']; // 타입 캐스팅도 함께
$stmt = $pdo->prepare("SELECT * FROM board WHERE id = :id");
$stmt->execute([':id' => $id]);
$row = $stmt->fetch();
2-7. ereg_* 정규표현식 함수 — 제거
PHP 7.0에서 완전 삭제되었습니다.
// ❌ 삭제됨
ereg("^[a-z]+$", $str);
ereg_replace("[^a-z]", "", $str);
// ✅ PCRE 함수 사용
preg_match("/^[a-z]+$/", $str);
preg_replace("/[^a-z]/", "", $str);
2-8. create_function() — 제거
PHP 8.0에서 완전 삭제되었습니다.
// ❌ 삭제됨
$fn = create_function('$x', 'return $x * 2;');
// ✅ 익명 함수(클로저) 또는 화살표 함수 사용
$fn = fn($x) => $x * 2;
3. 반드시 도입해야 할 현대 기능
3-1. 타입 선언 (Type Declarations) — PHP 7.0+
PHP는 이제 사실상 타입이 있는 언어입니다. 타입 선언은 버그를 사전에 차단하는 가장 효과적인 방법입니다.
<?php
declare(strict_types=1); // 파일 최상단에 반드시 선언
// 매개변수 타입 + 반환 타입
function getUser(int $id): ?array {
// int가 아닌 값이 들어오면 TypeError 발생
}
// 프로퍼티 타입 (PHP 7.4+)
class User {
public int $id;
public string $name;
public ?string $bio = null; // nullable
}
// Union 타입 (PHP 8.0+)
function process(int|string $input): void { }
// Intersection 타입 (PHP 8.1+)
function save(Countable&Iterator $collection): void { }
3-2. Named Arguments — PHP 8.0+
함수 호출 시 매개변수 이름을 명시해 가독성을 높입니다.
// ❌ 순서를 외워야 하는 기존 방식
array_slice($array, 0, 10, true);
// ✅ Named Arguments — 순서 무관, 의미 명확
array_slice(array: $array, offset: 0, length: 10, preserve_keys: true);
3-3. Match 표현식 — PHP 8.0+
switch의 개선된 대안입니다. 엄격한 비교(===)를 사용하고 값을 반환합니다.
// ❌ 기존 switch — 느슨한 비교, fall-through 위험
switch ($status) {
case 1:
$label = '활성';
break;
case 2:
$label = '비활성';
break;
default:
$label = '알 수 없음';
}
// ✅ match — 엄격한 비교, 표현식으로 값 반환
$label = match($status) {
1 => '활성',
2 => '비활성',
default => '알 수 없음',
};
3-4. Nullsafe 연산자 (?->) — PHP 8.0+
중첩된 null 체크를 단순화합니다.
// ❌ 기존 방식 — 중첩 if 지옥
$city = null;
if ($user !== null) {
if ($user->getAddress() !== null) {
$city = $user->getAddress()->getCity();
}
}
// ✅ Nullsafe 연산자
$city = $user?->getAddress()?->getCity();
3-5. Constructor Property Promotion — PHP 8.0+
생성자에서 프로퍼티 선언과 초기화를 동시에 처리합니다.
// ❌ 기존 방식 — 반복 코드
class User {
public int $id;
public string $name;
public string $email;
public function __construct(int $id, string $name, string $email) {
$this->id = $id;
$this->name = $name;
$this->email = $email;
}
}
// ✅ Constructor Promotion — 한 줄로 선언 + 초기화
class User {
public function __construct(
public readonly int $id,
public readonly string $name,
public string $email,
) {}
}
3-6. Enum — PHP 8.1+
마법 상수(define, const 배열)를 대체하는 타입 안전한 열거형입니다.
// ❌ 기존 방식 — 타입 안전성 없음
define('STATUS_ACTIVE', 1);
define('STATUS_INACTIVE', 2);
define('STATUS_PENDING', 3);
// ✅ Enum — 타입 안전, IDE 자동완성 지원
enum UserStatus: int {
case Active = 1;
case Inactive = 2;
case Pending = 3;
public function label(): string {
return match($this) {
self::Active => '활성',
self::Inactive => '비활성',
self::Pending => '대기 중',
};
}
}
$status = UserStatus::Active;
echo $status->label(); // "활성"
3-7. Readonly Properties — PHP 8.1+
불변 값 객체(Value Object) 구현에 필수입니다.
class UserId {
public function __construct(
public readonly int $value,
) {}
}
$id = new UserId(42);
$id->value = 99; // Error: Cannot modify readonly property
3-8. Fibers — PHP 8.1+
비동기 코드 패턴의 기반이 됩니다. (ReactPHP, Amp, Swoole과 연계)
$fiber = new Fiber(function(): void {
$value = Fiber::suspend('첫 번째 중단');
echo "재개 값: $value\n";
});
$result = $fiber->start(); // "첫 번째 중단" 반환
$fiber->resume('안녕하세요'); // "재개 값: 안녕하세요" 출력
3-9. declare(strict_types=1) 습관화
<?php
declare(strict_types=1);
// 이 한 줄이 암묵적 타입 변환을 막아 숨겨진 버그를 사전에 차단합니다.
3-10. Composer와 Autoloading — 필수 도구
PHP 현대 개발의 가장 기초적인 도구입니다. 반드시 강의에 포함해야 합니다.
# 패키지 설치
composer require vlucas/phpdotenv
# 개발 의존성 설치
composer require --dev phpunit/phpunit pestphp/pest
// composer.json — PSR-4 오토로딩 설정
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
3-11. 환경 변수 관리 (.env) — 보안 필수
// ❌ 기존 방식 — 하드코딩된 비밀번호
$conn = mysql_connect("localhost", "root", "1234");
// ✅ .env 파일로 분리
// .env
DB_HOST=localhost
DB_USER=root
DB_PASS=secret
DB_NAME=myapp
// PHP
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
$pdo = new PDO(
"mysql:host={$_ENV['DB_HOST']};dbname={$_ENV['DB_NAME']};charset=utf8mb4",
$_ENV['DB_USER'],
$_ENV['DB_PASS'],
);
3-12. PSR 표준 준수
현업에서 통용되는 PHP 코딩 표준입니다.
| PSR | 내용 | 적용 도구 |
|---|---|---|
| PSR-1 | 기본 코딩 표준 | PHP CS Fixer |
| PSR-2/12 | 코딩 스타일 가이드 | PHP CS Fixer |
| PSR-4 | 오토로딩 표준 | Composer |
| PSR-7 | HTTP 메시지 인터페이스 | Guzzle, Slim |
| PSR-11 | DI 컨테이너 | Laravel, Symfony |
| PSR-15 | HTTP 미들웨어 | Slim, Laminas |
4. 모듈 구조 재설계
기존 구조의 문제점
기존: 개발환경 → 기초문법 → 게시판 만들기 (단순 절차형)
- mysql_* 함수 기반의 절차형 코드만 다룸
- 보안(SQL Injection, XSS 등) 개념 전무
- 객체지향 프로그래밍 미흡
- 테스트, 배포, 현업 워크플로우 없음
- Composer, 프레임워크 등 현대 생태계 미포함
새로운 커리큘럼 구조
1단계 — 개발 환경 (신입 ~ 입문)
| # | 주제 | 핵심 내용 |
|---|---|---|
| 1-1 | PHP란 무엇인가 | PHP 8.x의 위치, 생태계, 사용 사례 |
| 1-2 | 개발 환경 구성 | Docker + PHP 8.3 + MySQL 8 (XAMPP 대신 Docker 권장) |
| 1-3 | 에디터 설정 | VS Code + PHP Intelephense + PHP CS Fixer 자동화 |
| 1-4 | Composer 입문 | 패키지 설치, autoload, vendor/ 이해 |
| 1-5 | 첫 번째 PHP 프로그램 | declare(strict_types=1) 습관 포함 |
2단계 — 기초 문법 (입문 ~ 초급)
| # | 주제 | 핵심 내용 |
|---|---|---|
| 2-1 | 변수와 타입 | 타입 선언, strict_types, 타입 캐스팅 |
| 2-2 | 연산자와 우선순위 | Nullish coalescing (??), Spaceship (<=>) |
| 2-3 | 제어문 | match 표현식, if/else, for, foreach |
| 2-4 | 함수 | 타입 힌트, 반환 타입, 화살표 함수(fn) |
| 2-5 | 배열 | 구조 분해 할당, spread 연산자, array 함수 |
| 2-6 | 문자열 | Heredoc, Nowdoc, str_contains, str_starts_with |
| 2-7 | 에러 처리 | try/catch/finally, Throwable, 사용자 정의 예외 |
3단계 — 객체지향 프로그래밍 (초급 ~ 중급)
| # | 주제 | 핵심 내용 |
|---|---|---|
| 3-1 | 클래스와 객체 | Constructor Promotion, readonly, 가시성 |
| 3-2 | 상속과 인터페이스 | abstract, interface, trait |
| 3-3 | 매직 메서드 | __construct, __toString, __invoke |
| 3-4 | 네임스페이스 | PSR-4, use, 오토로딩 |
| 3-5 | Enum | Backed Enum, 메서드 포함 Enum |
| 3-6 | SOLID 원칙 | 단일 책임, 의존성 역전 원칙 실습 |
4단계 — 데이터베이스 (중급)
| # | 주제 | 핵심 내용 |
|---|---|---|
| 4-1 | PDO 기초 | 연결, Prepared Statement, fetch 모드 |
| 4-2 | PDO 실전 | CRUD 작성, 트랜잭션 |
| 4-3 | SQL Injection 방어 | Prepared Statement의 원리 |
| 4-4 | 데이터베이스 설계 | 정규화, 인덱스, utf8mb4 설정 |
| 4-5 | 마이그레이션 개념 | 수동 SQL 마이그레이션 → Phinx 소개 |
5단계 — 웹 개발 실전 (중급)
| # | 주제 | 핵심 내용 |
|---|---|---|
| 5-1 | HTTP 기초 | 요청/응답, 헤더, 상태 코드 |
| 5-2 | 폼 처리와 보안 | XSS 방어(htmlspecialchars), CSRF 토큰, 입력 검증 |
| 5-3 | 쿠키와 세션 | session_regenerate_id(), 세션 하이재킹 방어 |
| 5-4 | 파일 업로드 | MIME 타입 검증, 파일명 보안, 저장 위치 |
| 5-5 | REST API 기초 | JSON 응답, HTTP 메서드, 상태 코드 설계 |
| 5-6 | 환경 변수 관리 | .env, vlucas/phpdotenv |
6단계 — 현대적 PHP 프로젝트 (중급 ~ 고급)
| # | 주제 | 핵심 내용 |
|---|---|---|
| 6-1 | 라우터 구현 | 직접 구현해보기 → Slim Framework 소개 |
| 6-2 | 미들웨어 패턴 | PSR-15, 인증/로깅 미들웨어 |
| 6-3 | 의존성 주입(DI) | 수동 DI → PHP-DI 컨테이너 |
| 6-4 | 테스트 입문 | PHPUnit, Pest 기초, TDD 개념 |
| 6-5 | 배포 | GitHub Actions / GitLab CI, PHP-FPM + Nginx |
| 6-6 | 보안 점검 | OWASP Top 10 PHP 관점 정리 |
5. Vanilla PHP vs 프레임워크 선택 가이드
학습 관점
Vanilla PHP 먼저 → 프레임워크는 나중
프레임워크가 내부에서 무엇을 하는지 이해하려면 Vanilla PHP 기반 지식이 반드시 필요합니다.
라우팅, DI 컨테이너, ORM의 원리를 모른 채 프레임워크를 배우면 "마법사 신드롬"에 빠집니다.
프레임워크 선택 기준 (2026년 기준)
| Laravel | Symfony | Slim | Laminas | |
|---|---|---|---|---|
| 학습 곡선 | 낮음 | 높음 | 매우 낮음 | 높음 |
| 커뮤니티 | 매우 활발 | 활발 | 보통 | 보통 |
| 국내 채용 수요 | 매우 높음 | 중간 | 낮음 | 낮음 |
| 용도 | 풀스택 웹앱 | 엔터프라이즈 | 마이크로 API | 엔터프라이즈 |
| ORM | Eloquent | Doctrine | 없음(선택) | Laminas DB |
| PHP 최소 요구 | PHP 8.2+ | PHP 8.1+ | PHP 7.4+ | PHP 8.1+ |
강의 적용 권장안
[4단계까지] — 순수 PHP + PDO로 진행
↓
[5단계] — Slim Framework로 라우팅 + REST API 구현
↓
[별도 Laravel 트랙] — Eloquent ORM, Blade, Artisan, Queue 등
Laravel을 선택해야 하는 경우
- 국내 스타트업/중소기업 취업 목표
- 빠른 프로토타이핑이 필요한 프로젝트
- 풀스택 개발자를 목표로 하는 학습자
- 활발한 패키지 생태계(Cashier, Telescope, Horizon 등) 활용
Symfony를 선택해야 하는 경우
- 대기업/금융/공공 프로젝트 목표
- Laravel의 내부 구조를 더 깊이 이해하고 싶을 때 (Laravel이 Symfony 컴포넌트를 다수 사용)
- 컴포넌트 단위로 필요한 것만 골라 쓰고 싶을 때
Vanilla PHP(+ Slim)으로 충분한 경우
- 간단한 REST API 서버
- 레거시 시스템 유지보수
- PHP 내부 원리 학습 목적
- 소규모 사이드 프로젝트
6. 개편 우선순위 로드맵
Phase 1 — 즉시 수행 (긴급)
- [ ]
mysql_*→ PDO/MySQLi 전환 (백업 강의 전체) - [ ] Short tag
<?→<?php교체 - [ ]
$HTTP_POST_VARS등 구버전 슈퍼전역변수 제거 - [ ] SQL Injection 취약 예제 전면 교체
- [ ] 개발 환경을 XAMPP → Docker 기반으로 전환
Phase 2 — 단기 (1~2개월)
- [ ] 타입 선언 +
strict_types예제 전면 도입 - [ ]
var키워드 → 명시적 가시성으로 교체 - [ ] Composer + Autoloading 모듈 신규 추가
- [ ] PDO Prepared Statement 전용 모듈 추가
- [ ] 세션/쿠키 보안 강화 예제 업데이트
Phase 3 — 중기 (2~4개월)
- [ ] OOP 모듈 강화 (Enum, Readonly, Constructor Promotion)
- [ ]
match표현식, Named Arguments, Nullsafe 연산자 추가 - [ ] REST API 모듈 신규 작성
- [ ] PHPUnit/Pest 테스트 기초 모듈 추가
- [ ] GitLab CI 배포 파이프라인 강의 추가
Phase 4 — 장기 (4개월+)
- [ ] Laravel 입문 트랙 신설
- [ ] OWASP Top 10 PHP 보안 모듈 신설
- [ ] PHP 8.4 신기능 (Property Hooks, Asymmetric Visibility) 추가
- [ ] 비동기 PHP (Fibers, ReactPHP 또는 Swoole) 소개 모듈