많은 개발자들이 PHP가 최대의 성능과 함께 최적화되기를 꿈꾼다. 개발자들은 많은 프로젝트에서 시스템 부하나 오류, 속도적인 문제를 만나서 고생하는 경우가 다수 발생한다. 일반적으로 설계 측면이나 개발 측면이 주요 원인이라고 볼 수 있겠지만, 아주 다양한 조건들이 성립돼야 올바른 서비스가 구현되기도 한다. 얼마 전 PHP는 버전 4에서 버전 5로 업그레이드되면서 새로운 도약을 준비하고 있다. 이것은 PHP의 최적화에서 중요한 변수가 될 수 있다. 개발 측면에서 볼 때 OOP(Object Oriented Programming)를 지원하면서 오류 문제를 해결할 수 있을 것으로 본다. PHP는 빠른 속도를 보장한다는 장점이 있지만 이것 또한 개발자의 기본적인 설계와 개발이 보장돼야 가능할 것이다. 여기서는 서비스 개발의 핵심인 설계 측면과 보안 측면, 개발자의 개발 측면, 시스템 운영 측면을 다루기로 한다.
설계적 측면에서 최적화 시스템을 구축할 때 가장 우선시되는 것이 바로 설계이다. 이 설계가 확장적 측면과 개발 내구성에 대해 고려하지 않는다면, 추후 재개발이라는 크나큰 과오를 만나게 된다. 그러지 않으려면 많은 시간을 투자해 설계에 중심을 두고 프로젝트를 진행해야 할 것이다.
올바른 DB 설계 데이터베이스의 설계는 가장 핵심적인 시스템 최적화의 요건이다. 우리는 DB 튜닝에서 프로그램 튜닝이라는 말을 종종 듣는다. 필자는 일전에 튜닝을 전문으로 하는 개발자를 만났는데, 이 튜닝이 얼마나 중요하고 또한 이를 위한 비용이 엄청나다는 것을 알았다. 문제의 사이트는 게시판을 전문으로 서비스하는 업체인데, 데이터량이 1만개를 넘어서면 부하가 많이 걸리고 속도가 떨어지는 문제가 있었다. 이 문제는 DB 관계에서 게시판의 정보를 담고 있는 테이블을 하나 추가하고 SQL 쿼리 문을 바꿈으로써 해결했다. 여기서 우리는 작은 설계하나가 확장성을 고려하지 않음으로써 얼마나 많은 재개발 비용이 발생하는가를 볼 수 있다.
프로젝트라는 것이 그렇듯이 처음 진행과 나중에 고객의 요구를 재반영했을 때의 형태는 50%가 넘게 바뀌어 있는 것을 보게 된다. 한 예로 초기 데이터를 모으는 테이블을 설계했는데 처음엔 15개의 필드였다가 프로젝트가 끝나고 나니 32개의 필드가 되어 있었다. 다행히 초기 데이터 테이블이라서 확장이 가능했지만 중간에 밀접하게 결합되어 있는 테이블이었다면 손을 쓰기가 곤란했을 것이다.
DB 서버와의 분리 서버를 구성하는 데 DB를 중요하게 사용하는 사이트라면 반드시 DB 서버와의 분리를 권장하고 있다. 즉 프로그램 소스와 데이터를 분리시키는 것이다. DB에서 무거운 쿼리를 던지게 되면 시스템의 부하가 많이 나타난다. 이런 경우 DB와 프로그램을 분리시켜서 부하를 나누는 것도 좋은 방법이다.
<그림 1>의 경우 발생될 수 있는 상황을 생각해 보자. 먼저 DB가 두 개로써 비용이 2배로 발생하게 된다. 또한 DB의 내용이 같다면 DB의 동기화도 문제가 될 수 있다. <그림 1>과 같은 사항은 오히려 두 개의 독립적인 서비스를 하면서 서로 링크로 서비스를 하는 개념에는 적합할 수 있으나, 서비스를 하나로 하는 사이트에서 분리 정책으로 만든 것이라면 문제가 발생될 소지가 높다.

<그림 1> 두 개의 웹 서버와 DB 서버를 사용하는 경우
<그림 2>를 살펴보자. <그림 2>는 우리가 쉽게 범할 수 있는 실수이기도 하지만 잘 적용하면 괜찮을 것 같은 서비스이기도 하다.

<그림 2> 하나의 웹 서버와 DB 서버를 같이 사용하는 웹 서버
이 시스템 구성은 하나의 DB와 웹 서버를 같이 사용하고, 또 다른 독립적인 웹 서버를 사용하는 경우이다. 실제로 이러한 사이트를 구축한 사례가 있었는데, 원래 처음 서비스는 DB와 웹 서버를 사용하고 있다가 시스템이 커지면서 하나의 웹 서버를 더 구축해 로드밸런싱을 시도했다. 하지만 로드밸런싱이 실제로 원활하게 이뤄지지 않는 문제가 발생했다. 왜냐하면 A 고객은 웹 서버에 접속하여 서비스를 하고, B 고객은 DB와 웹 서버에 접속돼 서비스를 받게 되는데 실제로 두 명의 고객의 웹 처리 속도가 달랐기 때문이다. 이것은 DB는 일정한 자원을 공유하여 서비스를 하고 있지만, DB가 있는 웹 서버는 데이터베이스의 로드된 시스템 자원을 제외하고 서비스를 하기 때문에 부하가 걸렸던 것이다.
이 시스템 구조는 DB를 전문으로 사용하는 프로그램과 자체로 처리되는 프로그램을 분리해 사용한다면 적합할 것이다. DB를 사용하는 고객은 웹 서버에 접속해 DB와 웹 서버의 서버로 옮겨가서 서비스를 받기 때문에 앞단의 웹 서버에는 부하를 덜 수 있다. 그렇다면 <그림 3>의 시스템 구조는 어디서 어울릴 수 있을까? 데이터베이스를 많이 사용하는 사이트에 적합하다고 볼 수 있다.

<그림 3> 하나의 DB 서버와 하나의 웹 서버
실제로 데이터베이스를 적극 활용하게 된다면 시스템 리소스를 엄청나게 가져간다. MS SQL의 예를 들면 동적 메모리에서 시스템의 자원 95% 이상을 점유해 DB 서비스를 최적화하려고 한다. 이렇게 했을 때 원활한 웹 서비스를 하기가 어렵다. 이와 같이 데이터베이스만을 위한 서버를 따로 준비해 두고 웹 서비스를 운영한다면 데이터베이스가 가지는 부담을 분리시킴으로써 원활한 서비스를 할 수 있을 것이다. 앞서 보았듯이 시스템 설계는 해당 서비스가 어떻게 구성되느냐에 따라 많은 차이점이 나타난다. 고객이 원하는 주서비스가 무엇인지. 메인 프로세스가 어떻게 기동돼야 하는지를 잘 구분해 시스템을 설계해야 할 것이다.
서버간의 분리 정책 서비스가 방대해지기 시작하면 서버들이 늘어나게 된다. 여기서도 우리는 분리 정책과 설계에 중심을 두어야 한다. 간단한 예를 들어보자. 사이트가 기본으로 DB를 핵심적으로 사용하면서 파일 다운로드 서비스를 자주 한다고 가정하자. 즉, 이 서비스는 웹 사이트에서 로그인한 후 사용자가 애플리케이션을 다운로드해 계속 DB와 통신하면서 정보를 주고받고 또한 이 정보에 의해 데이터를 다운받는다. 처음에는 하나의 서버에서 운영하다가 결국 과부하가 심하게 걸려서 서버를 두 대로 확장하려고 했으나, 다시 심사숙고한 끝에 결정한 결과가 <그림 4>와 같이 DB와 파일 서버를 분리시킨 것이다.

<그림 4> 각 서버를 분리한 모습
이렇게 함으로써 고객 애플리케이션의 통신과 DB와의 부담을 DB 서버가 가져가고 다운로드로 걸리는 웹 서버의 부하를 파일 서버가 가져가므로 안정적인 서비스가 가능하다. 여기서 우리가 주목해야 할 부분은 서비스의 용도와 시스템의 부하를 예측하고 설계하는 방법이다. 만일 서버를 두 대로 분할하면 어떻게 될까? DB 서버와 다운로드 서비스의 부하가 분명히 웹 서비스의 핵심적인 문제로 발생될 것이다. 이렇듯 설계는 시스템 최적화의 초석이라는 것을 알 수 있다.
보안적 측면에서 최적화 보안 문제가 웹 서비스의 화두로 나온지 오래다. 하지만 기본적인 보안 사항도 고려되지 않은 사이트가 아직도 많이 있다. 보안적인 안정화는 자칫 방심하면 엄청난 문제가 발생할 수도 있다. 실제로 웹 서비스를 제공하는 사이트는 로그인이나 게시판의 정보가 흐르는 로직을 해킹당해 손해를 보는 경우가 많다. 기초적이지만 보안적인 옵션들과 방법을 준비해 적용해야만 이후에 있을 문제에 대응할 수 있다. 특히, PHP나 서버의 보안 패치는 주기적으로 점검해야만 한다.
세션 vs. 쿠키 잘 알다시피 세션은 서버에서 생성돼 사용자의 로그인 후 사용을 보장하는 기술이다. 쿠키 또한 마찬가지로 로그인 후 사용을 보장하지만 세션은 서버에서 생성해 가지고 있고, 쿠키는 클라이언트에서 로그인 정보를 가지고 있다는 점이 다르다. 일반적으로 보안 문제를 위해 세션 사용을 권유하고 있다. 서버에서 사용자의 정보를 다루는 게 더 안정적이기 때문이다. 하지만 대용량 서비스(사용자가 많은 서비스)를 개발할 때는 서버의 부하가 큰 문제일 수 있다. 대용량 서비스를 할 때는 일반적으로 상용 보안 서비스를 사용하지 않는다면 쿠키를 사용해 서버의 부하를 줄이는 것도 하나의 방법일 것이다.
전역 변수 처리 전역 변수는 PHP에서도 보안상 치명적인 결함을 가지고 있다는 판단에 기본적으로 막고 있는 방법이다. 일반적으로 프로그램을 진행할 때 이러한 불편함 때문에 보안상 결함을 풀어놓는 경우가 많다. 하지만 정보가 중요하게 다뤄지는 곳에서는 반드시 이러한 문제를 고려해야 한다. 전역 변수의 옵션과 관련된 프로그램을 모듈화해 처리하는 방법도 개발 속도 개선에 도움이 될 것이다.
파일 업로드 보안 파일 업로드가 보안 문제의 화두로 떠오른 적이 있다. 이것은 필자도 한번 해킹(?)해 본 경험으로 파일 업로드에 실행가능한 코드를 업로드시켜서 다운로드 주소로 호출하면 업로드 프로그램이 실행된다. 이러한 문제를 막기 위해 개발자들은 다양하게 개발 옵션을 시도하고 있다. 먼저 서버에서 해당 디렉토리 실행 권한을 막는 방법을 들 수 있겠다.
웹 서버 컨트롤 파일에서 httpd.conf나 .htaccess 파일을 수정해 업로드된 파일이 저장되는 디렉토리에 php_engine off하면 프로그램이 해석되지 않는다. 다음은 매뉴얼에 나와 있는 코드이다. Example 5-4. More secure file name checking
<?php $username = $_SERVER[‘REMOTE_USER’]; // using an authentication mechanism $homedir = “/home/$username”;
if (!ereg(‘^[^./][^/]*$’, $userfile)) die(‘bad filename’); //die, do not process
if (!ereg(‘^[^./][^/]*$’, $username)) die(‘bad username’); //die, do not process //etc... ?>
SSL 처리 일반적으로 폼에서는 어떤 언어든지 암호화되지 않고 전송된다. 암호화는 전송받은 값을 받은 후에 그것을 가지고 가공하는 것이라고 볼 수 있다. 보통 SSL(Secure Socket Layer)을 사용하는데 결재 관련 정보들은 SSL로 81번 포트를 이용해 전송한다. SSL은 기본으로 프로토콜 차원에서 보안해 주는 개념이다. 일반적으로 https://로 사용되며 http://보다는 훨씬 안정적인 보안 기능을 수행하고 있다. 크게 어려운 설정 부분이 아니므로 로그인이나 개인정보 입력시에는 SSL을 사용하는 것을 권한다.
암호화 처리 암호화를 하는 방법은 다양하다. 사용자의 정보 전송을 위해 사용하는 방법으로 금융권에서는 SEED 방식을 채택하고 있고, 일반적으로 DES(Data Encryption Standard)도 많이 사용한다. PHP에서 가장 간단하게 사용할 수 있는 방법은 md5이다. 물론 md5가 안정성이라고 말하고 싶지는 않다. 하지만 최소한 암호화되지 않은 원문 데이터보다는 안정될 것이다. 암호화 관련해서는 깊이 있는 학습이 이뤄져야 한다. 자세한 정보는 보안 관련 사이트에서 정보를 얻기 바란다. | |