nemorize.me
  • # PHP

내가 (거의) 모든 곳에 PHP를 사용하는 이유

2025년 01월 10일 18시 36분 | 완독까지 약 11분

나는 PHP를 오래 전부터(4.0) 지금까지 계속 사용해오고 있다. 1~3버전을 기억하던 선배님들은 하룻강아지로 보겠지만, 요즘같은 세상에 PHP를 십수년간 사용했으면 오래 사용했다고 생각한다.

이 글을 통해 내가 왜 오랜기간 PHP를 사용했고, PHP를 계속 사용할 예정인지 담담하게 풀어보려고 한다. PHP를 찬양하거나, 그 외의 언어들을 폄하하고자 하는 목적이 아님을 미리 밝혀둔다. (심지어 개발자들이 공감하고 납득할만한 이유를 들지도 않는다. 그저 나의 개인적인 이유를 나열할 뿐인 글임을 다시 한번 밝힌다.)

Javascript와 Typescript

현대의 웹 개발 시장에서 JS와 TS는 빼놓을 수 없는 이 시장의 큰 획 중 하나다. 그들과 Python에게 밀려 노년을 쓸쓸하게 보내고 있는 PHP를 논하려면, 먼저 이 둘이 애호되는 이유를 살펴보아야 한다.

JS/TS(이후 TS 생략) 진영의 사람들은 프론트와 백을 하나의 언어로 작성할 수 있다는 점을 큰 장점으로 든다. 나도 동의한다. 특히 X엔드에서 작성한 타입을 그대로 가져와 Y엔드에서 사용할 수 있다는 점은 생산성 증진에 아주 큰 역할을 한다. 이러한 장점을 극대화 하기 위한 tRPC 같은 제품이 대히트를 치고 있는데 말해 뭐하겠는가.

서버리스 아키텍쳐가 대두되면서 JS는 더 큰 관심을 받았다. 물론 대다수의 서버리스 플랫폼들이 여러가지 언어를 지원하지만 그 중에서도 JS가 단연 탑이었다. Google Cloud Function, AWS Lambda, Azure Functions, 좀 더 최근에는 Cloudflare Workers, Vercel, Deno Deploy 등등 사실상 모든 서버리스 (함수) 플랫폼은 JS를 메인으로 제공한다. 그 전부터 JS의 흥행이 시작되었고, 거기에 서버리스 아키텍쳐 내지는 MSA 아키텍쳐의 부상과 함께 이러한 플랫폼들의 지원까지 겹쳐 더더욱 큰 생태계를 만들어 나가고 있다.

이런 JS에 대한 여러 기대감이 흐르는 시장 속에서 PHP는 특출난 장점을 만들어 내지 못하고 있다. 프론트엔드에서 바로 사용할 수 있는 타입을 내보내지도 못하고, JS만큼 자유로운 표현을 기대하지도 못하며, 서버리스 함수 플랫폼에서 PHP를 사용하려면 PHP 런타임이 포함된 컨테이너를 만들어 사용하거나, babel을 통해 JS로 변경해 사용해야 하는 등의 불편함을 감수해야 한다.

모놀리식과 마이크로 서비스

최근 MSA가 대두되기 시작했다. 아주 간략하게 축약하면 "하나의 제품을 만드는 데에 필요한 여러 기능들을 잘게 쪼개 각각의 서비스로 배포하는 아키텍쳐" 정도가 될 것이다. 이는 특히 각 기능들의 사용 빈도가 다르거나, 코스트가 다를 때 아주 유용하다. "필요한 만큼만 사용하고, 원하는 만큼 확장하여, 사용한 만큼만 지불한다"는 서버리스 아키텍쳐가 탄생한 이유도 사실상 MSA의 존재 때문이라고 봐도 무방하다.

대부분의 케이스에서 MSA는 오버엔지니어링이고, 모놀리식이 더 유리하다는 아주 합리적인 주장을 많은 사람들이 펼치지만, 개발자의 마음이 항상 합리적으로 작동하는 것은 아니다. MSA는 화끈하고, 멋있고, 개발자의 지적/창조적 욕구를 충족시켜주는 백엔드 패턴 중 1위라고 해도 무방할 것이다.

PHP는, 특히 현대 모던 PHP는 MSA와 대척점에 존재한다 표현해도 무방할 정도로 그 생태계가 MSA보다는 모놀리식 아키텍쳐에 치우쳐있다. MSA의 장점 중 하나라고 이야기하는 "언어 선택의 자유로움"은 프로그래밍 언어의 선택에 한정된 이야기다. 조금 억지를 부려 Visual Basic 6으로 MSA를 만들라고 하면, 설령 기술적으로 불가능하지 않더라도 누가 그런 선택을 하겠는가. PHP가 정확히 그런 위치에 놓여있다. 가장 대중적인 Laravel은 태생적으로 RoR을 닮은 풀스택 프레임워크고, MSA에 이용되기를 바라지 않는다. Symfony도 마찬가지다. 물론 심포니는 Laravel에 비해 각 컴포넌트의 결합도가 높지 않아 MSA에 조금 더 근접할 여지가 있지만, 마찬가지로 MSA로 사용하는 경우가 많지 않다.

PHP 특유의 납득하기 싫은 API들

PHP를 평가절하하는 제일 큰 이유는 "보안"이다. GET, POST를 전역변수로 노출시키거나, 밑도 끝도 없이 터져나오는 취약점은 PHP의 최대 단점 중 하나였으나, 출시된지 10년도 더 된 구버전(~5.x) 시절의 이야기이니 여기서는 다루지 않겠다.

이제는 충분히 해결되었다 볼 수 있는 보안 문제를 제외하고서도, PHP에는 고질적인 문제가 존재한다. 아직까지 PHP를 사용하는 사람들도 대책이 있다고 반론할지언정 완전히 부정하는 것은 불가능한, 아주 안타까운 문제다.

이미 유명해질대로 유명해져 PHP에 관심이 전혀 없는 개발자들도 봤을법한 explode() implode()는 PHP 개발자들의 발작 버튼이다. array_* 함수들의 시그니처도 대단하다. array_filter(array, callable) array_find(array, callable) 등 대다수의 함수는 배열이 앞에 오지만 array_map(callable, array) 의 경우 배열이 뒤로 간다. 물론 그들만의 이유가 존재하기는 한다. "이러이러한 기능을 구현하려면 이러이러한 형태여야 했어요" 라고 주장하고, 그 이유라면 어느정도 이해는 간다. 애초에 그 기능이 꼭 필요했는가를 논외로 했을 때.

PHP의 태생은 라스무스 러도프가 C로 작성하기 귀찮아서 그때 그때 필요한 기능들을 모아둔 나사 수십개가 빠진 코드 뭉치에 가깝다. 지금의 PHP 메인테이너가 어떠한 사람이나 그룹이건, PHP가 프로그래밍을 싫어하는 라스무스 러도프의 자식인 이상 PHP는 프로그래머의 시각에서 정상적으로 보이기 쉽지 않을 것이다.

제일 타입 안전하지만, 타입 기능이 제일 부족한 언어

인기있는 인터프리팅 스크립트 언어 중 PHP가 제일 타입 안전하다. PHP, Javascript, Python, Ruby, Perl 등등 중 런타임 타입 체크를 제공하는 스크립트 언어는 PHP가 유일하다. 물론 런타임 타입 체크의 존재 여부를 타입 안전하다고 표현하는 것은 잘못된 표현임을 알지만, 대충 넘어가 주기를 바란다.

어찌되었든 PHP는 다른 언어들보다 타입 검증에 조금 더 진심이다. 런타임 타입 체크를 제공하고, declare(strict_types=1); 지시자를 통해 인터프리터 언어들 특유의 암시적인 자동 형변환을 금지할 수도 있다.

그러나 PHP의 세계관에서 타입은 단순한 수준에서 그친다. 정수, 문자열, 부울과 같은 원시 타입들과 단순한 클래스의 조합 이외의 타입을 지원하지 않는다. 그러니까, 제네릭이나 TS의 객체 타입(내지는 interface)같은 존재를 전혀 바랄 수 없다는 것이다. 물론 PHPStan과 같은 정적 타입 분석 툴이 phpdoc을 사용해 복잡한 타입을 지정하고 분석할 수 있도록 하지만, 정말 맛이 없다.

그런데도 나는 왜 계속 PHP를 사용하는가?

지금까지 다들 알고 있는 PHP의 단점들만 나열했다. 이렇게 나열하고 보니 지금까지 PHP를 쓰고 있는 내가 참 미련해 보인다. 스캇 마니아라는 멸칭이 붙어도 반박하지 못할 것 같다.

나는 개인적인 프로젝트부터 업무를 위한 프로젝트까지, 내가 기술 스택을 선택할 권한이 있는 프로젝트에서는 시기 불문 거의 모두 PHP를 사용했다. 초등학교를 다니던 시기에는 간단한 웹사이트를 제작했고, 중학교를 다니던 시기에는 PHP로 게임서버를 만들어 대회에 참가해 수상하기도 했다. PHP를 사용해 임베디드 기기를 제어하는 클라이언트를 만들기도 했다. 고등학생이 되어서는 Git 클라이언트나 앱 빌드 서버와 같은 것들을 PHP로 만들어 얼마 되지 않지만 실제로 금전적인 이득을 보기도 했다.

물론 PHP만 사용한 것은 아니다. 프론트엔드의 시점에서는 전통적인 PHP 템플릿 렌더링을 사용하더라도 Bower, Webpack과 같은 JS 생태계를 활용했고, Angular 이후의 React 등이 인기를 끈 이후로는 React, Svelte를 사용했고, 지금도 사용하고 있다. 최근에는 특히 RN을 자주 사용하고 있다. 백엔드의 시점에서는 상황에 따라 JS(Node), Python, Go를 PHP와 함께 병행 사용하고 있다. PHP의 성능이 좋지 못하던 4~5버전 시절에는 C를 사용해 PHP 익스텐션을 만들어 쓰기도 했다.

다른 언어들을 선택할 시간과 기회가 충분히 있었고, 또 PHP 이외의 언어의 경험이 없는 것도 아니다. 그럼에도 내가 계속 PHP를 사용하는 이유는 대체 뭘까?

익숙함

일단 익숙함이 제일 크다. 다른 개발자들이 보기엔 새로운 문물에 적응하지 못한 도태된 스캇 매니아 정도로 볼테고, 부정할 수 없는 사실이긴 하다. 만약 내가 PHP가 아닌 다른 언어를 먼저, 더 오래 사용했다면 후술할 다른 이유들이 존재함에도 불구하고 PHP를 선택하지 않았을 것이다.

단순함

내가 말하는 단순함이란 단순히 언어가 쉽고 간략하다는 것이 아니다. PHP를 안전하게 사용하려면 오히려 다른 언어들보다 조금 더 까다롭다. 위에서 한번 언급한 것과 같이 PHP는 보안에 취약했다. 그 시절에 PHP를 안전하게 사용하려면 PHP가 가진 결함을 충분히 이해해야 했으며, 지금은 무분별한 라이브러리들에서 자신을 지키기 위해 라이브러리들의 취약점을 충분히 확인해야 한다.

내가 말하는 단순함은 플랫폼으로서의 PHP에게 적용되는 이야기다.

단순한 구조

위에서 언급했던 서버리스 아키텍쳐를 생각해보자. 우리는 이것을 90년대에 이미 만나봤다. 근본적으로 서버리스 함수는 CGI와 다를바가 없다. "필요한 만큼 확장하고, 쓴 만큼 지불한다"는 개념이 빠져있지만, 다시 한번 더 생각해보자. PHP라는 언어에 한정하여 본다면 이건 결국 "종량제 PHP 웹호스팅" 아닌가?

PHP를 사용하면 서버리스 함수를 만들어 사용하기 위해 특정 플랫폼에 종속될 필요도 없고, 그 종속에서 벗어나기 위해 수많은 레이어를 추가할 필요도 없다. 전 세계 어디에나 아주 많이 존재하는 웹호스팅 서비스 중 하나를 골라 결제하고, 아주 자연스러운 PHP 코드를 작성하기만 하면 된다. DB를 깔끔하게 사용하기 위해 커넥션 풀 프록시를 도입할 필요도 없다.

단순한 배포

모놀리식이든 MSA든 CGI로 작동하지 않는 언어들은 심리스한 무중단 배포를 위해 꽤 많은 고생을 해야한다. 무거운 CI 워크플로를 작성해야 하며, 새로운 버전의 코드가 완전히 부팅되기 전까지 기존 인스턴스를 중지하지 않고 있다 부팅이 완료된 후 인스턴스를 교체해야 한다. 이러한 것들을 자동으로 처리해주는 좋은 도구가 많이 만들어졌지만, PHP는 더 간단하다.

리모트 Git 서버에 push 하고, 서버에서 pull 하기만 하면 된다. 웹훅을 사용하면 더 간단하다. 웹훅 이벤트가 들어오면 git pull 커맨드를 자동으로 실행해주는 아주 간단한 코드 몇 줄이면 무거운 CI/CD 서버를 구동하지 않고도 아주 자연스럽고, 아주 안전하게 무중단 업데이트가 가능하다.

단순한 내 성향

프론트엔드로의 타입 공유는 JS 진영의 제일 탐나는 무기이기는 하나 단순한 구조와 배포를 포기해야 할 정도로 탐나지는 않는다. 모노레포든 다른 어떠한 형태의 구성이든 서로의 타입을 공유하기 위해 이런저런 세팅을 해야하고, 안전하게 버전 관리를 해주어야 한다. 그것들을 도와주는 도구가 존재하지만, 타입 공유만을 위해 그 많은 레이어를 추가하고 설정하는 것은 적어도 "내가 사용하는 범위 내에서는" 낭비에 가깝다.

내가 최근 1년 내 작업한 제품 중 제일 많은 사용자가 모인 서비스는 두 달만에 MAU 50만을 달성하고 그 이후로도 꾸준히 동일한 성적을 기록하고 있는, 호주에서 운영되는 서비스다. 웹은 React, 앱은 RN으로 작성했다. 물론 백엔드는 PHP만으로 이루어져 있다. 이 서비스를 제작하는데 소요된 시간은 3주 남짓이다. 내 프로젝트들은 디자인/개발/1차마케팅까지 평균 1개월, 길어야 3개월 정도를 잡는다. 그 이상 소요되는 프로젝트는 내가 흥미를 느끼지도 못하고, 내가 잘 다루는 분야도 아니라 수주를 받지 않는 편이다.

이런 내 성격상 세팅에 하루 이상 걸리는 워크플로는 시간 낭비일 수 밖에 없다. 계속해서 신경을 써 주어야 하는 구조는 정신력 낭비일 수 밖에 없다. 그것이 어떤 장점을 주더라도, 내가 관여하고 있는 진척도 수준에선 차라리 수동으로 명령어 입력하는게 더 유리하다.

생산성

나는 라스무스 러도프가 그러하듯 프로그래밍을 좋아하지 않는다. 이 블로그의 메인 페이지에서 볼 수 있듯 나는 "문제를 해결하는 것" 그 자체를 좋아하지, "프로그래밍으로" 문제 풀기를 좋아하거나, 깔끔하고 멋있는 설계를 기반으로 기술적으로 대단한 프로그램을 작성하는 것을 좋아하는 것이 아니다. 오히려 싫어하는 편이다.

나는 20살에 30만원짜리 PC만을 가지고 1인 사업을 시작해 만족할만한 수익을 달성하기까지의 4년간 어떠한 인건비도 지출하지 않았다. 기획, 디자인, 개발, 마케팅, 행정, 세무 업무까지 모두 혼자서 처리했다. 물론 그 이후로는 내 손을 타지 않아도 괜찮은 코드, 디자인, 행사 등에 한해 외주를 주거나 단기간 고용하여 처리한다.

이러한 나에게 있어 멋들어진 아키텍쳐나 언어가 제공하는 고급 기능들은 내 관심사가 아니다. 내게는 고객이(또는 내가) 기획한 서비스를 빠르게 시장에 출시하고, 빠르게 시장의 검증을 받고, 대중이나 경영진에게 충분한 가치를 인정받는 것이 중요하다. 내게 필요한 것은 아주 빠듯한 일정 내에 적당히 안전히 설계되고, 적당히 유지보수하기 편리하고, 눈에 띄는 취약점이 없는 적당한 코드다.

적절한 시장 검증이 끝나면 그 이후는 내 알 바가 아니다. 어차피 그 때가 되면 더 세심히 고려된 기획을 담아 더 적절한 환경에서, 나와는 다르게 개발에 조금 더 진심인 개발자들이 그들의 진심을 담아 새롭게 작성할 것이다. 다른 PHP 스타트업들은 그 때가 되면 Java Spring으로 넘어간다고들 한다.

PHP는 이런 내게 제일 적합한 언어라고 생각한다.

준수한 성능

단기간 내 시장검증에 실패해 기술적 퍼포먼스 개선과 기획 개선이 동시에 시행되어야 하는 상황이 오기도 한다. PHP는 성능이 꽤 좋은 편이다. Opcache나 JIT을 지원하는 버전을 사용한다면 웬만한 상황에서 PHP의 성능은 문제가 되지 않는다.

다만 가끔 사람이 많이 몰리는 이벤트를 기획하거나 하여 요청 하나 하나가 아쉬운 상황이 오기도 한다. 나는 퍼포먼스 개선이 필요한 상황이 오면 Swoole이나 Workerman같은 솔루션을 사용한다. 일반적으로 사용되는 (Fast)CGI 형태가 아닌 다른 일반적인 언어가 구현하는 것 처럼 포트를 직접 열어 요청을 처리하는 형태의 솔루션이다. 기존 코드를 모던 PHP 스타일에 맞게 작성했다면, 스무줄 내외의 코드를 추가하는 것만으로 수배에서 수십배의 퍼포먼스를 확인할 수 있다.

"처음부터 사용하면 됐던거 아니냐"라고 반문할 수 있지만, 위에서 언급했던 단순한 배포의 장점을 포기해야 한다. 성능은 나의 PHP 선택에 있어 큰 지분을 차지하지 않기에 이러한 기능은 최대한 늦게, 최후의 보루로, 또 필요할 때 잠깐만 사용하는 용도로 남겨놓는 편이다.

어찌되었든 결과적으로 퍼포먼스 문제에 자유로워졌고, 나는 기획과 구현에 더 집중할 수 있는 환경을 얻었다.

결론

나는 프로그래머가 아니다. 프로그래머가 아닌 내게 그것의 익숙함과 단순함, 높은 생산성, 그러면서도 준수한 성능을 제공해주는 PHP는 그것의 단점을 감수하고서라도, 스캇 매니아라고 불리는 불명예를 감수하고서라도 선택할 가치가 있다.

단지 그것 뿐이다.

이러한 상황이 아닌 정말 프로그래밍이 즐거운 당신에게 PHP는 거대하고 악명높은 똥덩어리에 지나지 않을 것이다. 난 그들의 평가를 존중한다. 그만큼 그들도 나를 스캇 매니아라고 부르는 것을 자제해 주었으면 한다. 차라리 코끼리박이가 더 힙스터스럽지 아니한가.