푸념

오랜만에 블로그를 쓴다.

회사의 주력 프로젝트에 집중하느라 너무 바빠서 글을 쓰지 못했다. 스트레스가 크면 집에서 쉴 때도 뭔가 생산적인 활동을 하기는 어렵다. 나중에 해야지하고 쌓아둔 개인 프로젝트와 쓰려고 제목만 써 둔 글이 산더미다.

그런 압박 속에서도 키보드를 붙들게 만드는 일이 있다.

이번 주에는 급하게 진행하게 된 외주 작업이 생겼다. 사용자들이 상품평을 남기는 간단한 웹 사이트를 만드는 것인데 오픈 예정일이 코앞이라 순식간에 만들어주어야 하는 과제였다.

기간이 급박한만큼 익숙하고 빠르게 개발할 수 있는 장고(Django)로 개발하려 했다. 데이터 구조도 간단하고 기능도 적고 주로 관리자용 페이지로 구성된 시스템이라 요구사항만 보면 좋은 프로젝트였다. 장고로 개발하면 5일도 안 걸릴 작업 같았다. 그런데 클라이언트 업체와 미팅을 해 보니 클라이언트 측이 PHP만 다룰 수 있다고 PHP로 개발해 줄 것을 요청하는 것이 아닌가. 5일이 15일로 늘어나는 순간이었다. PHP는 웬만해서는 건들고 싶지 않다. 내가 PHP를 잘 못 쓰기 때문이기도 하지만 PHP로 작업된 프로그램 중에는 너무 낡은 코드가 많기 때문이다. 스크립트 언어인데도 디버깅 하기는 왜 그렇게 힘이 든지…

그래도 새로운 사이트를 개발하는 것이고 모던 PHP라는 패러다임도 있는 만큼 새 출발을 올바르게 한다면 낡은 코드는 문제가 되지 않을 것 같았다. 나는 PHP 웹 프레임워크 중 현대적이고 장고와 비슷한 기능을 갖춘 라라벨(Laravel)을 이용해 개발해 주기로 했다. 다만 클라이언트가 웹 사이트를 배포할 서버 정보는 그 미팅에서 주지 않았고 다음에 알려준다고 했는데…

사실 라라벨은 몇 번 구경만 해 봤고 제대로 배우거나 써 본 적이 없었기 때문에 작업할 준비를 위해 바로 자료를 찾아보았다. 고맙게도 라라벨 공식 문서가 한국어로 번역돼 있었다. 하지만 공식 문서는 입문자에게는 설명이 좀 친절하지 않은 편이었고 너무 딱딱하게 번역된 면도 있었다. 입문용으로는 구 버전 기준으로 작성된 영문 튜토리얼 문서가 더 쉽고 도움이 됐다.(구글 검색하면 상단에 나온다.) 그걸 먼저 보고 한국어 매뉴얼을 보니 이해하기 좋았다. 라라벨은 마이그레이션 문법, 엘로퀀트 ORM, 페이커(faker)를 이용한 더미 데이터 생성(seeding) 기능, 깔끔한 템플릿 엔진 등을 갖추고 있었다. 기능이 풍부할 뿐 아니라 매우 깔끔하게 정돈되어 있어서 PHP 같은 느낌이 안 들고 보면 볼수록 정이 갔다. 이 정도라면 PHP도 개발할 맛이 나겠다는 생각이 들었다. 나는 기분 좋게 데이터 모델을 설계했다. 몇 시간만에 모델/마이그레이션/더미 데이터 생성기를 만들 수 있었다. 이 정도면 장고와 비교해도 손색이 없다는 생각이 들었다.

한참 라라벨과 기분 좋은 한 때를 보냈는데, 오늘 클라이언트로부터 서버 접속 정보를 받고는 눈 앞이 아득해 졌다. 일단 서버에는 FTP와 phpMyAdmin으로만 접속이 가능했다. SSH 접속 권한도 달라고 요청했으나 처음에는 서버 관리자가 SSH가 무엇인지조차 모른다며 내 요청 자체를 이해하지 못했다. 회의가 있다며 계속 통화를 피하더니 한참 뒤에야 SSH 접속은 보안상 허가해줄 수가 없다고 한다. 헐. 매우 황당하고 화가 났다. 게다가 서버에는 PHP로 만들어진 다른 웹사이트가 이미 구동중이었고 그 위에 PHP 프로그램을 짜 넣어서 새 웹사이트를 만들라고 하는 것이었다. 구동중인 웹사이트는 매우 낡고 지저분하게 코딩되어 있었으며 불필요한 파일들(“삭제할 폴더1” 같은)이 여기저기 섞여 있어 보기만해도 악취가 진동했다. DB도 이상하게 설계돼 있었고 MySQL 기본 인코딩 설정이 스웨덴어(?????) 문자셋으로 되어 있었다. 한 DB 안에도 테이블마다 문자셋이 뒤죽박죽 달랐다. PHP 설치 정보를 확인해보니 10년전 쯤에 릴리즈됐을 법한 (찾아보니 실제로는 6년전이긴 하다) 5.2.17 버전이 설치돼 있었다. SSH 접속이 불가하고 관리자 권한도 없으니 아파치 웹 서버 설정을 건드리는 것조차 할 수 없었다. phpMyAdmin으로 접속하라고 준 MySQL 계정에는 데이터베이스 생성 권한도 없었다. 그나마 테이블 생성 권한이 있으니 이걸로 하면 되긴 하지만.

도무지 이런 환경에서 작업할 엄두가 나지 않아서 새 서버를 요청했지만 고작 한달에 5,500원하는 가상서버호스팅 비용이 아깝다는 것과 기존 웹사이트의 DB와 추후 통합할 것을 염두에 두고 있다는 이유로 거절됐다. 잠깐만, 기존의 낣은 웹사이트를 앞으로도 계속 쓰겠다는 것이고 더 확장할 생각까지 있다는 것인가? 나는 그 웹사이트는 만든지 10년은 더 된 것 같은데 이제 그만 포기하시라고 말했다. 놀랍게도 만든지 3년도 안 된 거라고 한다. 이럴 수가?

낡은 PHP 환경에서 쓸 만한 프레임워크

아무튼 이 서버에서는 라라벨을 사용하겠다는 생각은 사치스런 망상에 불과했다.

어쩔 수 없이 프레임워크를 쓰지 않고 직접 A-to-Z PHP 개발을 해야할 것 같았다. 예전에 그렇게 작업한 적도 있지만 그걸 다시 하려고 하니 생각할수록 이건 잘못된 일이라는 생각이 들었다. MySQL 쿼리 함수를 직접 만들 수는 있지만 이게 기간 내에 할 수 있는 일인지, SQL 인젝션 방지 같은 보안 이슈는 또 언제 다 처리할 것인지, 일일이 CRUD 코드를 짜는 건 또 얼마나 번거로울지, JOIN 연산은 언제 또, 내가 생각못한 이슈는 또 얼마나 많을까 … 생각할 수록 답답한 것이다. 옛날엔 몰라서 신경 안 쓴 것들도 있지만 지금도 그렇게 할 수는 없지 않겠는가.

궁한 상황에서 머리를 굴려 보니 시간이 없다 하더라도 라라벨 말고 다른 라이브러리라도 빠르게 배워서 쓰는게, 차라리 더 빠르고 코드 품질도 더 좋지 않을까하는 생각이 들었다. 좀 구식이라고 듣긴 했지만 라라벨 못지 않게 유명하고 한국에서 많이 쓰는 코드이그니터(CodeIgniter)를 찾아보았다. PHP 필요 버전 5.3.7, 권장 버전 5.6이다. 헐 이 서버에서는 이것도 못 돌린다. 그 다음으로 케익PHP(CakePHP)를 찾아보았다. PHP 필요 버전 5.5.9다. 당연히 이것도 안 된다.

아. 결국 직접 바퀴를 발명해야 하는 것인가. 한없이 어두운 내 표정을 보고 동료가 말을 걸었다. “코드이그니터 옛날 버전이라도 쓰면 어때요?” 흠, 그렇군. 코드이그니터 버전 2를 살펴보았다. 일단 PHP 필요 버전은 5.1.6. 사용 가능. 순간 너무 기뻐서 만세를 불렀다. 하지만 이것만으로 되는 것은 아니다. 서버의 아파치 웹 서버 설정(내가 바꿀 수 없다)과 맞는지, MySQL 서버와 맞는지, 쓸만한 놈인지 등도 알아봐야 했다. 2시간 정도 이것저것 알아보고 튜토리얼을 해 보고 간단한 기능을 작성해 보니 이 서버에서도 (일단은) 실행이 되고 쓸 만하다는 걸 알게 됐다. 많은 기능은 없지만 간단하고 빠른 개발이 가능한 것 같다. 물론 좀 더 써보고 살펴봐야 알겠지만.

예상 개발기간이 5일에서 15일으로, 15일에서 불가능으로, 불가능에서 다시 8일 정도로 줄어든 드라마틱한 한 주였다.

프레임워크별 비교

프레임워크 요구 PHP 최소 버전
라라벨 4.2 5.4
라라벨 5.3 5.6.4
케익PHP 3.3 5.5.9
코드이그니터 2 5.1.6
코드이그니터 3 5.3.7

그리고 PHP 7에서 mysql.so 확장 사용하기

이 서버와 호환 되는 로컬 개발 환경을 갖추는 것도 만만한 일이 아니었다. 아파치 웹 서버를 설치해서 작업용 컴퓨터의 리소스를 낭비해야 하기 때문만은 아니었다. 진짜 문제는 내 작업용 컴퓨터에는 PHP 7이 설치돼 있는데 PHP 7에서는 mysql.so 확장이 삭제됐다는 점이었다. (PHP 7에서는 mysql.so 대신 mysqli.so가 지원된다. 그 전까지는 mysqli.so와 mysql.so가 같이 지원이 됐고, mysql.so를 쓰면 보안 경고가 발생했다.) 코드이그니터 2는 mysql.so 확장을 쓰기 때문에 PHP 7 버전에서는 실행이 안 된다!

만일 로컬 환경을 갖추지 못하면 FTP로 번번히 서버에 PHP 프로그램을 전송한 후 테스트를 해야 하는 판이었다. 게다가 SSH 가 안 돼서 아파치 웹 서버 로그도 볼 수 없다!

로컬 환경과 배포 환경을 비슷하게 맞추는 건 매우 중요한 일이기 때문에, 리눅스를 다 지우고 옛날 우분투 배포판이라도 깔아서 작업을 할까하는 생각을 잠깐 했다. 아니면 번거롭더라도 버추얼박스를 써야 하는 것일까? 한참 고민을 하고 있는데, 이번에도 지혜로운 직장 동료가 “그냥 mysql.so를 다운로드해서 쓰면 안 돼요?”라고 하는 것이다. PHP 7 환경에 맞게 컴파일 된 녀석을 구할 수 있을까요… 라고 답하는 도중에 응? 그냥 컴파일을 직접 하면 되잖아? 하는 생각이 스쳤다. 그래서 찾아보니 과연 방법을 찾을 수 있었다.

이 방법은 https://ckon.wordpress.com/2015/08/06/put-mysql-functions-back-into-php-7/ 에 설명된 방법이다.

먼저 https://github.com/php/pecl-database-mysql 소스코드를 클론한다.

git clone https://github.com/php/pecl-database-mysql mysql --recursive

아래 명령을 차례로 입력해 컴파일을 하고

cd mysql
phpize
./configure
make

관리자 권한으로 설치를 한다.

sudo make install

그러면 라이브러리가 설치된 경로가 터미널에 출력된다. 내가 사용중인 만자로 리눅스의 경우에는 사용자 디렉토리 아래($HOME/mysql/mysql.so)에 설치되던데, 리눅스 환경마다 설치되는 곳이 다른 듯하다.

라이브러리 파일이 위치한 경로를 확인한 후, php.ini 파일을 수정한다. 만자로 리눅스에서는 /etc/php/php.ini 파일이다.

sudo vi /etc/php/php.ini

extension 들이 있는 곳 중간에 extension=/home/bakyeono/mysql/mysql.so 와 같이 로드할 확장 라이브러리 파일 경로를 적어주면 된다.

/etc/php/php.ini
================

...
extension=/home/bakyeono/mysql/mysql.so
...

이렇게 하고 httpd(또는 apache2)를 재시작해주면 PHP 7에서도 코드이그니터 2가 잘 실행되었다.

sudo systemctl restart httpd.service

도커를 쓰면 이런 문제도 해결이 되려나, 아마 힘들 것 같긴 하다. 시간 날 때 알아봐야겠다.

낡은 PHP 코드는 세월호 같은 것이다

아직 끝난 건 아니지만 큰 위기는 넘긴 것 같다. 앞으로도 위험성은 있겠지만 작업 자체가 불가한 상황은 넘겼으니까. 이번 작업을 하면서 간단한 작업처럼 보였던 게 손을 대는 곳마다 무섭게 무너져내리는 걸 보면서 얼마나 가슴 졸였는지 모르겠다. 다음에는 이런 작업은 미리 눈치 채고 피하고 싶다. 그게 내 뜻대로 되는 건 아니지만 말이다.

어떻게 3년도 안 됐다는 웹 사이트가 이렇게 낡았을 수 있을까? 서버 업데이트는 안 한지 5년도 넘은 것 같고(설치 후 한 번도 안 한 것이 아닐까 의심스럽다.) 서버를 자체 보유/운영중이라고 말하지만 그럴리 없다. 서버 한 대로 수십 개의 사이트를 운영하는 업자의 눈속임에 속은 것이 아닐까 의심이 된다. 실제로 그런 서버를 몇 번 본 적이 있다. 아마 이번 클라이언트의 서버 관리자도 그래서 SSH 접속을 못 하게 하는 것 같다. 그게 뭔지 모르겠다는 낯 뜨거운 거짓말까지 하면서 말이다. 유지보수도 힘들고 생산성도 떨어지고 보안상 위험하기 짝이 없는 이런 웹사이트를 한가득 실은 정체불명의 서버에 이런 낡은 웹 사이트를 만든 업체들이 지금도 어디선가 또 다른 사이트를 찍어내고 있을 것 같다.

한국 웹에는 위험성이 잔뜩 쌓인 웹 사이트들이 그럴듯한 외관으로 도장만 대충 한 채로 운용되고 있다. 내부를 조금만 살펴보면 곳곳에 녹이 슬어 썩었다. 수명이 다한 배를 사서 불법 증축을 하고 선원들의 경고를 무시한 채 터무니없는 과적으로 운행하다 가라앉고 만 세월호. 선원들은 저임금과 고용 불안에 시달리는 비정규직 노동자들이었다. 아무도 타고 싶지 않은 배에 올라야 했던 그 선원들을 나는 비난하고 싶지는 않다. 저질 웹의 바다에서 개발자의 명예와 자긍심을 빼앗긴 채 새로운 것을 배울 돈도 시간도 없이 허덕이는 개발자들이라고 다를까. 그들이 한국 웹 환경을 구조할 수 있을까. 배운 건 가만히 있는 방법 뿐이다.