본문 바로가기
Code/PHP

Hello World, Again: 해킹을 딛고 다시 쓰는 2026년 PHP 개발기

by CoLife 2026. 3. 24.

오랜만에 새로운 공간에서 인사를 드립니다.

기존에 운영중이던 블로그가 안타깝게도 해킹을 당해 복구할 수 없게 되었습니다. 수년간 쌓아온 기록과 삽질의 역사들이 한순간에 날아간 것은 뼈아프지만, 이참에 백지상태에서 제 개발 인생을 다시 한번 정리해 보자는 마음으로 새 블로그를 열었습니다.

다시 시작하는 첫 글의 주제는, 제 개발 커리어의 시작이자 여전히 현재 진행형인 PHP입니다.

🌅 "지는 해", 그리고 "싸구려 언어"라는 인식

IT 업계에서 PHP는 참 재미있는 위치에 있습니다. 수년 전부터 "PHP는 지는 해"라는 말을 귀에 못이 박이도록 들어왔고, 누군가는 "배우기 쉬운 언어", "초보자들이나 쓰는 싸구려 언어"라며 깎아내리기도 합니다.

과거의 PHP가 그저 웹페이지에 동적인 요소를 조금 뿌려주는 스크립트 언어 취급을 받았던 것은 사실입니다. <?php 태그 안에 HTML과 비즈니스 로직, DB 쿼리가 한 덩어리로 뒤엉켜 있던 스파게티 코드를 떠올리면 그런 비판도 어느 정도 이해는 갑니다.

Evolution: DB 연결 코드로 보는 진화의 역사

하지만 언어의 평판이 제자리에 머무는 동안, PHP 생태계와 제 코드 스타일은 쉼 없이 진화했습니다.

저 역시 모든 것이 하나의 파일에 담겨 위에서 아래로 흐르던 '레거시 순서 지향' 코드로 개발을 시작했습니다. PHP의 변화를 가장 직관적으로 느낄 수 있는 DB 연결 방식의 변화를 보면 그 과정이 명확히 보입니다.

 

1. 혼돈의 시대 (mysql_query) 과거에는 모든 것이 날것(Raw)이었습니다. 전역 연결을 사용했고, SQL 인젝션(Injection)에 속수무책으로 당하곤 했던 아찔한 시절의 코드입니다.

<?php
// PHP 5.5에서 deprecated, 7.0에서 삭제된 추억의 함수들
$conn = mysql_connect("localhost", "root", "password");
mysql_select_db("my_database");

// $_GET 값을 그대로 쿼리에 때려 넣던 야생의 시절...
$result = mysql_query("SELECT * FROM users WHERE id = " . $_GET['id']);
$user = mysql_fetch_assoc($result);
?>

 

2. 과도기 (mysqli_query) 보안의 중요성이 대두되면서 mysqli가 등장했습니다. 객체 지향 스타일을 지원하고 Prepared Statement를 사용할 수 있게 되었지만, 여전히 코드는 장황했고 절차지향적 습관을 버리지 못한 경우가 많았습니다.

<?php
$conn = mysqli_connect("localhost", "root", "password", "my_database");

// Prepared Statement 도입으로 보안은 좋아졌지만, 바인딩 과정이 꽤 번거로웠습니다.
$stmt = mysqli_prepare($conn, "SELECT * FROM users WHERE id = ?");
mysqli_stmt_bind_param($stmt, "i", $id);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
?>

 

3. 현재 (PDO + PHP 8 Strict Types) 그리고 현재, 2026년의 우리는 **PDO(PHP Data Objects)**와 PHP 8의 문법을 결합하여 훨씬 안전하고 우아한 코드를 작성합니다. declare(strict_types=1)를 통해 데이터 타입을 엄격하게 강제하고, 에러는 Exception으로 우아하게 처리합니다.

<?php
declare(strict_types=1);

namespace App\Database;

use PDO;
use PDOException;

class UserRepository
{
    public function __construct(private PDO $pdo) {}

    // 반환 타입(?array)과 매개변수 타입(int)을 명확히 지정
    public function findUserById(int $id): ?array
    {
        try {
            // Named parameter를 사용하여 가독성과 안정성 확보
            $stmt = $this->pdo->prepare('SELECT * FROM users WHERE id = :id');
            $stmt->execute(['id' => $id]);
            
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result ?: null;
            
        } catch (PDOException $e) {
            // 에러 로깅 후 처리
            error_log($e->getMessage());
            throw new \RuntimeException('Database error occurred.');
        }
    }
}
?>

 

과거엔 숫자가 들어가야 할 곳에 문자가 들어가도 PHP가 알아서(때로는 엉망으로) 처리해 주었지만, 이제는 TypeError를 발생시키며 런타임 이전에 개발자의 실수를 단호하게 잡아냅니다.

🚀 우리가 여전히 PHP를 선택하는 진짜 이유: "압도적인 생산성"

현대적인 문법을 차치하더라도, 현업에서 PHP를 주력으로 사용하는 가장 큰 이유는 따로 있습니다. 바로 아이디어를 비즈니스 가치로 구현해 내는 압도적인 속도입니다.

새로운 서비스를 기획하고, 프로토타입을 만들어 시장의 반응을 보고, 빠르게 피드백을 반영하여 프로덕션 레벨로 끌어올리는 과정에서 PHP만큼 생산성이 높은 언어는 드뭅니다. 우아하고 완벽한 코드를 짜느라 타이밍을 놓치는 것보다, 안정적이고 검증된 생태계(Laravel, Symfony 등) 위에서 비즈니스의 문제를 가장 빠르게 해결하는 것. 그것이 제가 생각하는 개발자의 핵심 역량이며, PHP는 이를 위한 최고의 무기입니다.

🏁 다시, "code & life"

기존 블로그의 데이터는 사라졌지만, 그동안 쌓아온 제 머릿속의 경험과 삽질의 기록들은 고스란히 남아있습니다.

과거의 낡은 코드를 버리고 엄격하고 우아한 코드로 리팩토링하듯, 이 공간도 이전보다 더 깊이 있고 단단한 이야기들로 채워나가겠습니다. 다시 한번, 잘 부탁드립니다.

그밖에 캠핑과 기타, 여행, 테크관련 이야기도 올릴 예정입니다.